How can I compute which side of my cube is up?

Blitz3D Forums/Blitz3D Programming/How can I compute which side of my cube is up?

Blitzplotter(Posted 2009) [#1]
I have been searching around for some examples of surfacecollision, can anyone please hi-light any examples of this code in action so I can work out which side of the cubes is 'up', the cubes when they are loaded each have separate sides as set by the default cube model within Ultimate Unwrap 3D.

I'll only be attempting to which side is up once the cubes are static.

[EDIT]


Stevie G(Posted 2009) [#2]
The side that is pointing up is the one whose normals , when transformed from local space to world space have a y component which is greater than 0 ( prob best to use .5 incase of any inaccuracies )

i.e.

tformnormal faceNx, faceNy, faceNz, CUBEmesh, 0
if tformedy() > .5
;this face is facing upwards
endif


Blitzplotter(Posted 2009) [#3]
Thanks Stevie, will try this out this morning, still loving the fact that yesterday I fancied generating a program to bounce some dice around.

Stevie, this is the code I've been attempting to use to calculate which side is up, however all seven dice seem to be reporting that faceNy is 'up'.

Below is how I am loading the cubes, the cubes have each side individually identified:

[EDIT]

[EDIT]


jfk EO-11110(Posted 2009) [#4]
Using the Normals is nice, of course, but a Caveman like me would rather simply check the Y position of the children (top, bottom, side etc.) and then declare the topmost as the side that faces upward. IF the pivots of the children are not on the sides, but all in the center of the cube then you may use some additional Pivots instead. Maybe not that elegant, but at least it follows the KISS philosophy. :)


Stevie G(Posted 2009) [#5]
@ Bp,

My example was partially pseudocode, you need to set the faceNx etc.. components yourself. I also assumed you didn't use children to represent the sides of the cube as you didn't make this clear in your original post.

I see that you load in children for each side which is a bit overkill if you ask me - in which case jfk's solution would probably be best.

Stevie


Panno(Posted 2009) [#6]
append a entity to each side from a cube (maybe a pivot) create a highpoint over the map (sun) and test the entitydistance from the pivots to the sun is annother way


Blitzplotter(Posted 2009) [#7]
@jFK, I will attempt to find the Y position of the children. I'm not sure where (if indeed there are any) pivots attached to the children, so I may add some additional pivots for each child and then see which has the highest Y position.

If I come unstuck attacking from trying to establish which has the highest Y co-ordinate then I will try Panno's suggestion.

@Stevie, I appreciate I might be overdoing it somewhat with children for each side, I have not set faceNx componenets before, although if you know of a good example displaying typical code which sets faceNx components I'd appreciate it(;-).

Thanks for the help, BP.


Stevie G(Posted 2009) [#8]
@ Bp,

I don't have time to go into the normals solution but assuming that the children have a local position which is offset against the parent mesh ( i.e. not 0,0,0 ) then you can use something like this ...

Function WhichFaceIsUp$( Count )

	HighestSide$ = ""
	BestHeight# = 0
	
	For side = 1 To 6
	
		child = GetChild( mesh_with_children( count ) , side )
		
		If EntityY( child, 1 ) > BestHeight
			HighestSide = EntityName( child )
			BestHeight = EntityY( child, 1 )
		EndIf
		
	Next
	
	Return HighestSide
	
End Function


It returns the Name of the side but you can change that to return the child pointer or it's side number and deal with it from there.

Stevie


Blitzplotter(Posted 2009) [#9]
@Stevie, thankyou very much, I tried briefly to marry up some pivots to my child sides prior to dinner this evening & was not having much success, I look forward to giving this a whirl when I get back on my Dev PC.

@jfk, was just impressing my daughter with my skill at being able to do one side (wow I here you cry) of a rubiks cube, I think I peaked at doing two sides of a cube tops when I was younger - evidence I'd too much more interesting stuff to do, erm like program battleships in Basic on a Spectrum. Had to try your version of blitzcube - quite impressive!


Blitzplotter(Posted 2009) [#10]
Hmm, I have discovered that I am successfully loading children of the mesh at load time and attempting to address the memory location of the child to an array.

However, the children of the mesh do not appear to inherit the co-ordinates of the parent mesh when it is positioned at run time, they simply stay at 0.0 which is causing a bit of a headache.

I've been inserting various debug to find out why the children do not seem to be inheriting the parent mesh attributes to no avail. I check that the parent has children assocaited with it at load time with:



Then I position the entities with:

For x=1 To 7
	
	PositionEntity mesh_with_children(x),(-60+(x*30)),-20,DiceStartz
	
	RotateEntity mesh_with_children(x),180,0,0  ;will this change dice side up - no
	
Next



Then when I check the location of the main die mesh & the associated childrens EntityY parameter what is returned is the main mesh outputs the co-ordinate which was set (-20), I have changed this to +20 now - however the children all reflect 0.0. Is there some command I need to execute to ensure the children are all updated at the same time as the main mesh ?

	
	
	dicetemp = FindChild(cube_mem(dice_x),"back_grp")
	
	Text 40,280,"Dice Number: "
	Text 180+(dice_x*60),280,dice_x
	
	Text 40,360+(Counts*44),"dicetemp EntityY = "
	Text 180+(dice_x*60),360,EntityY(dicetemp)
	
	
	Text 40,422,"top_side(Count) EntityY =    "
	Text 180+(dice_x*60),422,+EntityY( top_side(dice_x))
	;Text 40,444,"bottom_side(Count) EntityY = "+EntityY( bottom_side(dice_x))
	;Text 40,466,"left_side(Count) EntityY =   "+EntityY( left_side(dice_x))
	;Text 40,488,"right_side(Count) EntityY =  "+EntityY( right_side(dice_x))
	;Text 40,512,"back_side(Count) EntityY =   "+EntityY( back_side(dice_x))
	;Text 40,534,"front_side(Count) EntityY =  "+EntityY( front_side(dice_x))
	
	Text 40,310,"mesh_with_children(Count) EntityY = "
	Text 180+(dice_x*60),334,EntityY(mesh_with_children(dice_x))
	
	Flip
	
	WaitKey
	
Next




Blitzplotter(Posted 2009) [#11]
So seeing as my mesh's children are misbehaving can someone please show me an example of code that will allow me to append 6 entities to each cube in question, then all I should hopefully have to do is check which entity is the highest. Unless someone can tell me why my children are misbehaving.

I'm beginning to suspect I may have needed to do something else within UU3D to make the children attach to the main cube - or maybe some command in Blitz3D after I've found the children.

Or when a PositionEntity is called is it necessary to position the child meshes, I wouldn't have thought so....

useful threads:

http://www.blitzbasic.com/Community/posts.php?topic=83868#946841

beginning to wonder If I am experiencing the same issue as LunC within the following thread:

http://www.blitzbasic.com/Community/posts.php?topic=76352

Which may explain why I keep getting 0.0 for my childs - if they are all centred on the middle of the parent entity. How can I confirm all the children are slap bang in the middle of the parent as I suspect?


Blitzplotter(Posted 2009) [#12]
Have been working with the loop index code to determine which face is up & I may've had an epiphany (;-)

I think my logic which has resulted in the following debug results is sound, however it appears that after getchild is executed on a loaded mesh with respect to EntityY({child- side 3 for example}),1 then the subsequent EntityY on the remaining sides returns 0. I do not know the reason for this, but it causes an inherent problem with me trying to discern the different heights of different children of one cube.

I posted a modified version of Stevie's code below the image which displays the cubes sides debug info in the image.



I proved this by incrmeneting the loop original index value from 1 to 3, hence the reason why the third side of the cube is displaying a value for EntityY:

[EDIT]


I could not get an array to work inside a function so I'd to go all long hand:




Blitzplotter(Posted 2009) [#13]
This

Text 180+(dice_x*60),466,+(EntityY( bottom_side(dice_x), 1 ))

works better than this

Text 180+(dice_x*60),466,+(EntityY( bottom_side(dice_x))

And has indeed revealed that my child entities appear to be slap bang in the centre of my cubes.


Stevie G(Posted 2009) [#14]
Here is a demo using normals of a standard blitz cube and no child entities. I've used vertexcolor so that you can see what it's doing.

When you create and texture the cube in your modeller, you will know what value each side has so adjust the returned values to suit.

Graphics3D 640,480,32,1

Global DICE = DICEcreate()
Global LIGHT = CreateLight()
Global CAM = CreateCamera()
PositionEntity CAM, 0,0,-5

While Not KeyHit(1)

	TurnEntity DICE, .05, 0, .05

	RenderWorld()
	
	Color 255,255,255
	Text 0,0, "The Dice Value is : " + DICEvalue( DICE )
	Color 255,0,0 : Text 0,30,  "Top:    1"
	Color 0,0,255 : Text 0,40,  "Bottom: 6"
	Color 0,255,255 : Text 0,50,"Right:  2"
	Color 255,255,0 : Text 0,60,"Left:   5"
	Color 0,255,0 : Text 0,70,  "Front:  3"
	Color 128,0,128 : Text 0,80,"Rear:   4"
	
	Flip
	
Wend

;====================================================================
;====================================================================
;====================================================================

Function DICEvalue( mesh )

	BestVert = - 1
	BestHeight# = 0

	s = GetSurface( mesh, 1 )
	For t = 0 To CountTriangles( s ) - 1 Step 2
		v0 = TriangleVertex( s, t, 0 )
		TFormNormal VertexNX( s, v0 ) , VertexNY( s, v0 ), VertexNZ( s, v0 ), mesh, 0
		If TFormedY() > BestHeight
			BestHeight = TFormedY()
			BestVert = v0
		EndIf
	Next
	
	If VertexNY( s, BestVert ) = 1 Value = 1	;Top
	If VertexNY( s, BestVert ) = - 1 Value = 6 	;Bottom
	If VertexNX( s, BestVert ) = 1 Value = 2	;Right
	If VertexNX( s, BestVert ) = - 1 Value = 5	;Left
	If VertexNZ( s, BestVert ) = 1 Value = 3	;Front
	If VertexNZ( s, BestVert ) = - 1 Value = 4	;Rear

	Return Value

End Function

;====================================================================
;====================================================================
;====================================================================

Function DICEcreate()

	mesh = CreateCube()
	EntityFX mesh, 2+4

	s = GetSurface( mesh, 1 )
	For v = 0 To CountVertices(s)-1
		If VertexNY( s, v ) = 1 VertexColor s, v, 255,0,0
		If VertexNY( s, v ) = - 1 VertexColor s, v, 0,0,255
		If VertexNX( s, v ) = 1 VertexColor s, v, 0,255,255
		If VertexNX( s, v ) = - 1 VertexColor s, v, 255,255,0	
		If VertexNZ( s, v ) = 1 VertexColor s, v, 0,255,0
		If VertexNZ( s, v ) = - 1 VertexColor s, v, 128,0,128
	Next

	Return mesh

End Function



Blitzplotter(Posted 2009) [#15]
Thanks Stevie, I will give this a try shortly - I really appreciate the assistance. I was kind of reaching the banging my head against the monitor stage - hypothetically speaking (;-)

Have just tried it on the laptop - thanks Stevie, this will be priceless with helping to develop my knowledge with respect to entity manipulation.

I implemented the code within my main dice manipulator, alas when I assign any mesh to an ODE/mesh it loses the ability for info to be extracted regarding which side is up. It has got me contemplating the nuances of applying gravitational math, that'll be physics to the cubes to retain the ability to establish which way is up. Whilst the challenge of invoking some basic (erm, not so basic really) gravitational and rotational velocity to the cubes mathematically, I passed my O level physics but that was 22 years ago - I'm not up to it at the moment.


jfk EO-11110(Posted 2009) [#16]
I was AFK, kind of. Thanks for what you said about the blitzcube. This was a nice finger exercise :) Something that can be finished in a few days, unlike fullfledged game projects, like fps or so.

Again, the cube problem. Let me suggest: when using pivots, since they are invisible, you may use CreateCube instead and alter it to CreatePivot later, when everything works. Just scale the cubes very small. Position them, parent them to the Dice, on the sides etc. They even don't have to be placed correctly on the surface, it's only important that they are aligned correctly. EG:
dim piv(5)
for i=0 to 5
 piv(i)=createcube()
 scaleentity piv(i),0.1,0.1,0.1
 entityparent piv(i),dice
next

translateentity piv(0), 1, 0, 0
translateentity piv(1),-1, 0, 0
translateentity piv(2), 0, 1, 0
translateentity piv(3), 0,-1, 0
translateentity piv(4), 0, 0, 1
translateentity piv(5), 0, 0,-1

I don't know, if ODE works together with Blitzs Entity Hierarchies. But if ODE doesn't move the children, then you maybe have to cheat somehow. Not sure if UpdateWorld is required here.
Oh, and if your mesh is loaded with an offset center (you said something about -20 ??) then you may use a command like FitMesh to reset the center Pivot. And I think you don't have to use LoadAnimMesh (if you don't really need to identify the sides by their names - I don't know if this is mandatory. If the sides are always the same then I think it's not neccessary)

To check what side is up you only have to filter the topmost pivot out. eg:

thisit=-1
top_y#=-1000

for i=0 to 5
 y#=entityy(piv(i),1)
if y>top_y# then
  top_y#=y
  thisit=i
 endif
next

now the variable thisit should hold the number of the side that is up.
You may use an additional array, like dim piv_name$(5) and name them accordingly in the creation loop.

BTW if the eyes of the dice correspond with the indicies the way I created them - I guess no :) but I think you can fix that easily, with some fiddling.

Hope this helps. Stevies Solution looks pretty good. You have the choice :)


Blitzplotter(Posted 2009) [#17]
@jfk, thanks for the alternative suggestion - will try this out tomorrow now that I've resolved my minor problem where IDEal wouldn't start, no Microsoft application wanted to start with various cryptic error messages, my wifes camera wouldn't connect to the PC - needed to delete a file buried in the registry to permit the RPCServer to start.

So, it wasn't really a minor problem - due to the fact I'm studying programming with the Open University and my Msoft IDE would not start. Happy dayz ;) Have had an initial stab at your pivot code - it certainly looks promising - thanks for the extra clarification from your initial post - the prospect of generating my own physics code was not overly appealing but now I've slept on it I do like a challenge! I really hope I can attach some pivots & cheat with the ODE mesh cubes - all in good time.


Blitzplotter(Posted 2009) [#18]
I've made an initial stab at understanding the pivot angle of attack, however I have discovered some confusing results. For some reason some pivots are never considered as 'highest', I need to do some more analysis. Here is the code so far:




Stevie G(Posted 2009) [#19]
@ Bp, you have a habbit of repeating code unnecessarily ;)

This is all you need:

thisit=-1
	top_y#=-1000
	
	For i = 0 To 5
		y# = EntityY( piv(i) , 1 )
		If y > top_y# Then
			top_y# = y       
			thisit = i
		EndIf
	Next
	
	For i = 0 To 5
		If thisit = i
			EntityColor piv(i), 255,0,0
		Else
			EntityColor piv(i), 255,255,255
		EndIf
	Next
		



Blitzplotter(Posted 2009) [#20]
@Stevie, thanks, my debug has a way of running away with itself and ends up overcomplicating stuff.

That works a treat on both the cubes created & the ODE/mesh cubes. ;)

I've just got to check out fitmesh to re-centre the model I am using.