How to rotate the craft.model around the specified axis?

How to rotate the craft.model around the specified axis?

Hi, guys,I am back to learn the craft and found many questions. Here is the one.

I read the built-in examples Block Library and try to use the technique in it.

In the built-in help docs, I found that only craft.model.cube and craft.model.plane have the “offset” parameter, with which can easily make the model rotate around any specified axis.

But craft.model.icosphere and the loaded model which using craft.model(“asset model”) have not the “offset”, how to rotate them like the craft.model.cube?

Here is the demo video:

https://youtu.be/zWJ47JgE-_M

Below is the code:

function setup()
    -- Create a new craft scene
    scene = craft.scene()
    scene.ambientColor = color(218, 158, 79)
    scene.sky.active = false
    
    -- Setup camera and lighting
    scene.sun.rotation = quat.eulerAngles(125, 125, 0)
    
    assert(OrbitViewer, "Please include Cameras project as a dependency")
    gViewer = scene.camera:add(OrbitViewer, vec3( 2.0,  0.5,  0.5), 8, 1, 400)
    gViewer.rx=45
    gViewer.ry=-45
    
    myChest = Chest()
end

function update(dt)
    -- Update the scene (physics, transforms etc)
    scene:update(dt)
    myChest:update()
end

-- Called automatically by codea 
function draw()
    update(DeltaTime)
    
    -- Draw the scene
    scene:draw()	
end


Chest = class()

function Chest:init()
    e = self.entity
    self.base = scene:entity()
    self.base.parent = e
    self.base.position = vec3(0.5, 0.3, 0.5)
    local r = self.base:add(craft.renderer, craft.model.cube(vec3(0.8,0.6,0.8)))
    r.material = craft.material(asset.builtin.Materials.Specular)
    r.material.diffuse = color(133, 79, 30)
    
    self.top = scene:entity()
    self.top.parent = e
    self.top.position = vec3(0.1, 0.6, 0.1)
    print("local=",self.top.position, " world=", self.top.worldPosition)
    local r2 = self.top:add(craft.renderer, craft.model.cube(vec3(0.8,0.2,0.8),vec3(0.4,0.1,0.4)))
    print("local=",self.top.position," world= ",self.top.worldPosition)
    r2.material = craft.material(asset.builtin.Materials.Specular)
    r2.material.diffuse = color(66, 47, 30, 255)
    self.angle = 0
    self.y = 0.6
    
    self.ball = scene:entity()
    self.ball.position = vec3(1.5, 0.3, 0.5)
    local r3 = self.ball:add(craft.renderer, craft.model.icosphere(0.3))
    r3.material = craft.material(asset.builtin.Materials.Specular)
    r3.material.diffuse = color(133, 124, 30)
    
    self.obj = scene:entity()
    self.obj.position = vec3(2.5, 0.3, 0.5)
    self.obj.scale = vec3(0.5, 0.5, 0.5)
    local r4 = self.obj:add(craft.renderer, craft.model(asset.builtin.Primitives.RoundedCube))
    r4.material = craft.material(asset.builtin.Materials.Specular)
    r4.material.diffuse = color(30, 133, 101)
    
    self.floor = scene:entity()
    self.floor.parent = e
    self.floor.position = vec3(0.1, 0.6, 0.1)
    local r5 = self.floor:add(craft.renderer, craft.model.plane(vec2(1.8,1.8),vec3(0.9,0.0,0.9)))
    r5.material = craft.material(asset.builtin.Materials.Specular)
    r5.material.diffuse = color(46, 66, 30)
    
    touches.addHandler(self, -1, false)
end

function Chest:update()
    self.top.rotation = quat.eulerAngles(0,  0, self.angle)
    self.ball.rotation = quat.eulerAngles(0,  0, self.angle)
    self.obj.rotation = quat.eulerAngles(0,  0, self.angle)
    self.floor.rotation = quat.eulerAngles(0,  0, self.angle)

    scene.debug:line(vec3(0.1, 0.6, 0.1-1),vec3(0.1, 0.6, 0.1+1),color(47, 239, 5))
    scene.debug:line(vec3(1.5, 0.3, 0.5-1),vec3(1.5, 0.3, 0.5+1),color(47, 239, 5))
    scene.debug:line(vec3(2.5, 0.3, 0.5-1),vec3(2.5, 0.3, 0.5+1),color(47, 239, 5))
end

function Chest:interact()
    if not self.open then        
        self.open = true
        tween(1.6, self, {angle = 90, y=10}, {easing=tween.easing.backOut,loop = tween.loop.once })
    else
        self.open = false
        tween(1.6, self, {angle = 0, y=0.6}, tween.easing.cubicIn)
    end
end

function Chest:touched(touch)
    if touch.state == BEGAN then
        self:interact()
    end
end

I’m not sure if this will help but for my helicopter project I put all the helicopter models inside a parent entity. Then I can rotate the parent entity, and offset the models however I like using their own position settings.

