Bone animation

An bone animation

I used mesh, not craft model, the reason is that with model matrix, it is easy to understand and calculate the positions, angles of bone animation.

Download the object files and save to your local folder — Documents

Model obj files:

https://GitHub.com/FreeBlues/bone-animation

https://youtu.be/9jy0B7QkMtg

Source code:


--# Main
-- BoneMesh
-- ????? Bones ? MeshTest ?? BoneTest ?????????? mesh ??????????
-- 2020.02.22 ?????????????????

function setup()
    -- craft scene ???
    craftSceneInit()
    objectsInit()
    
    -- ?? lovntArray ?????????????? robot
    robot = Robot(objectArray)
    -- ???????
    dat = DoActionThread(robot)

    -- ?? OrbitViewer ??????????????????????
    scene.camera:add(OrbitViewer, vec3(0,0,0),5, 10, 5)
end

-- ? ???(angle,x,y,z)??????(w,x,y,z)
function axis2quat(a,x,y,z)
    local w = math.cos(math.rad(a)/2)
    local x = math.sin(math.rad(a)/2)*x
    local y = math.sin(math.rad(a)/2)*y
    local z = math.sin(math.rad(a)/2)*z
    return quat(w,x,y,z)
end

function update(dt)
    dat:run()
    scene:update(dt)
end

function draw()
    update(DeltaTime)

    -- ?? craft ??    
    scene:draw()
    -- ?????
    scene.debug:line(vec3(0,0,0),vec3(1,0,0),color(255,0,0,255))  
    scene.debug:line(vec3(0,0,0),vec3(0,1,0),color(0,255,0,255))   
    scene.debug:line(vec3(0,0,0),vec3(0,0,1),color(255,255,0,255))  
    
    -- ?? mesh ???????????
    perspective()
    -- background()
    
    -- ?? craft ???????? mesh ?????
    local scp = scene.camera.position
    local x,y,z = scp.x, scp.y, scp.z
    camera(x,y,z,0,0,0, 0,1,0)
    
    -- ?? Robot ???? drawSelf ??
    robot:drawSelf()   
end

function objectsInit()
    
    -- run only once ????????14??????Model1.txt ~ Model14.txt
    for k=1,14 do
        saveText(asset.."Model"..k..".txt", "")
    end
    
    objectArray = {}   
    objectArray[1] = LoadObject("Documents:body", 1)
    objectArray[2] = LoadObject("Documents:body", 2)  
    objectArray[3] = LoadObject("Documents:head", 3)   
    objectArray[4] = LoadObject("Documents:left_top",4)   
    objectArray[5] = LoadObject("Documents:left_bottom",5)   
    objectArray[6] = LoadObject("Documents:right_top",6)   
    objectArray[7] = LoadObject("Documents:right_bottom",7)   
    objectArray[8] = LoadObject("Documents:right_leg_top",8)   
    objectArray[9] = LoadObject("Documents:right_leg_bottom",9)   
    objectArray[10] = LoadObject("Documents:left_leg_top",10)   
    objectArray[11] = LoadObject("Documents:left_leg_bottom",11)   
    objectArray[12] = LoadObject("Documents:left_foot", 12)   
    objectArray[13] = LoadObject("Documents:right_foot", 13) 
    
    floor = LoadObject("Documents:floor", 14)
end

function craftSceneInit()
    -- Create a new craft scene
    scene = craft.scene()
    
    -- ???????
    local sunny = readText(asset.builtin.Environments.Night)
    local env = craft.cubeTexture(json.decode(sunny))
    scene.sky.material.envMap = env
    scene.sky.eulerAngles = vec3(0,180,0)
    scene.camera.z = -10
    scene.camera.eulerAngles = vec3(0,0,0)
    scene.camera.position = vec3(0,0,0)
    
    -- ???????????
    -- scene.sun.active = false
    -- scene.sky.active = false
    -- Move the main camera
    scene.camera.position = vec3(0, -10, -10)
    
    -- ??????
    scene.sun:get(craft.light).intensity = 0.8
    scene.sun.position = vec3(0, -10, 0)
    scene.sun.rotation = quat.eulerAngles(45,0,45)
    scene.ambientColor = color(88, 107, 222, 255)
