I have quite a lot of code that is heavily invested in meshes which I’d like to adapt to use with Craft, so I came up with a little helper class that can be used as a drop-in for a mesh with a converter to a model for use with Craft.
Latest version can be found on github
PseudoMesh = class()
function PseudoMesh:init()
self.vertices = {}
self.texCoords = {}
self.normals = {}
self.colors = {}
self.size = 0
end
function PseudoMesh:vertex(k,v)
if v then
self.vertices[k] = v
else
return self.vertices[k]
end
end
function PseudoMesh:normal(k,v)
if v then
self.normals[k] = v
else
return self.normals[k]
end
end
function PseudoMesh:texCoord(k,v)
if v then
self.texCoords[k] = v
else
return self.texCoords[k]
end
end
function PseudoMesh:color(k,v)
if v then
self.colors[k] = v
else
return self.colors[k]
end
end
function PseudoMesh:resize(k)
self.size = k
end
function PseudoMesh:invertNormals()
for k,v in ipairs(self.normals) do
self.normals[k] = -v
end
end
function PseudoMesh:toModel()
local m = craft.model()
local i = {}
local n = #self.vertices
for k=1,n,3 do
if (self.vertices[k+1] - self.vertices[k]):cross(self.vertices[k+2] - self.vertices[k]):dot(self.normals[k+1] + self.normals[k+2] + self.normals[k]) < 0 then
table.insert(i,k)
table.insert(i,k+1)
table.insert(i,k+2)
else
table.insert(i,k)
table.insert(i,k+2)
table.insert(i,k+1)
end
end
m.positions = self.vertices
m.normals = self.normals
m.uvs = self.texCoords
m.colors = self.colors
m.indices = i
return m
end
Use as:
m = PseudoMesh()
-- set up m as if it were a mesh
e = scene:entity()
e.model = m:toModel()
The invertNormals
is because meshes would look the same from both sides but models are viewable from one only, so it may be that ones mesh is inside out. This flips it round.
As an example, I’ve adapted my old Roller Coaster code to Craft using this technique (@Simeon, @John would you consider replacing the old code with a Crafty update?).