ScaleMesh() Question

Blitz3D Forums/Blitz3D Programming/ScaleMesh() Question

John Blackledge(Posted 2005) [#1]
I've been using ScaleMesh() to move to 'origin' of a mesh to its centre/bottom. (Simply to centre the mesh, scaling doesn't actually matter.)
It's been working fine.

Now I want to do the same with hierarchical meshes (with child entities) and unfortunately MeshWidth() etc returns
-2000000 or some such number.
I then tried to recurse through the children but of course scaling each of those meshes just produces nonsense.

Bearing in mind that the meshes are not my own (else there'd be no problem) but imported, does anyone have a technique or piece of code for doing this?


jfk EO-11110(Posted 2005) [#2]
To center a mesh I wouldn't use scaleMEsh at all, instead I'd use FitMesh:
Fitmesh mesh, -meshwidth(mesh)/2.0,-meshheight(mesh)/2.0,-meshdepth(mesh)/2.0,meshwidth(mesh),meshheight(mesh),meshdepth(mesh)

But of course, you still need to use MeshWidth here.

Once upon a time I used a radical method that used simple cubes and MeshesIntersect, so the cube did a binary search of the start and end of the mesh in x,y and z. If you compare this with the logical position of the entity, you'll know'll how you need to PositionMesh the children to center the entire thing.

Of course, a complicated method.


John Blackledge(Posted 2005) [#3]
That's easy for you to say - you're THE jfk!
Seriously, that's beyond me.

I guess from what you're saying is that simply doing
x = EntityX(childmesh1) etc for each child, then changing the positions based on that original info is not going to work.
Else you would have done it?
In fact, will x = EntityX(childmesh1) actually work? - I think I know ahead of time that it will return a message of 'childmesh1 is not an entity'.

It's a simple idea - changing the origin/rotation point of a mesh to centre/bottom for easier manipulation.
ScaleMesh or FitMesh allow this, no problem, but not if there are children.
This really is a stinker.


John Blackledge(Posted 2005) [#4]
Sorry. I'm just going to bump this once in the hope that someone can help me.

How can I centre a hierarchical mesh in the same way that we can centre a single mesh using FitMesh() or maybe another way?


Shambler(Posted 2005) [#5]
2 Kludges I know but...

You could traverse the children and modify each ones vertices directly to scale them.

Or you could traverse the mesh, copy each child, scale them, addmesh them to a new mesh and delete the original mesh (containing all the children) after you have finished...this probably destroys the hierarchy though =/

[Edit] This appears to work for me but then I may have got hold of the wrong end of the stick...wouldn't be the first time.

Function Mesh_Scale(mesh%)

Local childcount%=CountChildren(mesh%)
Local child%=0

;use either
ScaleMesh mesh%,Rnd(2)+1,1,Rnd(2)+1
;or
;If childcount%=0  ScaleEntity mesh,Rnd(2)+1,1,Rnd(2)+1

For child%=1 To childcount%
Mesh_Scale(GetChild(mesh%,child%))
Next

End Function 



Baystep Productions(Posted 2005) [#6]
PositionMesh works better.


John Blackledge(Posted 2005) [#7]
Yeah, I tried the recursive style you use Shambler, but since the logic was 'find the centre/bottom of the mesh', which therefore became 'each mesh', then the table top ended up on the floor (-well, that _is_ logical).

Wish it was that simple.

PCD Guy, FitMesh() allows positioning within the call, so that wasn't the problem.

Since in my app I want to be able to allow the import of eg .3DS files then tweak them to move the 'origin/rotation' point from whereever is was originally to bottom/centre, I was doing fine on single meshes, but hierarchical meshes defeat me.

When I try to think it through I get a headache.
I must admit I dread that the only answer is to do it vertex by vertex - I just hope someone has a simpler way.


big10p(Posted 2005) [#8]
Are you talking about animated meshes here, or just a bunch of meshes parented together?

MeshWidth() etc returns -2000000 or some such number.
Really? I just tried it on some cubes parented together and it seems to work. Are you saying MeshWidth() has a bug?


Shambler(Posted 2005) [#9]
I had recent experience of this and yes MeshWidth/Height/Depth all returned something like -2000000 for the root node of a mesh loaded with LoadAnimMesh.

Regarding the scalemesh on child entities...I think the mesh I used each child was parent to a pivot at the centre of that child...so you could try

1) Store the childs parent
2) Parent the child to a temporary pivot
3) Scalemesh
4) Parent the child back to its original parent
5) Delete the temporary pivot


John Blackledge(Posted 2005) [#10]
Thanks for confirming that Shambler.

I think you've described the obvious way to handle this (temporary pivots).
I'll give it a go, and let you know.


John Blackledge(Posted 2005) [#11]
Well, it's tearing hair out time!
I've simulated a hierarchical mesh by parenting 3 cubes to a sphere.
Then I try to get the position of each child (before I even begin to investigate Shambler's idea), and lo! X,Y,Z all return zero! How insane is that? It doesn't matter whether I use the True or False flag as you see below.
Please feel free to tell me I'm an idiot, but why can't I get the x,y,z of the children?
Graphics3D 800,600
SetBuffer BackBuffer()
camera=CreateCamera()
PositionEntity camera, 0,0,-5
light=CreateLight()
AmbientLight 200,200,200

Global piv =  CreateSphere() : EntityColor piv,255,255,0 : EntityAlpha piv,0.5
Global cube1=CreateCube() : EntityColor cube1,255,0,0 : EntityAlpha cube1,0.5
Global cube2=CreateCube() : EntityColor cube2,0,255,0 : EntityAlpha cube2,0.5
Global cube3=CreateCube() : EntityColor cube3,0,0,255 : EntityAlpha cube3,0.5
PositionMesh cube1, 1,1,1
PositionMesh cube2, 3,3,3
PositionMesh cube3, 5,5,5
EntityParent cube1,piv
EntityParent cube2,piv
EntityParent cube3,piv

While Not KeyDown(1)
	TurnEntity piv,1,1,1
	UpdateWorld
	RenderWorld
	info(piv)
	Flip
Wend
End

;-------------------------
Function info(piv)
;-------------------------
Local x#,y#,z#

	Color 255,255,255
	x# = EntityX#(piv)
	y# = EntityY#(piv)
	z# = EntityZ#(piv)
	ty = 0 : Text 0,ty,"Piv "+x#+" "+y#+" "+z#
	cc = CountChildren(piv)
	For c = 1 To cc
		childent = GetChild(piv,c)
		x# = EntityX#(childent,False)
		y# = EntityY#(childent,False)
		z# = EntityZ#(childent,False)
		ty = ty + 20 : Text 0,ty,Str$(c)+"false "+x#+" "+y#+" "+z#
		x# = EntityX#(childent,True)
		y# = EntityY#(childent,True)
		z# = EntityZ#(childent,True)
		ty = ty + 20 : Text 0,ty,Str$(c)+"true "+x#+" "+y#+" "+z#
	Next
End Function



big10p(Posted 2005) [#12]
but why can't I get the x,y,z of the children?
Because you're using PositionMesh instead of PositionEntity. PositionMesh moves all the verts - the the mesh origin stays where it is, hence EntityX/Y/Z all equal zero. :)


John Blackledge(Posted 2005) [#13]
Understood, Big10p.

Ok, forget my last post.
Let's simplify it.
Here's a hierarchical table mesh.
I can get the children and recolor them.
But EntityX() etc is telling me that the positions of each child as regards the parent are all the same!




Shambler(Posted 2005) [#14]
You have to use the global flag for Entityx/y/z i.e. EntityX(mesh%,1)

[Edit] Just read your post properly and you are using true...must have another think about this one lol

[Edit] Like big10p says, if you use positionentity then it should work.


John Blackledge(Posted 2005) [#15]
Shambler, as I said forget that last code.

Instead I've loaded in a 3rd party table whch more correctly illustrates the situation: the x,y,z of each child are meaningless.


John Blackledge(Posted 2005) [#16]
OK, people, I think I've cracked it.

This code can centre a hierarchical (multi-child) mesh, either dead-centre on 3 axes, or centred on x,z aligned to y-bottom.
A portion of Mr Pickelsworth's code from the archive has been used (thanks Mr.P)

I certainly wouldn't mind if a few people tried this out in situ, before I post it in the code archives.
As usual, thanks to everyone who chipped in on this one.
;
; Usage: CentreAnimMesh(mesh[,0/1])
;
;--------------------
Function CentreAnimMesh(mesh,mode=0)
;--------------------
; mode=0 : centre on 3 axes
; mode=1 : centre on x,z; align to y bottom
Local origx#,origy#,origz#
Local allx#,ally#,allz#
Local newx#,newy#,newz#
Local cc,c,childent,mult

	; get orig position
	origx# = EntityX#(mesh)
	origy# = EntityY#(mesh)
	origz# = EntityZ#(mesh)
	
	; get 'all' vertices positions
	allx# = MeshAllX#(mesh)
	If mode=0 Then ally# = MeshAllY#(mesh)
	If mode=1 Then ally# = MeshAllYlowest#(mesh)
	allz# = MeshAllZ#(mesh)

	; find difference
	newx# = (origx# - allx#)
	newy# = (origy# - ally#)
	newz# = (origz# - allz#)
	
	; move one or all meshes
	cc = CountChildren(mesh)
	If cc = 0
		PositionMesh mesh, newx#,newy#,newz#
	Else
		For c = 1 To cc
			childent = GetChild(mesh,c)
			mult = 2
			PositionMesh childent, mult * newx#,mult * newy#,mult * newz#
		Next
	EndIf

End Function

;--------------------
Function MeshAllX#(parent)
;--------------------
Local LeftX#,RightX#
Local cc,c,childent,vx#,x#

	cc = CountChildren(parent)
	If cc = 0
		x# = MeshX#(parent)
	Else
		For c = 1 To cc
			childent = GetChild(parent,c)
			vx# = MeshX#(childent)
			If vx#<LeftX# Then LeftX#=vx#
			If vx#>RightX# Then RightX#=vx#
		Next
		x# = LeftX# + ( (RightX# - LeftX#) / Float(2) )
	EndIf

Return x#
End Function

;--------------------
Function MeshAllY#(parent)
;--------------------
Local BottomY#,TopY#
Local cc,c,childent,vy#,y#

	cc = CountChildren(parent)
	If cc = 0
		y# = MeshY#(parent)
	Else
		For c = 1 To cc
			childent = GetChild(parent,c)
			vy# = MeshY#(childent)
			If vy#<BottomY# Then BottomY#=vy#
	    If vy#>TopY# Then TopY#=vy#
		Next
		y# = BottomY# + ( (TopY# - BottomY#) / Float(2) )
	EndIf

Return y#
End Function

;--------------------
Function MeshAllYlowest#(parent)
;--------------------
Local BottomY#,TopY#
Local cc,c,childent,vy#,y#

	cc = CountChildren(parent)
	If cc = 0
		y# = BottomMost#(parent)
	Else
		For c = 1 To cc
			childent = GetChild(parent,c)
			vy# = BottomMost#(childent)
			If vy#<BottomY# Then BottomY#=vy#
	    If vy#>TopY# Then TopY#=vy#
		Next
		y# = BottomY# + ( (TopY# - BottomY#) / Float(2) )
	EndIf

Return y#
End Function

;--------------------
Function MeshAllZ#(parent)
;--------------------
Local BackZ#,FrontZ#
Local cc,c,childent,vz#,z#

	cc = CountChildren(parent)
	If cc = 0
		z# = MeshZ#(parent)
	Else
		For c = 1 To cc
			childent = GetChild(parent,c)
			vz# = MeshZ#(childent)
			If vz#<BackZ# Then BackZ#=vz#
			If vz#>FrontZ# Then FrontZ#=vz#
		Next
		z# = BackZ# + (FrontZ# - BackZ#)/ 2
	EndIf

Return z#
End Function

;------------------------------------------------------------------------------------
;--------------------
Function MeshX#(mesh)
;--------------------
Local LeftX#,RightX#
Local s,su,v,vx#,x#

	For s = 1 To CountSurfaces(mesh)
		su = GetSurface(mesh,s)
		For v = 0  To CountVertices(su)-1
			vx# = VertexX#(su,v)
			If vx#<LeftX# Then LeftX#=vx#
			If vx#>RightX# Then RightX#=vx#
		Next
	Next
  x# = LeftX# + ( (RightX# - LeftX#) / Float(2) )

Return x#
End Function

;--------------------
Function MeshY#(mesh)
;--------------------
Local BottomY#,TopY#
Local s,su,v,vy#,y#

	For s = 1 To CountSurfaces(mesh)
		su = GetSurface(mesh,s)
		For v = 0  To CountVertices(su)-1
			vy# = VertexY#(su,v)
			If vy#<BottomY# Then BottomY#=vy#
	    If vy#>TopY# Then TopY#=vy#
		Next
	Next
	y# = BottomY# + ( (TopY# - BottomY#) / Float(2) )

Return y#
End Function

;--------------------
Function MeshZ#(mesh)
;--------------------
Local BackZ#,FrontZ#
Local s,su,v,vz#,z#

	For s = 1 To CountSurfaces(mesh)
		su = GetSurface(mesh,s)
		For v = 0  To CountVertices(su)-1
			vz# = VertexZ#(su,v)
			If vz#<BackZ# Then BackZ#=vz#
			If vz#>FrontZ# Then FrontZ#=vz#
		Next
	Next
	z# = BackZ# + (FrontZ# - BackZ#) / 2

Return z#
End Function

;--------------------
Function BottomMost#(mesh)
;--------------------
Local BottomY#,TopY#
Local s,su,v,vy#

	For s = 1 To CountSurfaces(mesh)
		su = GetSurface(mesh,s)
		For v = 0  To CountVertices(su)-1
			vy# = VertexY#(su,v)
			If vy#<BottomY# Then BottomY#=vy#
			If vy#>TopY# Then TopY#=vy#
		Next
	Next

Return BottomY#
End Function



IPete2(Posted 2005) [#17]
coolio John,

Well done - Mr. Tenacious! :)

IPete2.


John Blackledge(Posted 2005) [#18]
Thanks Pete.
I've tested it on a few different models tonight, and it seems fine.

It works on both hierarchical and non-hierarchical meshes.
Err... so I think - job done.