Capricorn 76
These Lua tutorials demonstrate how to initialise the physics engine.

Starting up the physics engine

---------------------------
---------------------------
-- Tutorial: Physics engine. Test 1
-- Starting up the physics engine.
--
-- Copyright (c) 2006-2008 Capricorn 76 Pty. Ltd.
---------------------------
---------------------------

---------------------------
---------------------------
-- PROGRAM STARTS HERE
---------------------------
---------------------------

---------------------------
-- Initialise the graphics engine, using a software renderer.
-- Then initialise the physics engine.
---------------------------
local graphicsInitialised = IGraphics:init( 'SOFTWARE', -- Instead of using hard-coded strings, we could IApp:loadScript('constantsVideoDrivers.e76script') and use the pre-defined constants.
                                640, 480,       -- Width/height
                                false,          -- Fullscreen
                                16,         -- Bits/color depth
                                false,          -- Shadows
                                false,          -- Antialiasing
                                false,          -- VSync
                                30,         -- Frame rate
                                false);     -- Silent errors are off, so ScriptENGINE will raise an error is something's not right

local physicsInitialised = IPhysics:init(       1,          -- Adaptive solver model
                                1,          -- Adaptive friction model
                                0.5,            -- Default static friction
                                0.4,            -- Default dynamic friction
                                0,          -- Min mass. Any entities with a mass  < this are not simulated
                                1000,           -- Max mass, Any entities with a mass  > this are simulated as static bodies
                                true,           -- Optimise 3D meshes when loading
                                50,         -- Physics frame rate. Should be as high as possible to give the physics engine plenty of samples when simulating collisions etc.
                                false);     -- Silent errors are off, so ScriptENGINE will raise an error is something's not right


if (graphicsInitialised and physicsInitialised) then

    ---------------------------
    -- Run the app processing loop for 5 seconds
    ---------------------------
    IApp:run(5000);

    ---------------------------
    -- Close the engine, the window will close, and the program will terminate
    ---------------------------
    IPhysics:destroy();
    IGraphics:destroy();
end

Create a box and give it mass

---------------------------
---------------------------
-- Tutorial: Physics engine. Test 2
-- Starting up the physics engine, create a box and give it mass.
--
-- Create a 3D camera, floor and box directly in script.
-- Normally, you would use the ScriptENGINE World Editor to create your 3D worlds, then use IWorld:load() to load them in.
--
-- Copyright (c) 2006-2008 Capricorn 76 Pty. Ltd.
---------------------------
---------------------------

---------------------------
---------------------------
-- PROGRAM STARTS HERE
---------------------------
---------------------------
---------------------------
-- Initialise the graphics engine, using OPENGL.
-- If you try to use the software renderer, you'll find that the graphics engine is using a lot of CPU, which slows the physics.
-- So, only use software rendering when absolutely necessary, but always try to use hardware acceleration for the graphics.
-- Then initialise the physics engine.
---------------------------
local graphicsInitialised = IGraphics:init( 'OPENGL',       -- Instead of using hard-coded strings, we could IApp:loadScript('constantsVideoDrivers.e76script') and use the pre-defined constants.
                                640, 480,       -- Width/height
                                false,          -- Fullscreen
                                16,         -- Bits/color depth
                                false,          -- Shadows
                                false,          -- Antialiasing
                                false,          -- VSync
                                30,         -- Frame rate
                                false);     -- Silent errors are off, so ScriptENGINE will raise an error is something's not right

local physicsInitialised = IPhysics:init(       1,          -- Adaptive solver model
                                1,          -- Adaptive friction model
                                0.5,            -- Default static friction
                                0.4,            -- Default dynamic friction
                                0,          -- Default elasticity
                                0,          -- Min mass. Any entities with a mass  < this are not simulated
                                1000,           -- Max mass, Any entities with a mass  > this are simulated as static bodies
                                true,           -- Optimise 3D meshes when loading
                                50,         -- Physics frame rate. Should be as high as possible to give the physics engine plenty of samples when simulating collisions etc.
                                false);     -- Silent errors are off, so ScriptENGINE will raise an error is something's not right