end


--# Robot
Robot = class()

function Robot:init(objectArray)   
    self.lowest = math.huge
    self.lowestForDraw = {}
    self.lowestForDrawTemp = {}
    
    self.bRoot = BodyPart(0,0,0,objectArray[1],1,self)
    self.bBody = BodyPart(0,0.938,0,objectArray[2],2,self)
    self.bHead = BodyPart(0,1,0,objectArray[3],3,self)
    
    self.bLeftTop = BodyPart(0.107,0.938,0,objectArray[4],4,self)
    self.bLeftBottom = BodyPart(0.105,0.707,-0.033,objectArray[5],5,self)
    self.bRightTop = BodyPart(-0.107,0.938,0,objectArray[6],6,self)
    self.bRightBottom = BodyPart(-0.105,0.707,-0.033,objectArray[7],7,self)
    
    self.bRightLegTop = BodyPart(-0.068,0.6,0.02,objectArray[8],8,self)
    self.bRightLegBottom = BodyPart(-0.056,0.312,0,objectArray[9],9,self)
    self.bLeftLegTop = BodyPart(0.068,0.6,0.02,objectArray[10],10,self)
    self.bLeftLegBottom = BodyPart(0.056,0.312,0,objectArray[11],11,self)
    
    local leftFootLowest = {{0.068,0.0,0.113},{0.068,0,-0.053}}
    local rightFootLowest = {{-0.068,0.0,0.113},{-0.068,0,-0.053}}
    self.bLeftFoot = BodyPart(0.068,0.038,0.033,objectArray[12],12,self,true,leftFootLowest)
    self.bRightFoot = BodyPart(-0.068,0.038,0.033,objectArray[13],13,self,true,rightFootLowest)
    print("robot ",self.bRightFoot.lowestDots[1][1])
    self.bpArray = {}
    self.bpArray[1] = self.bRoot 
    self.bpArray[2] = self.bBody
    self.bpArray[3] = self.bHead
    self.bpArray[4] = self.bLeftTop
    self.bpArray[5] = self.bLeftBottom
    self.bpArray[6] = self.bRightTop
    self.bpArray[7] = self.bRightBottom
    self.bpArray[8] = self.bRightLegTop
    self.bpArray[9] = self.bRightLegBottom 
    self.bpArray[10] = self.bLeftLegTop 
    self.bpArray[11] = self.bLeftLegBottom 
    self.bpArray[12] = self.bLeftFoot 
    self.bpArray[13] = self.bRightFoot
    
    -- ??????????
    self.bRoot:addChild(self.bBody) 
      
    self.bBody:addChild(self.bHead)
    self.bBody:addChild(self.bLeftTop)
    self.bBody:addChild(self.bRightTop)
    self.bBody:addChild(self.bLeftLegTop)         
    self.bBody:addChild(self.bRightLegTop)
    
    self.bLeftTop:addChild(self.bLeftBottom)

    self.bRightTop:addChild(self.bRightBottom)

    self.bRightLegTop:addChild(self.bRightLegBottom)
    self.bLeftLegTop:addChild(self.bLeftLegBottom)
    
    self.bLeftLegBottom:addChild(self.bLeftFoot)
    self.bRightLegBottom:addChild(self.bRightFoot)
    
    self.finalMatrixForDrawArray = {matrix()}
    self.finalMatrixForDrawArrayTemp = {matrix()}   
    for i=1,#self.bpArray,1 do
        self.finalMatrixForDrawArray[i] = matrix()
        self.finalMatrixForDrawArrayTemp[i] = matrix()             
    end
    
    -- ???????????????????????????????????
    self.bRoot:initFatherMatrix()
    -- ?????????????????????????????
    self.bRoot:updateBone()
    -- ??????????????????????????????
    self.bRoot:CalMWorldInitInver()
