Positioning a Cylinder between two spheres,
BlitzMax Forums/MiniB3D Module/Positioning a Cylinder between two spheres,
| ||
Hi, This is my first 3D project and I'm having a problem positioning a cylinder between two spheres. I seem to have a mental block on this! I've calculated the length of the Cylinder as the distance between the two spheres and calculated a vector to rotate it, but how do I calculate where it should be positioned? The code below is what I am using to test it, but even without positioning the angle of the cylinder just looks wrong! What am I doing wrong? |
| ||
Draw one endpoint of the cylinder at the center of one of the spheres, and if the rotation and such is correct the other end should automagically end up in the other sphere? |
| ||
Calculating position between objects is the easy bit, rotation is hard. I calculated the midway points and then used PointEntity to rotate it. To point it the other way you could use RotateMesh to realign the cylinder's mesh but this function is only in Openb3d.SuperStrict Import sidesign.minib3d Const MODE_FULLSCREEN% = 1 Const MODE_WINDOWED% = 2 Global width%=800, height%=600, depth%=0, Mode%=MODE_WINDOWED Graphics3D width, height, depth, Mode Local camera:TCamera = CreateCamera() PositionEntity camera,0,0,-10 Local light:TLight =CreateLight() RotateEntity light,90,0,0 Global sender:TEntity = CreateSphere() Global recipient:TEntity = CreateSphere() Global Line:TEntity = CreateCylinder() EntityColor Line, $FF, $FF, $ff EntityColor sender, $FF, $99, $99 EntityColor recipient, $99, $FF, $99 positionSpheres( Sender, Recipient, Line ) While Not KeyDown( KEY_ESCAPE ) If KeyHit(KEY_SPACE) Then positionSpheres( Sender, Recipient, Line ) RenderWorld Text 0,0,"Press space to refresh, Escape to exit" Flip Wend End Function positionSpheres( Sender:TEntity Var, Recipient:TEntity Var, Line:TEntity Var ) Local length:Float '# Reposition the Spheres PositionEntity sender, RndFloat()*20-10, RndFloat()*20-10, RndFloat()*10+3 PositionEntity recipient, RndFloat()*20-10, RndFloat()*20-10, RndFloat()*10+3 '# Position Line (Cylinder) between two spheres ' Length should be the distance between the two spheres ' length = Sqr( (EntityX(Recipient)-EntityX(Sender))^2 + (EntityY(Recipient)-EntityY(Sender))^2 + (EntityZ(Recipient)-EntityZ(Sender))^2 ) length = EntityDistance( Sender, Recipient ) ScaleEntity Line, 0.05, length, 0.05 ' Rotate cylinder to match vector between to spheres Local vx# = Abs(EntityX( sender ) - EntityX( recipient ))/2 Local vy# = Abs(EntityY( sender ) - EntityY( recipient ))/2 Local vz# = Abs(EntityZ( sender ) - EntityZ( recipient ))/2 Local lx#,ly#,lz# If EntityX( sender ) > EntityX( recipient ) ; lx=EntityX( recipient ) ; Else ; lx=EntityX( sender ) If EntityY( sender ) > EntityY( recipient ) ; ly=EntityY( recipient ) ; Else ; ly=EntityY( sender ) If EntityZ( sender ) > EntityZ( recipient ) ; lz=EntityZ( recipient ) ; Else ; lz=EntityZ( sender ) PositionEntity Line, lx+vx,ly+vy,lz+vz PointEntity Line,sender End Function |
| ||
It's been a few weeks since I last took a look at this code, but this evening I fixed it and thought I would share it back here for others. It seems that when a Cylinder or Cone is created, it stands vertical on the Y axis. PointEntity() uses the Z axis, so I added a 90 degree rotation after creation and it worked... SuperStrict Import sidesign.minib3d SeedRnd( MilliSecs() ) Const MODE_FULLSCREEN% = 1 Const MODE_WINDOWED% = 2 Global width%=800, height%=600, depth%=32, mode%=MODE_WINDOWED Graphics3D width, height, depth, mode Local camera:TCamera = CreateCamera() PositionEntity camera,0,0,-10 Local light:TLight =CreateLight() RotateEntity light,90,0,0 Global sender:TMesh = createSphere() Global recipient:TMesh = createSphere() Global line:TMesh = createCylinder() entitycolor Line, $FF, $0, $0 RotateMesh Line, 90.0, 0.0, 0.0 positionSpheres( Sender, Recipient, Line ) While Not KeyDown( KEY_ESCAPE ) If KeyHit(KEY_SPACE) Then positionSpheres( Sender, Recipient, Line ) RenderWorld Text 0,0,"Press space to refresh, Escape to exit" Flip Wend End Function positionSpheres( Sender:TMesh Var, Recipient:TMesh Var, Line:TMesh Var ) Local length:Float '# Reposition the Spheres PositionEntity sender, RndFloat()*20-10, RndFloat()*20-10, RndFloat()*10+3 PositionEntity recipient, RndFloat()*20-10, RndFloat()*20-10, RndFloat()*10+3 ' Calculate the length of the Line as the distance between the two spheres length = entitydistance( Sender, Recipient ) /2 ScaleEntity Line, 0.25, 0.25, Length ' Positon cylinder half way between two spheres Local vx# = EntityX( sender ) + ( EntityX( recipient ) - EntityX( sender ) )/2 Local vy# = EntityY( sender ) + ( EntityY( recipient ) - EntityY( sender ) )/2 Local vz# = EntityZ( sender ) + ( EntityZ( recipient ) - EntityZ( sender ) )/2 positionEntity Line, vx, vy, vz ' Rotate the line so that it joins the two spheres together PointEntity Line, sender End Function |