Positioning a Cylinder between two spheres,

BlitzMax Forums/MiniB3D Module/Positioning a Cylinder between two spheres,

Scaremonger(Posted 2015) [#1]
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?




xlsior(Posted 2015) [#2]
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?


markcw(Posted 2015) [#3]
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




Scaremonger(Posted 2015) [#4]
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