end

function Robot:calLowest()
		self.lowest=math.huge
		self.bRoot:calLowest()
end

function Robot:updateState()
    self.bRoot:updateBone()    
end

function Robot:backToInit()
    self.bRoot:backToInit()
end

function Robot:flushDrawData()
    for k,bp in ipairs(self.bpArray) do
        bp:copyMatrixForDraw()
    end
    self.lowestForDraw = self.lowest
end

function Robot:drawSelf()
    -- ????????????? modelMatrix
    for i=1,#self.bpArray do
        for j=1,16 do
        self.finalMatrixForDrawArrayTemp[i][j] = self.finalMatrixForDrawArray[i][j]            
        end
    end
    
    self.lowestForDrawTemp=self.lowestForDraw;
    modelMatrix(modelMatrix():translate(0, -self.lowestForDrawTemp, 0))

    -- ?? BodyPart ? drawSelf ?????????????
    self.bRoot:drawSelf(self.finalMatrixForDrawArrayTemp)
    -- popMatrix()
end

--# BodyPart
BodyPart = class()

-- ?????????1 BodyPart:drawSelf() ?????????2 Robot:drawSelf() ????? bRoot????????? child ??
-- ????????????? lovnt:drawSelf()

function BodyPart:init(fx,fy,fz,lovnt,index,robot,lowestFlag,lowestDots)
    self.index = index
    self.object = lovnt
    self.object.e.position = vec3(fx,fy,fz)
    self.object.e.active = true
    self.fx = fx
    self.fy = fy
    self.fz = fz
    self.robot = robot
    self.father = nil
    self.mFather = matrix()
    self.mWorld = matrix()
    self.mFatherInit = matrix()
    self.mWorldInitInver = matrix()
    self.finalMatrix = matrix()
    self.lowestFlag = lowestFlag
    self.lowestDots = lowestDots    
    self.childs = {}
    -- bRoot ???
    if self.index == 1 then self.object.e.active = false end
end

function BodyPart:calLowest()
    if self.lowestFlag == true then
        -- print("ll ",self.lowestDots[1][1])           
        for k,p in ipairs(self.lowestDots) do
            -- print("p ",p[1])
            local pqc=vec4(p[1],p[2],p[3],1);--???????
            local resultP=vec4(0,0,0,1); --????????????
            local resultP = self.finalMatrix * pqc

            if resultP[2]<self.robot.lowest then
                -- ????y???????????y??
                -- print("low ", self.robot.lowest)
                self.robot.lowest = resultP[2]; --???????????y??
            end
        end
    end
    for k,bc in ipairs(self.childs) do
        bc:calLowest()
    end
end

function BodyPart:copyMatrixForDraw()
    for i=1,16,1 do
        self.robot.finalMatrixForDrawArray[self.index][i] = self.finalMatrix[i]
    end
end

function BodyPart:drawSelf(tempMatrixArray)
    -- ????????????1 ??????2 ??????
    if self.object ~= nil and self.index~=1 then
        pushMatrix()
        -- ?????? mesh ??????? === ????
        -- print("m1 ",modelMatrix())
        modelMatrix(tempMatrixArray[self.index])
        -- print("m2 ",modelMatrix())
        -- ?? loadObjVerNorTex ????? craft ? mesh
        self.object:drawSelf()
        popMatrix()
    end
    for k,bc in ipairs(self.childs) do
        bc:drawSelf(tempMatrixArray) 
    end 
end

function BodyPart:initFatherMatrix()
    local tx,ty,tz = self.fx,self.fy,self.fz
    if self.father ~= nil then
        tx = self.fx - self.father.fx
        ty = self.fy - self.father.fy
        tz = self.fz - self.father.fz
    end

    -- ??????????????????
    self.mFather = matrix()
    self.mFather = self.mFather:translate(tx,ty,tz)
    for i=1,16,1 do
        self.mFatherInit[i] = self.mFather[i]
    end

    -- ???????
    for k,bc in ipairs(self.childs) do
        bc:initFatherMatrix()
    end
