Rotating mesh vertices

I’m trying to write some code in order to combine multiple meshes with separate rotation and translation values together but with great difficulty. I was wondering if anyone knew how to do it. Here is example code without rotation or translation added.


`verticesCollect = {}

--rotation
r = {vec3(45, 0, 45), vec3(20, 75, 0), vec3(67, 99, 15)}
--translation
t = {vec3(50, 0, 50), vec3(-50, -50, 0), vec3(-50, 0, 50)}
--start points
s = {vec3(-10, -10, -10), vec3(-25, -25, -25), vec3(-10, -25, -5)}
--end points
e = {vec3(10, 10, 10), vec3(25, 25, 25), vec3(10, 25, 5)}

for k = 1,3 do
    local vertices = {
        vec3(s[k].x,s[k].y,s[k].z), vec3(e[k].x,s[k].y,e[k].z), vec3(e[k].x,s[k].y,s[k].z),
        vec3(s[k].x,s[k].y,s[k].z), vec3(e[k].x,s[k].y,e[k].z), vec3(s[k].x,s[k].y,e[k].z),
            
        vec3(s[k].x,e[k].y,s[k].z), vec3(e[k].x,e[k].y,e[k].z), vec3(e[k].x,e[k].y,s[k].z),
        vec3(s[k].x,e[k].y,s[k].z), vec3(e[k].x,e[k].y,e[k].z), vec3(s[k].x,e[k].y,e[k].z),
            
        vec3(s[k].x,s[k].y,s[k].z), vec3(e[k].x,e[k].y,s[k].z), vec3(e[k].x,s[k].y,s[k].z),
        vec3(s[k].x,s[k].y,s[k].z), vec3(e[k].x,e[k].y,s[k].z), vec3(s[k].x,e[k].y,s[k].z),
            
        vec3(s[k].x,s[k].y,s[k].z), vec3(s[k].x,e[k].y,e[k].z), vec3(s[k].x,e[k].y,s[k].z),
        vec3(s[k].x,s[k].y,s[k].z), vec3(s[k].x,e[k].y,e[k].z), vec3(s[k].x,s[k].y,e[k].z),
            
        vec3(e[k].x,e[k].y,e[k].z), vec3(e[k].x,e[k].y,s[k].z), vec3(e[k].x,s[k].y,s[k].z),
        vec3(e[k].x,e[k].y,e[k].z), vec3(e[k].x,s[k].y,e[k].z), vec3(e[k].x,s[k].y,s[k].z),
            
        vec3(s[k].x,s[k].y,e[k].z), vec3(e[k].x,s[k].y,e[k].z), vec3(e[k].x,e[k].y,e[k].z),
        vec3(e[k].x,e[k].y,e[k].z), vec3(s[k].x,e[k].y,e[k].z), vec3(s[k].x,s[k].y,e[k].z)
    }
    for v,_ in pairs(vertices) do
        table.insert(verticesCollect, vertices[v])
    end
end

finalMesh = mesh()
finalMesh.vertices = verticesCollect`

@Athalax I’m not sure what you’re trying to do. I see you have rotation and start and end points. Just going by your comments, here’s some code that showns 2 meshes rotating at different speeds and moving in different directions.

EDIT: You might be able to include tweens to control the rotation and moving from a start to end points.

function setup()
    tab={}
    table.insert(tab,mesh2(vec2(0,0),vec2(100,0),vec2(0,100),
        color(255, 0, 188, 255),color(195, 255, 0, 255),color(255, 36, 0, 255),200,100,2,1))
    table.insert(tab,mesh2(vec2(0,0),vec2(100,0),vec2(0,100),
        color(0, 23, 255, 255),color(255, 0, 99, 255),color(76, 255, 0, 255),200,HEIGHT-100,4,-1))
end

function draw()
    background(40, 40, 50)
    for a,b in pairs(tab) do
        b:draw() 
    end 
end

mesh2 = class()

function mesh2:init(p1,p2,p3,c1,c2,c3,x,y,sp,dy)
    self.m=mesh()
    self.m.vertices={p1,p2,p3}
    self.m:setColors(255,255,255)
    self.m:color(1,c1)
    self.m:color(2,c2)
    self.m:color(3,c3)
    self.rot=0
    self.sp=sp
    self.x=x
    self.dy=dy
    self.y=y
end

function mesh2:draw()
    pushMatrix()
    self.y=self.y+self.dy
    translate(self.x,self.y)
    self.rot=self.rot+self.sp
    rotate(self.rot)
    self.m:draw()
    popMatrix()
end

@Athalax Here’s my above code where I control the movement and rotation of the meshes using tweens. Looking at your code, I think this might be what you’re trying to do.

