This class takes a craft model and creates a new craft entity which has as its children models of all the triangles which constituent the original model. If the explode parameter is set true, each triangle is given a random velocity and rotation and its trajectory will evolve following the specified gravity.
As one might expect it is quite cpu intensive, but could be ok if you want to explode small models. If anyone has idea to improve the speed let me know!
-- craft model disintegration
-- PiInTheSky, 15 july 2020
-- displayMode (FULLSCREEN_NO_BUTTONS)
displayMode (OVERLAY)
-- displayMode (FULLSCREEN)
function setup()
fps=120
parameter.watch("fpsstr")
parameter.watch("memory")
parameter.integer("tdirection",-1,1,1)
parameter.number("gScale",0.,1.,0.1)
-- Create a new craft scene
scene = craft.scene()
scene.farPlane=10000
scene.nearPlane=0
--orbital viewer
orv=scene.camera:add(OrbitViewer, vec3(0,0,0), 400, 0, 2000)
--model
myModel=scene:entity()
myModel.active=true
myModel.model = craft.model(asset.builtin.Primitives.Sphere)
-- myModel.model = craft.model(asset.builtin.Primitives.Monkey)
myModel.scale=vec3(1,1,1)*20
myModel.position=vec3(50,100,0)
myModel.eulerAngles=vec3(0,180,0)
myModelTriangles=makeTriangles(myModel)
myModelTriangles.ent.scale=vec3(1,1,1)*20
myModelTriangles.ent.position=vec3(-50,100,0)
myModelTriangles.ent.active=true
parameter.boolean("explode",false, function(s) myModelTriangles.explode=s end)
end
makeTriangles=class()
function makeTriangles:init(originalEnt)
self.originalEnt=originalEnt
self.allTs={}
self.t=0
self.endt=5
self.explode=false
self.sampling=1
self.destroyAtEnd=false
local originalModel=self.originalEnt.model
local vCount=originalModel.vertexCount
local iCount=originalModel.indexCount
self.nTriangles=iCount/(3*self.sampling)
print("vertex Count ",vCount)
print("index Count ",iCount)
print("no of triangles ",self.nTriangles/self.sampling)
--parent entity of all the children triangles
self.ent=scene:entity()
self.ent.active=true
self.ent.scale=self.originalEnt.scale
self.ent.position=self.originalEnt.position
self.ent.eulerAngles=self.originalEnt.eulerAngles
--loop over indices to make the triangle models
local i
local step=3*self.sampling
for i=1, iCount, step do
self:createTriangle(i)
end
return self
end
function makeTriangles:createTriangle(i)
local originalModel=self.originalEnt.model
local i1=originalModel.indices[i]
local i2=originalModel.indices[i+1]
local i3=originalModel.indices[i+2]
local p1=originalModel.positions[i1]
local p2=originalModel.positions[i2]
local p3=originalModel.positions[i3]
local n1=originalModel.normals[i1]
local n2=originalModel.normals[i2]
local n3=originalModel.normals[i3]
-- local c1=originalModel.colors[i1]
-- local c2=originalModel.colors[i2]
-- local c3=originalModel.colors[i3]
-- print(c1,c2,c3)
--centre of mass position
local pcom=(p1+p2+p3)/3
p1=p1-pcom
p2=p2-pcom
p3=p3-pcom
local tri=scene:entity()
tri.parent=self.ent
tri.active=true
tri.model=craft.model()
tri.model.indices ={1,2,3, 3,2,1}
tri.model.positions= {p1,p2,p3, p1,p2,p3}
tri.model.normals= {n1,n2,n3, n1,n2,n3}
-- tri.model.colors={c1,c2,c3, c1,c2,c3}
tri.material = craft.material(asset.builtin.Materials.Standard)
tri.position=pcom
tri.material.diffuse=color(238, 59, 185)
tri.velocity=vec3(math.random()-0.5, math.random()-0.5, math.random()-0.5)*2
tri.deltaQuatScale=5
tri.deltaQuat=quat.eulerAngles( (math.random()-0.5)*tri.deltaQuatScale,
(math.random()-0.5)*tri.deltaQuatScale,
(math.random()-0.5)*tri.deltaQuatScale )
table.insert(self.allTs,tri)
end
function makeTriangles:update()
local g=vec3(0,-10,0)*gScale
local dt=DeltaTime*tdirection
if self.explode then
self.t=self.t+dt
local nTriangles=self.nTriangles
local i
for i =1, nTriangles do
local thisT=self.allTs[i]
local newv=thisT.velocity+g*dt
thisT.velocity=newv
thisT.position=thisT.position+newv*dt
thisT.rotation=thisT.rotation*thisT.deltaQuat
end
if self.t>self.endt then
print("stop exploding")
self.explode=false
if self.destroyAtEnd then
for i =1, nTriangles do
self.allTs[i]:destroy()
end
collectgarbage()
end
end
end
end
function update(dt)
memory = string.format("%.3f Mb",collectgarbage("count")/1024)
myModelTriangles:update()
scene:update(dt)
end
function draw()
update(DeltaTime)
scene:draw()
--frames per second
myfps(WIDTH*0.9,HEIGHT*0.9)
end
function touched(touch)
orv:touched(touch)
end
function myfps(x,y)
fps=fps*0.9+0.1/DeltaTime
fpsstr=string.format("%.0f",fps)
text("fps="..fpsstr,x,y)
end