end

function BodyPart:CalMWorldInitInver()
    -- ? self.mWorld ??
    self.mWorldInitInver = self.mWorld:inverse()
    -- ???????    
    for k,bc in ipairs(self.childs) do
        bc:CalMWorldInitInver()     
    end
end

function BodyPart:updateBone()
    if self.father ~= nil then
        -- Codea ???????????
        self.mWorld = self.mFather * self.father.mWorld
        -- self.robot.bpArray[self.index].object.e.position = self.mWorld *self.robot.bpArray[self.index].object.e.position 
    else
        for i=1,16,1 do
            self.mWorld[i] = self.mFather[i]
        end
    end
    
    -- ???????????????
    self:calFinalMatrix()
    -- ???????   
    for k,bc in ipairs(self.childs) do
        bc:updateBone()
    end     
end

-- ???????????
function BodyPart:calFinalMatrix()
    -- Codea ???????????
    self.finalMatrix = self.mWorldInitInver * self.mWorld
end

function BodyPart:backToInit()
    for i=1,16,1 do
        self.mFather[i] = self.mFatherInit[i]
    end
    
    -- ???????    
    for k,bc in ipairs(self.childs) do
        bc:backToInit()
    end             
end

function BodyPart:translate(x,y,z)
    -- mesh ???? DoActionThread ????????????
    self.mFather = self.mFather:translate(x,y,z)
    
    -- craft ???? DoActionThread ????????????
    -- ??????????
    -- self.lovnt.e.position = m * self.lovnt.e.position
    self.robot.bpArray[self.index].object.e.position = vec3(x,y,z)
end

function BodyPart:rotate(a,x,y,z)
    -- mesh ???? DoActionThread ????????????
    self.mFather = self.mFather:rotate(a,x,y,z)

    -- craft ???? DoActionThread ????????????
    local q = axis2quat(a,x,y,z)
    self.robot.bpArray[self.index].object.e.rotation = q
end