@UberGoober Thank you for reminding me. I almost forgot the entity.parent. I added a few changes and now the effect is as follows?

https://youtu.be/xXZojXXQXW0

The changed code:

Chest = class()
    
function Chest:init()
    e = self.entity
    self.base = scene:entity()
    self.base.parent = e
    self.base.position = vec3(0.5, 0.3, 0.5)
    local r1 = self.base:add(craft.renderer, craft.model.cube(vec3(0.8,0.6,0.8)))
    r1.material = craft.material(asset.builtin.Materials.Specular)
    r1.material.diffuse = color(133, 79, 30)
    
    self.root = scene:entity()
    self.root.position = vec3(1.5, 0.3, 0.5)
    local r0 = self.root:add(craft.renderer, craft.model.cube(vec3(0.8,0.2,0.8),vec3(0.3,0.1,0.4)))
    
    self.top = scene:entity()
    self.top.parent = self.root
    self.top.position = vec3(0.1, 0.6, 0.1)
    local r2 = self.top:add(craft.renderer, craft.model.cube(vec3(0.8,0.2,0.8),vec3(0.4,0.1,0.4)))
    r2.material = craft.material(asset.builtin.Materials.Specular)
    r2.material.diffuse = color(66, 47, 30, 255)
    self.angle = 0
    self.y = 0.6
    
    self.ball = scene:entity()
    self.ball.parent = self.root
    self.ball.position = vec3(0, 0.3, 0.5)
    local r3 = self.ball:add(craft.renderer, craft.model.icosphere(0.2))
    r3.material = craft.material(asset.builtin.Materials.Specular)
    r3.material.diffuse = color(133, 124, 30)
    
    self.obj = scene:entity()
    self.obj.parent = self.root
    self.obj.position = vec3(1.5, 0.3, 0.5)
    self.obj.scale = vec3(0.5, 0.5, 0.5)
    local r4 = self.obj:add(craft.renderer, craft.model(asset.builtin.Primitives.RoundedCube))
    r4.material = craft.material(asset.builtin.Materials.Specular)
    r4.material.diffuse = color(30, 133, 101)
    
    self.floor = scene:entity()
    self.floor.parent = e
    self.floor.position = vec3(0.1, 0.6, 0.1)
    local r5 = self.floor:add(craft.renderer, craft.model.plane(vec2(1.2,1.2),vec3(0.6,0.0,0.6)))
    r5.material = craft.material(asset.builtin.Materials.Specular)
    r5.material.diffuse = color(46, 66, 30)
    
    touches.addHandler(self, -1, false)
end

function Chest:update()
    self.root.rotation = quat.eulerAngles(0,  0, self.angle)
    self.top.rotation = quat.eulerAngles(0,  0, self.angle*8)
    self.ball.rotation = quat.eulerAngles(0,  0, self.angle)
    self.obj.rotation = quat.eulerAngles(0,  0, self.angle*10)
    self.floor.rotation = quat.eulerAngles(0,  0, self.angle)

    scene.debug:line(vec3(0.1, 0.6, 0.1-1),vec3(0.1, 0.6, 0.1+1),color(47, 239, 5))
    scene.debug:line(vec3(1.5, 0.3, 0.5-1),vec3(1.5, 0.3, 0.5+1),color(239, 5, 5))
    
    local a = self.ball.worldPosition + vec3(0,0,-1)
    local b = self.ball.worldPosition + vec3(0,0,1)
    scene.debug:line(a, b,color(239, 5, 199))
    
    local a = self.top.worldPosition + vec3(0,0,-1)
    local b = self.top.worldPosition + vec3(0,0,1)
    scene.debug:line(a, b,color(16, 239, 5))
    
    local a = self.obj.worldPosition + vec3(0,0,-1)
    local b = self.obj.worldPosition + vec3(0,0,1)
    scene.debug:line(a, b,color(239, 233, 5))
end


function Chest:interact()
    if not self.open then
        self.open = true
        tween(1.6, self, {angle = 90, y=10}, {easing=tween.easing.backOut,loop = tween.loop.once })
    else
        self.open = false
        tween(1.6, self, {angle = 0, y=0.6}, tween.easing.cubicIn)
    end
end


function Chest:touched(touch)
    if touch.state == BEGAN then
        self:interact()
    end
end

The problem now is that objects with the offset attribute can easily rotate around different axes by performing their own rotate method, objects that don’t have the offset property are limited to a certain extent, and their own rotate method can only rotate around their central axis, and objects that want to rotate around an axis in another location can only do so by following these steps:

  1. Add a parent entity to the object;
  2. Set the parent entity ’s position (that is, the Axis around which the object will rotate) ;
  3. Rotate the parent entity, the object is then rotated.

@John Can all types of models (cube,plane,icosphere,loaded model etc.) have an offset property, and not just the cube and the plane, so they can all deal with rotation in a consistent way, thanks