Monday, May 7, 2012

Mech: Building the 3D simulator

I needed a 3D simulator. There are lots of programs that let you draw objects and place them. I didn't see offhand any that have the simulator compute the locations of things based on their distances from other things. And it would have taken me a while to find the right one with the right APIs so I just didn't.

Instead I'm making a 3D simulator. Like the 2D version I already made it computes locations based on relative distances from other locations. I've added compatibility with 2D as well as lines for convenience.

Today, I got it computing locations even for the complex 3D cases. The interesting part of this was doing a bunch of rotations until the points were in a plane where I could compute the solutions to them.

I solve the problem in two major parts. Each part is essentially solving for the intersection of two points. So let's say I have joints A,B,C and distance dA,dB,dC from the new joint D that we're going to place. I start with joint A and joint B. I solve for where D is relative to them. But in a 3D world that's actually a circle. Based on the location of C and dC I can find a specific point on the circle D. Below are the exact steps:

  • STEP 0: Copy initial points so they never drift with repeated transformations
  • STEP 1: Translate to make point 1 the origin
  • STEP 2: Rotate around Y axis till point 2 lies in Z=0 plane
  • STEP 3: Rotate around Z axis till point 2 lies in Y=0 plane (now must be on the X-axis)
  • STEP 4: Solve for point 4(new point)'s to find the X and Y. The X here will end up being the real X in this space. The Y is simply the radius.
  • STEP 5: The problem now starts over, remaking a new point A and B based on the X,Y we solved and point 3
  • STEP 6: Translate to make point newA's X=0
  • STEP 7: Rotate around Y axis 90 degrees to make the solution circle lie at Z=0
  • STEP 8: Rotate around Z axis till point newB lies on the Y=0 plane (it now must be on the X-axis)
  • STEP 9: Solve for point 4(new point)'s to find the new X and Y locations. The transformations we've already done will fill out all the other data found along the way.
  • STEP 10: Build the solution
  • STEP 11: Back out all transformations

If you spend a few minutes thinking about this, you'll notice that the points and distances is not enough to determine an exact point. It determines one of two points. As with the 2D system, I'm solving this by using the right hand rule. If you list the points clockwise from your perspective, whatever perspective you choose, the plane those points in will be between you and the new point. Take a sec to think about it.

To give an example test case I run:

#Test case: 3D joint

j = joint()

j.jointA = location(1.0,0,0)

j.jointB = location(0.0,1.0,0.0)

j.jointC = location(0.0,0.0,1.0)

j.spanA = span(1.0)

j.spanB = span(math.sqrt(1+1+1))

j.spanC = span(1.0)

j.computeLocation()

if(j.x > 1.01 or j.x < 0.99 or j.y > 0.01 or j.y < -0.01 or j.z > 1.01 or j.z < 0.99):

\t p = False

\t print "ERROR on test case 8: %s"%j.toString()

I've decided to call the new rendering and computing engine MindFuck3D. From this post, I hope you can begin to see why. Once I try to actually design in this new language I think it will really win it's name. It will be difficult to get good at but very quick and powerful once I have it down.

No comments:

Post a Comment