Musings of a Fondue

Particles and SketchUp Shenanigans

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.

The model on Threejs,

Particles extracted,

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.

Comments