Calculating the final vertices of a nested face
-
I've tried to boil this down to a small as example as possible, what I need to do is given a face, calculate it's absolute final position in XYZ (taking into account transforms, etc). It's for a paint tool I'm working on that works (and aligns regardless of grouping. I happen to use Sketchup for game mapping and the particulars of the exporter force pretty much everything to be a group.
A less than compelling example video of the paint tool http://www.youtube.com/watch?v=hb63D7Cmt50
I've mostly got it working, except for the origin is off when dealing with groups within groups, there is just something I'm not grokking here. So after many hours of head scratching, I figured I'd see if anyone can enlighten me.
So I take the face, I walk up the hierarchy, adding transforms, (and in theory, transformation origins) and compute the new points. The code below just adds the transformation.origin, I know this is wrong, and it's what trying to solve. I've tried a dozen things (transforming them by the container, etc,) but there is just something I'm not understanding.
Here's the code
module WALK def WALK.setface model = Sketchup.active_model @newg = model.entities.add_group @s = nil if model.selection.empty? UI.messagebox "Selection empty" return nil else if model.selection[0].is_a? Sketchup;;Face @s = model.selection[0] else UI.messagebox "Face not selected" end end end # make sure groups are unique Sketchup.active_model.definitions.each{|d|d.instances[1..-1].each{|i|i.make_unique}if d.group? and d.instances[1]} def WALK.main WALK.GetParent(@s) end def WALK.GetParent(ent) Sketchup.active_model.start_operation("Walk") model = Sketchup.active_model @newg = model.entities.add_group m = model.materials.add "test" m.color="red" orig = ent tpos = Geom;;Point3d.new 0,0,0 # keep track of origin trans = Geom;;Transformation.new(Geom;;Point3d.new(0,0,0)) # add transforms to this while (ent.respond_to?('parent') ) # walk up hierarchy if ((ent.is_a? Sketchup;;ComponentDefinition)) if ent.group? t = ent.instances[0].transformation # Get the group's transform tpos += t.origin.transform(trans).to_a # !!!WRONG trans *= t # combine transforms end ent = ent.instances[0] # become the instance end ent = ent.parent end vertices = orig.outer_loop.vertices newverts = [] vertices.each do |v| np = v.position.clone np+= tpos.to_a # !!! Wrong np.transform! trans newverts.push np end f = @newg.entities.add_face newverts # create the face f.material=m Sketchup.active_model.commit_operation end end # end mod if !file_loaded?(__FILE__) UI.menu("Plugins").add_item("Select Walk Face") { WALK.setface } UI.menu("Plugins").add_item("Make Walk Face") { WALK.main } end file_loaded(__FILE__)
It adds two items to the plugin menu
Select Walk Face and Make Walk FaceTake the example here
The geom looks like this...
Group
--Group
----Wide Cylinder faces
--Group
----Group
------Cube faces
----Group
------ Tall Cylinder FacesSeeing backing out of a group clears the selection, here's where Select Walk Face comes in. Click down into the inner group of the cube and select a face and then select Select Walk Face, this simply stashes the face for Make Walk Face
Now if you actually ran Make Walk Face here, it works fine, making a new face, respecting transforms and in the right place.
But back all the way out of the group and run Make Walk Face
and you get this....
If you've read this far, I commend you
Any insight on what I'm not understanding would truly be appreciated.
Thanks!
-Lee -
Have you tried
tr=container.transformation.inverse
and applying it to the initial object and then iterating and getting/setting the transformation for the container's container etc until you get to the model level... -
@tig said:
Have you tried
tr=container.transformation.inverse
and applying it to the initial object and then iterating and getting/setting the transformation for the container's container etc until you get to the model level...That didn't seem to work (inverse), though I may very well have misunderstood what you meant, but what you said gave me an answer anyway. By applying the transform to the points at each container successively, it works perfectly! (or at least in every test so far)
Which is how I should have tried it initially but I was thinking from a performance standpoint, and forgot the old adage "premature optimization is the root of all evil"
def WALK.GetParent(ent) Sketchup.active_model.start_operation("Walk") model = Sketchup.active_model @newg = model.entities.add_group m = model.materials.add "test" m.color="red" orig = ent tpos = Geom;;Point3d.new 0,0,0 # keep track of origin trans = Geom;;Transformation.new(Geom;;Point3d.new(0,0,0)) # add transforms to this vertices = orig.outer_loop.vertices.map {|v| v.position.clone} while (ent.respond_to?('parent') ) # walk up hierarchy if ((ent.is_a? Sketchup;;ComponentDefinition)) if ent.group? t = ent.instances[0].transformation # Get the group's transform vertices.each_with_index do |v,i| vertices[i].transform! t end end ent = ent.instances[0] # become the instance end ent = ent.parent end f = @newg.entities.add_face vertices # create the face f.material=m Sketchup.active_model.commit_operation end
Thanks again for the help!
Advertisement