Am I using applyTorque incorrectly in Craft?

Hello, Everyone.

I’ve come back to Codea Craft using a different approach to my projects; instead of attaching a camera to my objects and moving the objects by moving the attached camera, I’m using Craft.physics to apply forces and torques to objects and have the camera move and track the Craft 3D objects that have moved. AppyForce seems to work fine, but I can’t seem to get applyTorque to move my Craft objects with attached rigid bodies (please see attached video). Right now I’m just trying to rotate the crab object left and right by applying torque to the Y axis (Crab.up axis). Here is my code; I appreciate anyone’s suggestions, thanks!

viewer.mode=FULLSCREEN

function setup()
    rectMode(CENTER)
    scene = craft.scene()
    -- turn off gravity
    scene.physics.gravity = vec3(0,0,0)
    -- background free download from: https://images.gamebanana.com/img/ss/mods/1873a.webp
    scene.sky.material.envMap = craft.cubeTexture(asset.SeaSky)
    
    --    setup 3D models (all availalbe online as free downloads)  
    -- island credit to Herminio Nieves; available at: https://www.cgtrader.com/items/843619/download-page
    Island = scene:entity()
    Island.model = craft.model(asset.Small_Tropical_Island.Small_Tropical_Island)
    Island.scale = vec3(1,1,1)
    Island.worldPosition = vec3(-480,-75,-50)
    Island.eulerAngles = vec3(0,90,0)
    Island:add(craft.rigidbody, STATIC)
    Island:add(craft.shape.model, Island.model)
    
    -- crab available at: http://3dmag.org/en/market/item/1590/
    Crab = scene:entity()
    Crab.model = craft.model(asset.crab.Crab_obj)
    Crab.worldPosition = vec3(-360, -45, 90)
    Crab.scale = vec3(25,25,25)
    CrabRigidBody = Crab:add(craft.rigidbody, DYNAMIC)
    Crab:add(craft.shape.model, Crab.model)
    
    -- chest available at: https://www.turbosquid.com/3d-models/3d-treasure-chest-low-poly-pbrt-1875139#
    Chest = scene:entity()
    Chest.model = craft.model(asset.Chest.Chest)
    Chest.worldPosition = vec3(-320,-45,90)
    Chest.scale = vec3(0.2,0.2,0.2)
    Chest:add(craft.rigidbody, STATIC)
    Chest:add(craft.shape.model, Chest.model)
    
    --   Ocean model available at: https://creazilla.com/nodes/41918-sea-and-ocean-set-3d-model
    Ocean = scene:entity()
    Ocean.model = craft.model(asset.ocean_sim)
    Ocean.material = craft.material(asset.builtin.Materials.Standard)
    Ocean.material.diffuse = color(81,102,130)
    Ocean.scale = vec3(0.6,0.8,0.6)
    Ocean.worldPosition = vec3(1,1,1)
    Ocean.eulerAngles = vec3(0,0,0)
    Ocean:add(craft.rigidbody, STATIC)
    Ocean:add(craft.shape.model, Ocean.model)
    
    --  Put camera behind Crab
    followCrab()

    -- Test parameter on sidescreen to rotate camera to see crab 
    parameter.action("MoveCrabLeft",changeObject)
    parameter.action("MoveCrabRight", changeObject)
    parameter.action("MoveCrabForward", changeObject)
    parameter.action("MoveCrabBackward", changeObject)
    parameter.action("MoveCrabUp", changeObject)
    parameter.action("MoveCrabDown", changeObject)
    parameter.action("RotateCrabLeft", changeObject)
    parameter.action("RotateCrabRight", changeObject)
end

function draw()
    update(DeltaTime)
    scene:draw()
end

-- updates physics when updates(dt)
function update(dt)
    scene:update(dt)
    followCrab()
end

function changeObject(object)
    if object == "MoveCrabLeft" then
        CrabRigidBody:applyForce(Crab.right *50)
    end
    if object == "MoveCrabRight" then
        CrabRigidBody:applyForce(-Crab.right *50)
    end
    if object == "MoveCrabForward" then
        CrabRigidBody:applyForce(Crab.forward *50)
    end
    if object == "MoveCrabBackward" then
        CrabRigidBody:applyForce(-Crab.forward *50)
    end
    if object == "MoveCrabUp" then
        CrabRigidBody:applyForce(Crab.up *50)
    end
    if object == "MoveCrabDown" then
        CrabRigidBody:applyForce(-Crab.up *50)
    end
    if object == "RotateCrabLeft" then
        CrabRigidBody:applyTorque(Crab.up *1000)
    end
    if object == "RotateCrabRight" then
        CrabRigidBody:applyTorque(-Crab.up *1000)
    end
