Particles are cool! Example,
I had this idea back in 2014 of getting the points from premade 3D models (similar to the video above), and using them to do fancy animations in Threejs. Then I hit a knowledge wall and shelved it. Until today…
Part 1) Getting the particles
At the time, I was using SketchUp and had downloaded some freely shared models I wanted to work with. SketchUp has no built in method for exporting points but googling led me to TIG’s homebrew script Export Vertices to CSV. The script returns all the vertices of a given selection when the selection is a face or an edge. However, the models I was working with were complex and consisted of multiple faces and edges nested in groups upon groups. It would have been impossibly tedious to traverse each of these nested groups and individually select the faces and edges within (not to mention the high likelihood of missing some).
So I opened up TIG’s script in a text editor and got to work. Luckily, the script was written in Ruby, a language I was somewhat familiar with. I tweaked the code so that it did the tree traversal for me (into and out of the various nested groups (branches) to reach the faces and edges at the tips (leaves)). This was accomplished through recursion.
def boildown( ents )
for e in ents
#base case
if e.class == Sketchup::Face or e.class == Sketchup::Edge
verts << e.vertices
#recursion case ... keep exploding until class is face/edge
elsif e.class == Sketchup::Group
boildown(e.entities)
elsif e.class == Sketchup::ComponentInstance
boildown(e.definition.entities)
end
end
end
I got all the points, but something was clearly not right. It looked more like knolling than a model. It turned out the exported points did not include the transformations (scaling, translation, rotation) that had been applied at a group/component level using matrices. I had floundered through this Udacity course before so the use of transformation matrices wasn’t a completely foreign concept. But my understanding at the time wasn’t strong enough to implement the necessary codefu to the export script. And the project was put on hold.
Fast forward to 2016. And it occurred to me that I now know enough to tackle the challenge. This time around I was able to understand more of the SketchUp Documentation and exactly what each line in TIG’s code was accomplishing. In particular, re-reading the docs revealed that a built-in method already exists that applies a transformation to a point. (So there’s actually no need to understand how transforms are applied to a point nor to build your own method). The method is called by simply saying,
transformedPt = theTransformation * originalPt
After much code wrangling, I came up with the following code: Gist link. Specifically, I wrote everything in the getVerts
function. The end result is a modified version of TIG’s script that
- grabs the vertices from all the faces and edges in the model (whether selected, nested, or otherwise).
- and applies group and component level transforms to the vertices.
$verts = []
def getVerts( ents, transforms )
# === By JK ===
for e in ents
# Base case
if e.class == Sketchup::Face or e.class == Sketchup::Edge
# Apply transforms
if transforms.length > 0
e.vertices.each do |vert|
v = vert.position
transforms.reverse_each do |transform|
v = transform * v
end#do
$verts << v
end#do
# Else pass as is
else
e.vertices.each{ |vert| $verts << vert.position }
end#if
# Recursion case ... keep exploding until class is face/edge
elsif e.class == Sketchup::Group
puts "Found a group: " + e.name + "\n"
t = transforms.dup
t << e.transformation
puts "And it has this many transforms: " + t.length.to_s
getVerts( e.entities, t )
elsif e.class == Sketchup::ComponentInstance
puts "Found a component: " + e.name + "\n"
t = transforms.dup
t << e.transformation
puts "And it has this many transforms: " + t.length.to_s
getVerts( e.definition.entities, t )
end#if
end
end
You might ask yourself, all this for a bunch of dots? Really?
Yup! Cause dots are cool.
Part 2) Playing with particles
Here’s an example using this model by Katase.
Click the pictures below to open the respective programs. The controls are: left click and drag to rotate, right click and drag to pan, scroll to zoom.
Particles animated.
To see the animation, refresh the program. The program uses the buffer geometry code from my previous project.
Fancy fade between the particle and full model. Uses code from this awesome Threejs example.