-- ?????
function BodyPart:addChild(child)
    table.insert(self.childs, child)
    -- self.childs[#self.childs+1] = child
    child.father = self
end


--# LoadObject
LoadObject = class()

function LoadObject:init(objPath,id)

    self.e = scene:entity()
    -- self.e.position = vec3(0,0,0)
    -- self.e.scale = vec3(10,10,10)
    self.e.model = craft.model(objPath)
    self.e.material = craft.material(asset.builtin.Materials.Standard)
    -- self.e.material.map = readImage("Dropbox:face1")
    self.e.active = true
    self.id = id
    self.m = self:model2mesh(self.e.model, self.id)
    -- self.m.vertices = self.e.model.positions
    -- self.m.texCoords = self.e.model.uvs
    -- self.m.normals = self.e.model.normals
    -- self.m.colors = self.e.colors

    self.m:setColors(255,255,255,255)
    self.m.texture = readImage(asset.builtin.Blocks.Ice)
    ---[[ ??OpenGLES3.0 ???9_1 ? shader
    self.m.shader = shader(s.v3,s.f3)
    -- m.shader = shader(s.v2,s.f2)
    self.m.shader.modelMatrix = matrix()
    self.m.shader.viewMatrix = matrix()
    self.m.shader.projectionMatrix = matrix()    

    -- m.shader.modelMatrix=m.shader.modelMatrix:rotate(50, 	0,	1, 	0)
    self.m.shader.uCamera = vec3(0,5,1)
    self.m.shader.uLightLocation = vec3(100,103,103)
    self.m.shader.sTexture = self.m.texture    
end

function LoadObject:model2mesh(model,id)
    local m = mesh()
    local indices = model.indices    
    local vb = m:buffer("position")
    local tb = m:buffer("texCoord")
    local nb = m:buffer("normal")
    local cb = m:buffer("color")
    local vt,tt,nt,ct = {{}},{{}},{{}},{{}}
    vb:resize(#indices)
    tb:resize(#indices)
    nb:resize(#indices)
    cb:resize(#indices)

    -- ???? id ??????????    
    local str = readText(asset.."Model"..id..".txt")
    
    -- ????????????????????
    if str == "" then       
        for k=1,#indices do
            vb[k] = model.positions[model.indices[k]]
            tb[k] = model.uvs[model.indices[k]]
            nb[k] = model.normals[model.indices[k]]
            cb[k] = model.colors[model.indices[k]]
            -- ?vec3?vec2 ??????????????????
            vt[k] = {vb[k].x, vb[k].y, vb[k].z}
            tt[k] = {tb[k].x, tb[k].y}
            nt[k] = {nb[k].x, nb[k].y, nb[k].z}
            ct[k] = {cb[k].x, cb[k].y, cb[k].z}
        end
        local modelString = json.encode({vt,tt,nt,ct})
        saveText(asset.."Model"..id..".txt", modelString)
    else
        local t = json.decode(str)   
        vt,tt,nt,ct = t[1], t[2], t[3], t[4]              
        print("t ", #t[3][2], t[1][1][1])
        -- ??
        for k = 1,#vt do
            vb[k] = vec3(vt[k][1], vt[k][2], vt[k][3])
            tb[k] = vec2(tt[k][1], tt[k][2])
            nb[k] = vec3(nt[k][1], nt[k][2], nt[k][3])
            cb[k] = vec3(ct[k][1], ct[k][2], ct[k][3])
        end        
    end    
    
    print("indices: ", #indices, type(id), id)
    return m
end


function LoadObject:update(dt)

end

function LoadObject:drawSelf()    
    -- ?? mesh ??
    self.m:draw()    
end

s = {
v3 =[[#version 300 es
uniform mat4 modelViewProjection; //?????
uniform mat4 modelMatrix; //????
uniform mat4 viewMatrix; //????
uniform mat4 projectionMatrix; //????
uniform vec3 uLightLocation;	//????
uniform vec3 uCamera;	//?????
in vec3 position;  //????
in vec3 normal;    //?????
in vec2 texCoord;    //??????
//?????????????
out vec4 ambient;
out vec4 diffuse;
out vec4 specular;
out vec2 vTextureCoord;  
//??????????
void pointLight(					//??????????
  in vec3 iNormal,				//???
  inout vec4 ambient,			//???????
  inout vec4 diffuse,				//???????
  inout vec4 specular,			//???????
  in vec3 lightLocation,			//????
  in vec4 lightAmbient,			//?????
  in vec4 lightDiffuse,			//?????
  in vec4 lightSpecular			//?????
){
  ambient=lightAmbient;			//????????????  
  vec3 normalTarget=position+iNormal;	//?????????
  vec3 newNormal=(modelMatrix*vec4(normalTarget,1)).xyz-(modelMatrix*vec4(position,1)).xyz;
  newNormal=normalize(newNormal); 	//???????
  //?????????????
  vec3 eye= normalize(uCamera-(modelMatrix*vec4(position,1)).xyz);  
  //??????????????vp
  vec3 vp= normalize(lightLocation-(modelMatrix*vec4(position,1)).xyz);  
  vp=normalize(vp);//???vp
  vec3 halfVector=normalize(vp+eye);	//??????????    
  float shininess=30.0;			//?????????
  float nDotViewPosition=max(0.0,dot(newNormal,vp)); 	//?????vp????0????

  diffuse = lightDiffuse*nDotViewPosition;				//??????????
  float nDotViewHalfVector=dot(newNormal,halfVector);	//????????? 
  float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess)); 	//?????????
  specular=lightSpecular*powerFactor;    			//??????????
}


void main()     
{ 
// mat4 modelViewProject = projectionMatrix*(viewMatrix* modelMatrix);
    gl_Position = modelViewProjection * vec4(position,1); //??????????????????  

   // ????????????????????      
   vec4 ambientTemp, diffuseTemp, specularTemp;   
    pointLight(normalize(normal),ambientTemp,diffuseTemp,specularTemp,uLightLocation,vec4(0.15,0.15,0.15,1.0),vec4(0.59,0.59,0.59,1.0),vec4(0.4,0.4,0.4,1.0));
   
   ambient=ambientTemp;
   diffuse=diffuseTemp;
   specular=specularTemp;
   vTextureCoord = texCoord;//????????????????
}      
]],

f3 = [[#version 300 es 
precision mediump float;
uniform sampler2D sTexture;//??????
//?????????????
in vec4 ambient;
in vec4 diffuse;
in vec4 specular;
in vec2 vTextureCoord;
out vec4 fragColor;

void main()                         
{    
   //???????????
   vec4 finalColor=texture(sTexture, vTextureCoord);    
   //???????
   fragColor = finalColor*ambient+finalColor*specular+finalColor*diffuse;

}   
]],

v51 = [[#version 300 es
//?????????????
uniform mat4 uMVPMatrix; //?????
uniform mat4 uMMatrix; //????
uniform vec3 uLightLocation;	//????
uniform vec3 uCamera;	//?????
in vec3 aPosition;  //????
in vec3 aNormal;    //?????
//?????????????
out vec4 ambient;
out vec4 diffuse;
out vec4 specular;
out vec4 vPosition;
 
void pointLight(				//??????????
  in vec3 normal,				//???
  inout vec4 ambient,			//???????
  inout vec4 diffuse,			//???????
  inout vec4 specular,			//???????
  in vec3 lightLocation,		//????
  in vec4 lightAmbient,			//?????
  in vec4 lightDiffuse,			//?????
  in vec4 lightSpecular			//?????
){
  ambient=lightAmbient;			//????????????  
  vec3 normalTarget=aPosition+normal;	//?????????
  vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(aPosition,1)).xyz;
  newNormal=normalize(newNormal); 	//???????
  //?????????????
  vec3 eye= normalize(uCamera-(uMMatrix*vec4(aPosition,1)).xyz);  
  //??????????????vp
  vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz);  
  vp=normalize(vp);//???vp
  vec3 halfVector=normalize(vp+eye);//??????????    
  float shininess=50.0;				//?????????
  float nDotViewPosition=max(0.0,dot(newNormal,vp)); 	//?????vp????0????
  diffuse=lightDiffuse*nDotViewPosition;				//??????????
  float nDotViewHalfVector=dot(newNormal,halfVector);	//????????? 
  float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess));//?????????
  specular=lightSpecular*powerFactor;//??????????
}

void main()     
{ 
   gl_Position = uMVPMatrix*vec4(aPosition,1); //??????????????????  
   pointLight(normalize(aNormal),ambient,diffuse,specular,uLightLocation,vec4(0.1,0.1,0.1,1.0),vec4(0.7,0.7,0.7,1.0),vec4(0.3,0.3,0.3,1.0));
   vPosition=uMMatrix*vec4(aPosition,1);
} 
]],

f51 = [[#version 300 es
precision mediump float;			//??????
uniform sampler2D sTexture;		//??????
in vec4 ambient;				//??????????????????
in vec4 diffuse;					//??????????????????
in vec4 specular;				//??????????????????
in vec4 vPosition;  				//?????????????????
out vec4 fragColor;
uniform highp mat4 uMVPMatrixGY; //???????????????????
void main(){
   //??????????????????????
   vec4 gytyPosition=uMVPMatrixGY * vec4(vPosition.xyz,1);
   gytyPosition=gytyPosition/gytyPosition.w;	//??????
   float s=gytyPosition.s+0.5;				//??????????????
   float t=gytyPosition.t+0.5;
   vec4 finalColor=vec4(0.8,0.8,0.8,1.0); 		//???????
   if(s>=0.0&&s<=1.0&&t>=0.0&&t<=1.0){	//??????????????????
   vec4 projColor=texture(sTexture,vec2(s,t));	//??????????
   vec4 specularTemp=projColor*specular;	//?????????????
   vec4 diffuseTemp=projColor*diffuse;		//?????????????
   fragColor=finalColor*ambient+finalColor*specularTemp+finalColor*diffuseTemp;//????????
   }else {//????????
       fragColor = finalColor*ambient+finalColor*specular+finalColor*diffuse;
    }
}]],}



--# DoActionThread
DoActionThread = class()

function DoActionThread:init(robot)
    self.currActionIndex = 1
    self.currStep = 1
    self.robot = robot
    self.actionGenerator = ActionGenerator()
    self.currAction = self.actionGenerator.acArray[self.currActionIndex]
end

-- ??? run ?? draw ? update ?????????????????
function DoActionThread:run()

    self.robot:backToInit()
    if self.currStep >= self.currAction.totalStep then
        self.currActionIndex =  (self.currActionIndex+1)%(#self.actionGenerator.acArray)
        self.currAction = self.actionGenerator.acArray[self.currActionIndex+1]
        self.currStep = 1
    end

    for k,ad in ipairs(self.currAction.data) do
        -- ?????????????????
        local partIndex, aType = ad[1],ad[2]
        local frameStep = self.currStep/self.currAction.totalStep
        if aType == 0 then
            local xStart,yStart,zStart = ad[3],ad[4],ad[5]
            local xEnd,yEnd,zEnd = ad[6],ad[7],ad[8]
            local currX = xStart+(xEnd-xStart)* frameStep
            local currY = yStart+(yEnd-yStart)* frameStep
            local currZ = zStart+(zEnd-zStart)* frameStep
            self.robot.bpArray[partIndex]:translate(currX,currY,currZ)
        elseif aType == 1 then
            local startAngle,endAngle = ad[3],ad[4]
            local currAngle = startAngle+(endAngle-startAngle)* frameStep
            local x,y,z = ad[5],ad[6],ad[7]
            self.robot.bpArray[partIndex]:rotate(currAngle,x,y,z)
        end
    end
    self.robot:updateState()
    self.robot:calLowest()
    self.robot:flushDrawData()
    self.currStep = self.currStep+1
end



--# ActionGenerator
ActionGenerator = class()

function ActionGenerator:init()
    self.count = 20
    self.acArray = {}
    self.acArray[1] = Action()
    self.acArray[2] = Action()
    self.acArray[3] = Action()
    self.acArray[4] = Action()
    local i = 1  
    
    self.acArray[1].totalStep = self.count
    self.acArray[1].data = {
    --{bodyNo. actionType?0-translate 1-rotation ?StartAngle  EndAngle   Rotation AxisXYZ}
    {1+i,0,0,0,0,0,0,0},
    --{body??  ?????0-?? 1-????????  ?????   ?????XYZ}
    {1+i,1,10,10,1,0,0},
    --{leftTop??  ?????0-?? 1-????????  ?????   ?????XYZ}
    {3+i,1,-70,0,0.948,0,0.316},
    --{rightTop??  ?????0-?? 1-????????  ?????   ?????XYZ}
    {5+i,1,-70,0,-0.948,0,0.316},
    --{leftTopDown??  ?????0-?? 1-????????  ?????  ?????XYZ}
    {4+i,1,-80,-80,0.948,0,0.316},
    --{rightTopDown??  ?????0-?? 1-????????  ?????  ?????XYZ}
    {6+i,1,80,80,-0.948,0,0.316},
    --{?????  ?????0-?? 1-????????  ?????   ?????XYZ}
    {7+i,1,-50,0,1,0,0},
    --{?????  ?????0-?? 1-????????  ?????   ?????XYZ}
    {9+i,1,20,0,1,0,0},
    --{?????  ?????0-?? 1-????????  ?????   ?????XYZ}
    {10+i,1,0,90,1,0,0},
    --{????  ?????0-?? 1-????????  ?????, ?????XYZ}
    {11+i,1,10,0,1,0,0},}
    
    self.acArray[2].totalStep = self.count
    self.acArray[2].data = {
    --{body??, ?????0-?? 1-???,?????, ?????, ?????XYZ}
    {1+i,0,0,0,0,0,0,0},
    --{body??, ?????0-?? 1-???,?????, ?????, ?????XYZ}
    {1+i,1,10,10,1,0,0},
    --{leftTop??, ?????0-?? 1-????????  ?????   ?????XYZ}
    {3+i,1,0,70,0.948,0,0.316},
    --{rightTop??,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {5+i,1,0,70,-0.948,0,0.316}, 
    --{leftTopDown??, ?????0-?? 1-???,?????, ?????, ?????XYZ}
    {4+i,1,-80,-80,0.948,0,0.316},
    --{rightTopDown??, ?????0-?? 1-???,?????, ?????, ?????XYZ}
    {6+i,1,80,80,-0.948,0,0.316},
    --{?????,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {7+i,1,0,20,1,0,0},
    --{?????,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {9+i,1,0,-50,1,0,0},
    --{?????,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {10+i,1,90,0,1,0,0},
    --{????,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {12+i,1,0,10,1,0,0},}
    
    self.acArray[3].totalStep = self.count
    self.acArray[3].data = {
    --{body??  ?????0-?? 1-????????  ?????   ?????XYZ}
    {1+i,0,0,0,0,0,0,0},
    --{body??  ?????0-?? 1-????????  ?????   ?????XYZ}
    {1+i,1,10,10,1,0,0},
    --{leftTop??  ?????0-?? 1-????????  ?????   ?????XYZ}
    {3+i,1,70,0,0.948,0,0.316},
    --{rightTop??  ?????0-?? 1-????????  ?????   ?????XYZ}
    {5+i,1,70,0,-0.948,0,0.316},
    --{leftTopDown??  ?????0-?? 1-????????  ?????   ?????XYZ}
    {4+i,1,-80,-80,0.948,0,0.316},
    --{rightTopDown??  ?????0-?? 1-????????  ?????   ?????XYZ}
    {6+i,1,80,80,-0.948,0,0.316},
    --{?????  ?????0-?? 1-????????  ?????   ?????XYZ}
    {7+i,1,20,0,1,0,0},
    --{?????  ?????0-?? 1-????????  ?????   ?????XYZ}
    {9+i,1,-50,0,1,0,0},
    --{?????  ?????0-?? 1-????????  ?????   ?????XYZ}
    {8+i,1,0,90,1,0,0},
    --{????  ?????0-?? 1-????????  ?????   ?????XYZ}
    {12+i,1,10,0,1,0,0},}
    
    self.acArray[4].totalStep = self.count
    self.acArray[4].data = {
    --{body??,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {1+i,0,0,0,0,0,0,0},
    --{body??,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {1+i,1,10,10,1,0,0},
    --{leftTop??,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {3+i,1,0,-70,0.948,0,0.316},
    --{rightTop??,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {5+i,1,0,-70,-0.948,0,0.316},
    --{leftTopDown??, ?????0-?? 1-???,?????, ?????, ?????XYZ}
    {4+i,1,-80,-80,0.948,0,0.316},
    --{rightTopDown??, ?????0-?? 1-???,?????, ?????, ?????XYZ}
    {6+i,1,80,80,-0.948,0,0.316},
    --{?????,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {7+i,1,0,-50,1,0,0},
    --{?????,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {9+i,1,0,20,1,0,0},
    --{?????,  ?????0-?? 1-????????  ?????   ?????XYZ}
    {8+i,1,90,0,1,0,0},
    --{????  ?????0-?? 1-????????  ?????, ?????XYZ}    
    {11+i,1,0,10,1,0,0},}
    
end

--# Action
Action = class()

function Action:init()
    self.data = {{},{},{},{},{},{},{},{},{},{}}
    self.totalStep = 0
end

It is just a prototype. B)

Wow nice work!

@Simeon Glad to hear that!
The next I will try to use pure Craft properties and methods to calculate without mesh and matrix.
But before this, I need to learn more about Craft …