sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Roller coaster animation - move TO and angle of edge

    Scheduled Pinned Locked Moved Developers' Forum
    2 Posts 2 Posters 485 Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • N Offline
      Nask
      last edited by

      Hi all,

      I am trying to make a model to animate a kind of roller coaster.

      Step 1: Select the cart and the path (loose edges) and define which is the cart and what are the edges.

      Step 2: Put the edges in order and put them in a array

      Step 3: Depending on the time, calculate where the cart should be on the track

      Step 4: Move the cart TO the start of the edge it should be

      Step 5: Move the cart BY the amount it has already travelled on the edge

      Step 6: Rotate the cart TO rotx,y,z = 0

      Step 7: Rotate the cart to match rotx, roty and rotz of the edge

      My problems start at step 5. I only know how to move by a certain amount, but not how to move to a certain point, whatever the start position was. I thought to do this using a Point3D instead of vector3d object, but this does not work.

      The same I have to solve for the rotation.

      Then the last question is whether you can get the angles of an edge in an easy way, so without calculating them from the coordinated of start and end point.

      Can you guys help me out here?

      See below the test code I wrote for the move TO and move BY

      model = Sketchup.active_model
      ents = model.entities
      face= ents.add_face [0,0,0],[5,0,0],[5,5,0], [0,5,0]
      face_group = ents.add_group face
      
      
      clock = 0
      
      timer_id = UI.start_timer(0.1, true) {
           
       if clock <= 100 
         vvMoveToPoint = [0,0,0]
         point = Geom;;Point3d.new vvMoveToPoint
         t1 = Geom;;Transformation.new point 
      
         vvMoveByVector = [clock/10,clock/10,0]
         vector= Geom;;Vector3d.new vvMoveByVector 
         t2 = Geom;;Transformation.new vector
      
         t_all = t1 * t2
      
         face_group = face_group.transform! t_all
      
       else
         UI.stop_timer timer_id
         puts "clock is larger than 5 " + clock.to_s
            
       end
      
         clock = clock + 1  
      }
      
      
      

      Here I laready tried things like changing the order of t1 and t2...

      EDIT: I now also tried to get the coordinates of the group with position, but that doesnt work, I have tried to make a bound for the group and get the position of the bound box, but that doesnt work neither. Maybe I have to save in a variable which tranlations and rotations I have done with the group, but that seems strange.. SU should have some information of where the group is, no??

      EDIT 2: I got the thing working, but with the method where I store the performed transformation in variables, to transform it back later. I supose there are better ways to do this, so I am open for suggestions... The challenge I have now is to introduce several carts that travel together, so I will be busy for a while..

      
      model = Sketchup.active_model
      ents2 = model.entities
      ents = model.selection # selection in future
      
      viNumberOfEdges = ents.count-1
      puts "NumberOfEdges" + viNumberOfEdges.to_s
      
      cart = ents.find { |ent| ent.typename.to_s == "ComponentInstance"}
      path = []
      path = ents
      
      path.remove [cart]
      
      vesPath = []
      
      path.each {|item|
      
      	if item.typename=="Edge"
      		vesPath = vesPath + [item]
      	end }
      
      
      puts "First element of vesPath" + vesPath[4].to_s
      
      vesOrderedPath = []
      
      vesOrderedPath = vesOrderedPath + [vesPath[0]] #First element has to be filled, but not used
      vesOrderedPath = vesOrderedPath + [vesPath[0]]
      
      vesPath = vesPath - [vesOrderedPath[1]]
      
      i = 1
      
      veLast = vesOrderedPath[1]
      
      while i <=  viNumberOfEdges
      
      	vvEnd = veLast.end
      	veNext = vesPath.find {|edge| edge.start == vvEnd || edge.end == vvEnd } 
      	vesOrderedPath = vesOrderedPath + [veNext]
      	vesPath = vesPath - [veNext]
      	veLast = veNext
      
      	i = i + 1
      end
      
      
      i = 1
      ents2 = model.entities
      vrsLength = [0]
      vrsLengthAcc = [0]
      vrTotalLength = 0.0
      vrLength = 0.0
      
      
      while i <= vesOrderedPath.size-2 
      	
      	vrLength = vesOrderedPath[i].length
      	vrsLength = vrsLength + [vrLength]
      	vrTotalLength = vrTotalLength + vrLength
      	vrsLengthAcc = vrsLengthAcc + [vrTotalLength]
      
      
      	i = i + 1
      end
      
      
       vrSpeed = 0.1
      
       posCartx = 0.0
       posCarty = 0.0
       posCartz = 0.0
      
       rotx = 0.0
       roty = 0.0
       rotz = 0.0
       clock = 0.0
      
       timer_id = UI.start_timer(0.5, true) {
        
      
      
       if clock <= 500 
      
      
      
      	# define vector to get back to origin
      	vvMoveToPoint = [-posCartx ,-posCarty ,-posCartz ]
      	point = Geom;;Point3d.new vvMoveToPoint
      	t0 = Geom;;Transformation.new point 
      
      	# define rotation back
      	trb_x = Geom;;Transformation.rotation [posCartx ,posCarty ,posCartz],
      													  [1, 0, 0],-rotx
      
      	
      	trb_z = Geom;;Transformation.rotation [posCartx ,posCarty ,posCartz],
      													[0, 0, 1],-rotz
      
      
      	# define starting point
      	
      		
      	vrDistInLap = clock*vrSpeed%vrTotalLength
      
      	vrTemp = vrsLengthAcc.find {|acc| acc>vrDistInLap}
      
      	viEdgeID = vrsLengthAcc.index vrTemp 
      
      	vrTravelledOnOtherEdges = vrsLengthAcc[viEdgeID -1]
      	vrTravelOnEdge = vrDistInLap - vrTravelledOnOtherEdges
      
      	veCurrentEdge = vesOrderedPath[viEdgeID] 
      
      	px = veCurrentEdge.start.position.x
      	py = veCurrentEdge.start.position.y
      	pz = veCurrentEdge.start.position.z
      
      
      	vvMoveToPoint = [px,py,pz]
      	point = Geom;;Point3d.new vvMoveToPoint
      	t1 = Geom;;Transformation.new point 
      
      	# update location
      	posCartx = px 
      	posCarty = py 
      	posCartz = pz 
      	
      	# define vector
         
      	factor = ( vrTravelOnEdge/ veCurrentEdge.length.to_inch)
      
          vx_tot = veCurrentEdge.end.position.x.to_inch - veCurrentEdge.start.position.x.to_inch
          vy_tot = veCurrentEdge.end.position.y.to_inch - veCurrentEdge.start.position.y.to_inch
          vz_tot = veCurrentEdge.end.position.z.to_inch - veCurrentEdge.start.position.z.to_inch
      
      	vx = vx_tot * factor
      	vy = vy_tot * factor
      	vz = vz_tot * factor
          
      
      	vvMoveByVector = [vx,vy,vz]
      	vector= Geom;;Vector3d.new vvMoveByVector 
      	t2 = Geom;;Transformation.new vector
      	
      	posCartx = posCartx + vx 
      	posCarty = posCarty + vy 
      	posCartz = posCartz + vz 
      
      	rotx = Math.asin(vz_tot/veCurrentEdge.length.to_inch)
      
      	tr_x = Geom;;Transformation.rotation [posCartx ,posCarty ,posCartz],
      													[1, 0, 0],rotx
      
      	rotz = Math.asin(vx_tot/veCurrentEdge.length.to_inch)
          if vy > 0 
      		rotz = -rotz
          end
          
      
      	tr_z = Geom;;Transformation.rotation [posCartx ,posCarty ,posCartz],
      													[0, 0, 1],rotz
      	
      
      
      	t_all = tr_z * tr_x * t2 * t1 * t0 * trb_x * trb_z
      
      	cart = cart.transform! t_all
      
      
      
       else
      	UI.stop_timer timer_id
      	puts "clock is larger than 5 " + clock.to_s
      		
       end
      
      	clock = clock + 1  
      }
      
      
      
      
      

      Code only works when you select one group (block that is centered on the origin) and a loop of edges before executing it

      1 Reply Last reply Reply Quote 0
      • M Offline
        MartinRinehart
        last edited by

        My tutorial, Chapter 16 has library code to handle this. You may be able to go straight to Chapter 16 and get your work done. But as TIG points out (reincarnated as the wise old one at the fairytale SketchUCation tavern) that has its drawbacks.

        Author, Edges to Rubies - The Complete SketchUp Tutorial at http://www.MartinRinehart.com/models/tutorial.

        1 Reply Last reply Reply Quote 0
        • 1 / 1
        • First post
          Last post
        Buy SketchPlus
        Buy SUbD
        Buy WrapR
        Buy eBook
        Buy Modelur
        Buy Vertex Tools
        Buy SketchCuisine
        Buy FormFonts

        Advertisement