end

function followCrab()
    scene.camera.worldPosition = Crab.worldPosition
    scene.camera.rotation = Crab.rotation
    scene.camera.worldPosition = scene.camera.worldPosition - (scene.camera.forward *60)
    scene.camera.worldPosition = scene.camera.worldPosition + (scene.camera.up *15)
end

https://youtu.be/KND-bPKp39I

@SugarRay Here’s an example I put together showing applyTorque. Tap the screen to start the torque. The torque gets applied each draw cycle in the update function. So you have to start and stop the torque or else it will continue to accumulate.

viewer.mode=FULLSCREEN

function setup()
    fill(255,0,0)
    assert(OrbitViewer, "Please include Cameras as a dependency")
    scene = craft.scene()
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(0, 62, 255, 255)
    skyMaterial.horizon=color(99, 255, 0, 255)
    v=scene.camera:add(OrbitViewer, vec3(0,5,0), 30, 0, 200)
    
    sphere1=scene:entity()
    s1=sphere1:add(craft.rigidbody,DYNAMIC)
    sphere1.position=vec3(4,0,0)
    sphere1:add(craft.shape.sphere,1)
    sphere1.model = craft.model.icosphere(1,2)
    sphere1.material = craft.material(asset.builtin.Materials.Specular)
    sphere1.material.diffuse=color(255,0,0)

    local ww=scene:entity()
    local w=ww:add(craft.rigidbody,STATIC)
    ww.position=vec3(0,-1,0)
    ww:add(craft.shape.box,vec3(10,.1,10))
    ww.model = craft.model.cube(vec3(10,.1,10))
    ww.material = craft.material(asset.builtin.Materials.Standard)
end

function draw()
    update(DeltaTime)
    scene:draw()
    text("tap screen to apply torque",WIDTH/2,HEIGHT/2)	
end

function update(dt)
    scene:update(dt)
    if tor then
        s1:applyTorque(vec3(0,0,1))
    end
end

function touched(t)
    if t.state==BEGAN then
        tor=true
    end
end

@SugarRay Here’s another example.

viewer.mode=FULLSCREEN

function setup()
    fill(255,0,0)
    assert(OrbitViewer, "Please include Cameras as a dependency")
    scene = craft.scene()
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(0, 62, 255, 255)
    skyMaterial.horizon=color(99, 255, 0, 255)
    v=scene.camera:add(OrbitViewer, vec3(0,5,0), 30, 0, 200)
    
    local w1=scene:entity()
    local w=w1:add(craft.rigidbody,STATIC)
    w1.position=vec3(0,-1,0)
    w1:add(craft.shape.box,vec3(10,.1,10))
    w1.model = craft.model.cube(vec3(10,.1,10))
    w1.material = craft.material(asset.builtin.Materials.Standard)
    
    local w2=scene:entity()
    ww=w2:add(craft.rigidbody,DYNAMIC)
    w2.position=vec3(0,0,0)
    w2:add(craft.shape.box,vec3(2,2,2))
    w2.model = craft.model.cube(vec3(2,2,2))
    w2.material = craft.material(asset.builtin.Materials.Standard)
end

function draw()
    update(DeltaTime)
    scene:draw()
    text("tap screen to start or stop torque",WIDTH/2,HEIGHT/2)	
end

function update(dt)
    scene:update(dt)
    if tor then
        ww:applyTorque(vec3(0,10,0))
    end
end

function touched(t)
    if t.state==BEGAN then
        tor = not tor -- toggle torque or or off with each tap
    end
end

Thanks, @dave1707!
Your sample spins perfectly.
Mine still won’t spin for some reason :frowning:
I even simplified my applyTorque command and put it into the function update(dt) section, and it still wouldn’t spin, no matter how much torque I gave it (maybe very heavy crab? :slight_smile: )

Apply force still works well in my project; the only other differences as far as I can tell is that I’m applyTorque to a more complicated mesh and that your project has the camera Dependencies on it. If you get a chance, can you try applyTorque to an imported more complex model? Alternatively, I can upload my project to Dropbox and send it to you and see if you can get my model crab to spin.