if (graphicsInitialised and physicsInitialised) then
    ---------------------------
    -- At this point, you might add some resource folders to the ScriptENGINE filesystem.
    -- ScriptENGINE will search its filesystem when loading scripts, 3D models, textures etc...
    -- In you final programs, you should copy the ScriptENGINE constants files into your own program folders, so they'll be distributed with your program...
    ---------------------------
    IApp:addSearchPath('../../Common/Models');
    IApp:addSearchPath(IApp:getExeFilePath() .. './Constants'); -- IApp:getExeFilePath() returns the path to the ScriptENGINE.exe

    ---------------------------
    -- Load some constants into our script
    ---------------------------
    IApp:loadScript(IApp:getExeFilePath() .. '/Scripts/constantsMaterialTypes.e76script');

    ---------------------------
    -- Create the camera, so we can view the world
    ---------------------------
    local cameraId = IWorld:createCamera();         -- Create a camera entity (but it's still not added to the world yet)
    IWorld:setEntityPosition(cameraId, '0 5 -10');      -- 3D Vectors are formatted as 'X Y Z'
    IWorld:setCameraLookAt(cameraId, '0 0 0');          -- Make the camera look at the origin
    IWorld:addCamera(cameraId);                 -- Add the camera to the world

    ---------------------------
    -- Create the floor
    -- Use an ScriptENGINE unit.
    -- Units are used for non-animated entities (like buildings, floors etc).
    -- Use ScriptENGINE agents for with 3D animated models like skeletal (.X) and morph (.MD2) models
    ---------------------------
    local floorId = IWorld:createUnit();                    -- Create a unit entity (but it's still not added to the world yet)
    IWorld:setEntityModelName(floorId, 'plane.x');          -- Set the 3D model used to graphically display the unit.
    IGraphics:setEntityMaterialType(floorId, -1, MAT_SOLID);    -- Set the graphical material type to 'solid',
    IGraphics:setEntityTextureName(floorId, 0, -1, 'floor.png');    -- Asiign a texture to the unit
    IWorld:setEntityScale(floorId, '10 1 10');              -- Make the unit bigger

    -- This is the line that asks the physics engine to simulate the unit.
    -- It's at the engine's max defined mass, so will be simulated as a static body.
    -- Static bodies are simulated with high detail, using the entity's 3D faces.
    -- Compare with dynamic entities that use bounding boxes, ellipses or complex hulls
    IPhysics:setEntityMass(floorId, 1000);
    IWorld:addUnit(floorId);                            -- Add the unit to the world

    ---------------------------
    -- Create the box
    -- Use an ScriptENGINE unit.
    ---------------------------
    local boxId = IWorld:createUnit();                  -- Create a unit entity (but it's still not added to the world yet)
    IWorld:setEntityModelName(boxId, 'cube.x');             -- Set the 3D model used to graphically display the unit.
    IGraphics:setEntityMaterialType(boxId, -1, MAT_SOLID);      -- Set the graphical material type to 'solid',
    IGraphics:setEntityTextureName(boxId, 0, -1, 'crate.jpg');  -- Asiign a texture to the unit
    IWorld:setEntityPosition(boxId, '0 5 0');               -- Change the unit's position

    -- This is the line that asks the physics engine to simulate the unit.
    -- It's between the engine's min/max defined mass, so will be simulated as a dynamic body.
    -- By default, ScriptENGINE will use a bounding box...
    IPhysics:setEntityMass(boxId, 10);
    IWorld:addUnit(boxId);                          -- Add the unit to the world

    -- Start simulating entity.
    -- When entities are at rest, the physics engine will stop simulating them (by default). This setting is controllable via the IPhysics interface
    -- The physics engine will automatically restart the entity's simulation when it interacts in a collision, has a force/torque applied, or you call activateEntity()
    IPhysics:activateEntity(boxId);

    ---------------------------
    -- Run the app processing loop for 5 seconds
    ---------------------------
    IApp:run(5000);

    ---------------------------
    -- Close the engine, the window will close, and the program will terminate
    ---------------------------
    IPhysics:destroy();
    IGraphics:destroy();
end

Load a 3D scene from disk

---------------------------
---------------------------
-- Tutorial: Physics engine. Test 3
-- Starting up the physics engine, creating a box and giving it mass.
--
-- Load a 3D scene from disk. We saved the scene from Test 2...
-- Add a force and torque to the box.
--
-- Copyright (c) 2006-2008 Capricorn 76 Pty. Ltd.
---------------------------
---------------------------

---------------------------
---------------------------
-- PROGRAM STARTS HERE
---------------------------
---------------------------
---------------------------
-- Initialise the graphics engine, using OPENGL.
-- If you try to use the software renderer, you'll find that the graphics engine is using a lot of CPU, which slows the physics.
-- So, only use software rendering when absolutely necessary, but always try to use hardware acceleration for the graphics.
---------------------------
local graphicsInitialised = IGraphics:init( 'OPENGL',       -- Instead of using hard-coded strings, we could IApp:loadScript('constantsVideoDrivers.e76script') and use the pre-defined constants.
                                640, 480,       -- Width/height
                                false,          -- Fullscreen
                                16,         -- Bits/color depth
                                false,          -- Shadows
                                false,          -- Antialiasing
                                false,          -- VSync
                                30,         -- Frame rate
                                false);     -- Silent errors are off, so ScriptENGINE will raise an error is something's not right

local physicsInitialised = IPhysics:init(       1,          -- Adaptive solver model
                                1,          -- Adaptive friction model
                                0.5,            -- Default static friction
                                0.4,            -- Default dynamic friction
                                0,          -- Default elasticity
                                0,          -- Min mass. Any entities with a mass  < this are not simulated
                                1000,           -- Max mass, Any entities with a mass  > this are simulated as static bodies
                                true,           -- Optimise 3D meshes when loading
                                50,         -- Physics frame rate. Should be as high as possible to give the physics engine plenty of samples when simulating collisions etc.
                                false);     -- Silent errors are off, so ScriptENGINE will raise an error is something's not right


if (graphicsInitialised and physicsInitialised) then
    ---------------------------
    -- At this point, you might add some resource folders to the ScriptENGINE filesystem.
    -- ScriptENGINE will search its filesystem when loading scripts, 3D models, textures etc...
    -- In you final programs, you should copy the ScriptENGINE constants files into your own program folders, so they'll be distributed with your program...
    ---------------------------
    IApp:addSearchPath('./Common/Models');
    IApp:addSearchPath(IApp:getExeFilePath() .. './Constants'); -- IApp:getExeFilePath() is the path to the ScriptENGINE.exe

    ---------------------------
    -- Load some constants into our script
    ---------------------------
    IApp:loadScript(IApp:getExeFilePath() .. '/Scripts/constantsMaterialTypes.e76script');

    ---------------------------
    -- Load the 3D world instead of creating all the entities here.
    -- Use the ScriptENGINE World Editor to create your 3D worlds.
    -- The Editor also generates a worldIds.e76script with all your entity identifiers.
    ---------------------------
    IWorld:load('./', 'worldData');
    IApp:loadScript('worldIds');    -- This script was created by the ScriptENGINE World Editor, and holds all the entity Ids in the world.

    ---------------------------
    -- Add a force and torque to the box
    ---------------------------
    IPhysics:addEntityImpulseForce(idUnit_box, '1000 1000 0');
    IPhysics:addEntityImpulseTorque(idUnit_box, '0 1000 0');

    ---------------------------
    -- Run the app processing loop for 5 seconds
    ---------------------------
    IApp:run(5000);

    ---------------------------
    -- Close the engine, the window will close, and the program will terminate
    ---------------------------
    IPhysics:destroy();
    IGraphics:destroy();
end

Add a force to the box using physics raycasts

---------------------------
---------------------------
-- Tutorial: Physics engine. Test 4
-- Performing physics raycasts.
--
-- Load a 3D scene from disk. We saved the scene from Test 2...
-- Add a force to the box using physics raycasts to determine the intersection point.
--
-- Copyright (c) 2006-2008 Capricorn 76 Pty. Ltd.
---------------------------
---------------------------

---------------------------
-- Mouse button subscriber callback function
---------------------------
function OnMouseClick(eventType, mouseX, mouseY, mouseWheel, userData)
    ---------------------------
    -- Left button clicked?
    ---------------------------
    if (IMouse:leftButtonClicked(eventType)) then
        -- Use the 'Filter' version of this function to only raycast Units.
        -- Multiple entity types can be filtered by adding the unit types...
        local entityHit = IPhysics:rayCastMousePositionFilter(IWorld:getUnitTypeId());

        -- If an intersection is found, ScriptENGINE will return a Lua table holding the entity id, and the intersection point.
        if (entityHit) then
            local entityId  = entityHit['entity'];
            local intersection  = entityHit['intersection'];

            -- Add a force to the entity, but not at its centre-of-mass.
            -- Instead, we add the force at an offset position, defined by the raycast intersection.
            IPhysics:addEntityImpulseForceOffset(entityId, '0 0 5', IMisc:vectorSubtract(intersection, IWorld:getEntityPosition(entityId)));
        end

        return true; -- Handled event
    end
end

---------------------------
---------------------------
-- PROGRAM STARTS HERE
---------------------------
---------------------------

---------------------------
-- Initialise the graphics engine, using OPENGL.
-- If you try to use the software renderer, you'll find that the graphics engine is using a lot of CPU, which slows the physics.
-- So, only use software rendering when absolutely necessary, but always try to use hardware acceleration for the graphics.
---------------------------
local graphicsInitialised = IGraphics:init( 'OPENGL',       -- Instead of using hard-coded strings, we could IApp:loadScript('constantsVideoDrivers.e76script') and use the pre-defined constants.
                                640, 480,       -- Width/height
                                false,          -- Fullscreen
                                16,         -- Bits/color depth
                                false,          -- Shadows
                                false,          -- Antialiasing
                                false,          -- VSync
                                30,         -- Frame rate
                                false);     -- Silent errors are off, so ScriptENGINE will raise an error is something's not right

local physicsInitialised = IPhysics:init(       1,          -- Adaptive solver model
                                1,          -- Adaptive friction model
                                0.5,            -- Default static friction
                                0.4,            -- Default dynamic friction
                                0,          -- Default elasticity
                                0,          -- Min mass. Any entities with a mass  < this are not simulated
                                1000,           -- Max mass, Any entities with a mass  > this are simulated as static bodies
                                true,           -- Optimise 3D meshes when loading
                                50,         -- Physics frame rate. Should be as high as possible to give the physics engine plenty of samples when simulating collisions etc.
                                false);     -- Silent errors are off, so ScriptENGINE will raise an error is something's not right


if (graphicsInitialised and physicsInitialised) then
    ---------------------------
    -- At this point, you might add some resource folders to the ScriptENGINE filesystem.
    -- ScriptENGINE will search its filesystem when loading scripts, 3D models, textures etc...
    -- In you final programs, you should copy the ScriptENGINE constants files into your own program folders, so they'll be distributed with your program...
    ---------------------------
    IApp:addSearchPath('./Common/Models');
    IApp:addSearchPath(IApp:getExeFilePath() .. './Constants'); -- IApp:getExeFilePath() is the path to the ScriptENGINE.exe

    ---------------------------
    -- Load some constants into our script
    ---------------------------
    IApp:loadScript(IApp:getExeFilePath() .. '/Scripts/constantsMaterialTypes.e76script');

    ---------------------------
    -- Load the 3D world instead of creating all the entities here.
    -- Use the ScriptENGINE World Editor to create your 3D worlds.
    -- The Editor also generates a worldIds.e76script with all your entity identifiers.
    ---------------------------
    IWorld:load('./', 'worldData');
    IApp:loadScript('worldIds');    -- This script was created by the ScriptENGINE World Editor, and holds all the entity Ids in the world.

    ---------------------------
    -- Subscribe to mouse clicks. ScriptENGINE will call our callback function when the user clicks the mouse
    ---------------------------
    local subMouse = IEvents:subscribeMouseButton('OnMouseClick');

    ---------------------------
    -- Add a force and torque to the box
    ---------------------------
    IPhysics:addEntityImpulseForce(idUnit_box, '1000 1000 0');
    IPhysics:addEntityImpulseTorque(idUnit_box, '0 100 0');

    ---------------------------
    -- Run the app processing loop for ever. User has to manually close the window.
    ---------------------------
    IGraphics:createText('ctlLabel', 'Click the box to perform a physics raycast. A force will be applied at the intersection point. Close the window when you\'re finished', '0.05 0.05 0.95 0.1', false, true, false, '1 1 1 1');
    IApp:run();

    ---------------------------
    -- Always unsubscribe when your finished handling events
    ---------------------------
    IEvents:unsubscribe(subMouse);

    ---------------------------
    -- Close the engine, the window will close, and the program will terminate
    ---------------------------
    IPhysics:destroy();
    IGraphics:destroy();
end

Copyright © 2006-23 Sep 2009 Capricorn 76 Pty. Ltd. (created on Wed Sep 23 16:49:12 2009)