function setup()
    tw1={x=100,y=100,r=0}
    tween(5,tw1,{x=100,y=800,r=360},{loop=tween.loop.pingpong})
    tw2={x=400,y=HEIGHT-100,r=0}
    tween(2,tw2,{x=400,y=100,r=720},{loop=tween.loop.pingpong})
    
    tab={}
    table.insert(tab,mesh2(vec2(-66,-33),vec2(34,-33),vec2(34,67),
        color(255, 0, 188, 255),color(195, 255, 0, 255),color(255, 36, 0, 255),tw1))
    table.insert(tab,mesh2(vec2(-66,-33),vec2(34,-33),vec2(34,67),
        color(0, 255, 148, 255),color(255, 0, 61, 255),color(0, 45, 255, 255),tw2))
end

function draw()
    background(40, 40, 50)
    for a,b in pairs(tab) do
        b:draw() 
    end 
end

mesh2 = class()

function mesh2:init(p1,p2,p3,c1,c2,c3,tw)
    self.m=mesh()
    self.m.vertices={p1,p2,p3}
    self.m:setColors(255,255,255)
    self.m:color(1,c1)
    self.m:color(2,c2)
    self.m:color(3,c3)
    self.tw=tw
end

function mesh2:draw()
    pushMatrix()
    translate(self.tw.x,self.tw.y)
    rotate(self.tw.r)
    self.m:draw()
    popMatrix()
end

Sorry if I wasn’t clear, I’m trying to increase framerate by, instead of drawing each part of the mesh individually and then rotating and translating them, I want to join each part of the mesh together into one big mesh. The start and end points mean bottom and top corners of each mesh and the rotation & translation values are static.

@Athalax Here is an example of joining the vertices of two meshes with different trasforms together. The meshes are nothing fancy, but hopefully its enough to give you the idea :slight_smile:

Depending on your usage it may or may not help your framerate. You may want to consider other approaches like culling as well. Make sure you profile in some way so that you can see that your changes are truely making a difference to performance.

It works by constructing a transform matrix for each mesh which is then applied to the mesh’s vertices by multiplying them with the matrix before adding them into the combined mesh.

The multiplication of the mesh’s vertices is essentially the same thing that Codea does behind the scenes to draw a mesh when you use the translate/rotate/scale functions followed by mesh.draw. Except because we are doing our drawing inside annother mesh (kind of) we need to do this ourselves.

A few things to watch out for:

  • The order of multiplying the scale, rotation and translation matrices matters.
  • Rotation assumes the centre of a mesh’s rotation is at 0,0,0 in the local/object coordinates system. (The centre of the mesh is at origin in context to its vertices).
  • Matrix * vec3 is valid, vec3 * Matrix will cause a runtime error
  • Textures will also need to be combined into a single image asset

CombineMeshTest = class()

function CombineMeshTest:init()
    
    local w,h = 32,32
    
    local m1 = {
        vec3(-w,0,h),
        vec3(-w,0,-h),
        vec3(w,0,-h),
        
        vec3(-w,0,h),
        vec3(w,0,-h),
        vec3(w,0,h),
    }
    -- create transformation matrix with the position, rotation (in degrees) and scale
    local m1Matrix = self:getMatrix(vec3(0,-16,0),vec3(0,0,0),vec3(1,1,1))
    
    local m2 = {
        vec3(-w,0,h),
        vec3(-w,0,-h),
        vec3(w,0,-h),
        
        vec3(-w,0,h),
        vec3(w,0,-h),
        vec3(w,0,h),
    }
    -- create transformation matrix with the position, rotation (in degrees) and scale
    local m2Matrix = self:getMatrix(vec3(0,16,0),vec3(0,45,0),vec3(1,1,1))
    
    -- combine
    local combined = {}
    for i,v in ipairs(m1) do
        table.insert(combined,m1Matrix * v)
    end
    
    for i,v in ipairs(m2) do
        table.insert(combined,m2Matrix * v)
    end
    
    self.mesh = mesh()
    self.mesh.vertices = combined
end

-- The function chaining below is multipliying.
-- you can also use matrix1 * matrix2.
function CombineMeshTest:getMatrix(p,r,s)
    return matrix()
    :scale(s:unpack())
    :rotate(r.x,1,0,0)
    :rotate(r.y,0,1,0)
    :rotate(r.z,0,0,1)
    :translate(p:unpack())
end

function CombineMeshTest:draw()
    self.mesh:draw()
end

@Athalax See if you can use anything from the discussion shown below. It talks about making the frame rate higher for 3D games. I show a cube type object that was made from 714 meshes and then modified the code again so the object was made up of just 6 meshes. The frame rate increased back to 60 FPS.

https://codea.io/talk/discussion/7742/how-to-make-fps-higher-at-a-3d-game#latest

Thanks for the help!