I check this out more tonight after work.

@SugarRay applyTorque takes a vec3 value. You can apply torque to the x,y,z axis either one at a time or all 3.

Thanks, @dave1707. Yes, I gave applyTorque a vec3 like you did in your examples but it still didn’t seem to work. :frowning:

Would you (or anyone else on the chat that is interested) mind downloading and testing it out at your convenience and see if you can figure out what I’m doing wrong? Simple subset of a larger project but has large meshes in it so big file:

Thanks :slight_smile:

the problem is somewhere in your model, if you use craft.shape.box in your add function it will allow for the spin in torque but the crab gets bounced around the scene

Thanks, @skar, for taking a look. I started thinking about that myself tonight-- since I’m using craft.physics now to move entities (instead of moving them directly), perhaps the difference might be that @dave1707’s example attaches a physics box.shape to the cube to act on, while in my project I initially tried to attach shape.model (which is supposed to approximate the shape of the 3D model) to try and act on. For some reason, applyTorque in Codea doesn’t seem to want to rotate the shape.model (although it will translate it fine with applyForce); it seems I’d need need to attach a different shape to my 3D mesh. I tried capsule but didn’t get it to work-- you mentioned you got box to work but the actual physics of the spin was off when you spun the crab using that shape.

@John, any other suggestions for attaching craft.shape’s to more complex imported 3D models that will work with applyTorque? Will Codea4 use different shapes to attach to its 3D models for physics?

Thanks!

@SugarRay Is this closer to what you’re doing.

viewer.mode=FULLSCREEN

function setup()
    fill(255,0,0)
    assert(OrbitViewer, "Please include Cameras as a dependency")
    scene = craft.scene()
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(0, 62, 255, 255)
    skyMaterial.horizon=color(99, 255, 0, 255)
    v=scene.camera:add(OrbitViewer, vec3(0,5,0), 30, 0, 200)
    
    local w1=scene:entity()
    local w=w1:add(craft.rigidbody,STATIC)
    w1.position=vec3(0,-2,0)
    w1:add(craft.shape.box,vec3(10,.1,10))
    w1.model = craft.model.cube(vec3(10,.1,10))
    w1.material = craft.material(asset.builtin.Materials.Standard)
    
    mdl = scene:entity()
    m1 = mdl:add(craft.rigidbody, DYNAMIC)
    mdl.position = vec3(0,-2,0)
    mdl:add(craft.shape.box,vec3(1,1,1))
    mdl.model = craft.model(asset.builtin.Blocky_Characters.Adventurer)   
end

function draw()
    update(DeltaTime)
    scene:draw()
    text("tap screen to start or stop torque",WIDTH/2,200)
end

function update(dt)
    scene:update(dt)
    if tor then
        m1:applyTorque(vec3(0,3,0))
    end
end

function touched(t)
    if t.state==BEGAN then
        tor=not tor
    end
end

Yes, @dave1707, thanks-- that is exactly what I was trying to do.

For my learning, I’ll work on figuring out how to put a craft.shape.box around my imported 3D mesh crab. Craft.shape.capsule probably approximates model a little better but the capsule didn’t seem spin with applyTorque either.

Is there any way/property to “measure” the width and length of an imported 3D model in Codea? Such a way/property would be helpful in figuring out the size of the Craft.shape I need to put around my imported 3D mesh. If not, I imaging I could just import the 3D model into some other type of 3D mesh constructing software that might tell me.

Thanks.

@SugarRay I don’t think it really matters how big the cube or other shape is. You could try decreasing the size of the cube in my example and see what happens if you make it smaller.

Okay, thanks, @dave1707, I’ll try that.

It might be helpful if in future Codea.craft iterations if there was a feature where you could make the Craft.shapes visible in the scene as some other physics engines allow for debugging purposes.

P.S.,
Perhaps not to demonstrate using applyTorque but for the project itself, I think I’ll need craft.shape to best approximate the size around my imported 3D model since I’ll be using that craft.shape in detecting collisions of my 3D model in addition to using it as an object to enact craft.physics upon.

@SugarRay If you’re using the shape for collision, then you’ll need to approximate the size as close as possible. You could have multiple shapes to cover the body, another to cover the claws, etc. instead of one big shape.

Thanks, @dave1707, I’ll try that, too!