scaling meshes - keeping aspect ratio

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
LuMo
Posts: 410
Joined: Sun Aug 21, 2005 2:45 am
Location: Austria
Contact:

scaling meshes - keeping aspect ratio

Post by LuMo »

hey!

i'm trying to scale my models (with a program on my pc)
what do i do?
i grab all my data... find out MIN and MAX values of ALL coordinates
i calculate height with and depth of my meshes
take the maximum extension and keep it

i normalize the dimensions of the mesh to 1 and then scale it up to what was passed to my program...

so this is my code... but somehow it does not scale to eg... 20
some values are larger in my result...

Code: Select all

        minX = lmesh.verticesV3[0].x; // init...
        minY = lmesh.verticesV3[0].y;
        minZ = lmesh.verticesV3[0].z;
        maxX = lmesh.verticesV3[0].x;
        maxY = lmesh.verticesV3[0].y;
        maxZ = lmesh.verticesV3[0].z;
        for&#40; unsigned long idx = 1; idx<lmesh.vertexCount; idx++ &#41;
        &#123;
          minX = min&#40;minX, lmesh.verticesV3&#91;idx&#93;.x&#41;;
          minY = min&#40;minY, lmesh.verticesV3&#91;idx&#93;.y&#41;;
          minZ = min&#40;minZ, lmesh.verticesV3&#91;idx&#93;.z&#41;;
          maxX = max&#40;maxX, lmesh.verticesV3&#91;idx&#93;.x&#41;;
          maxY = max&#40;maxY, lmesh.verticesV3&#91;idx&#93;.y&#41;;
          maxZ = max&#40;maxZ, lmesh.verticesV3&#91;idx&#93;.z&#41;;
        &#125;	    	
        	
				// resize values
				sizeX = &#40;maxX - minX&#41;/2;
				sizeY = &#40;maxY - minY&#41;/2;
				sizeZ = &#40;maxZ - minZ&#41;/2;
				
				float fSizemax=max&#40;max&#40;sizeX,sizeY&#41;,sizeZ&#41;;
				
				printf&#40;"fSizemax = %f\n" ,fSizemax&#41;;
				printf&#40;"sizeX = %f\n" ,sizeX&#41;;
				printf&#40;"sizeY = %f\n" ,sizeY&#41;;
				printf&#40;"sizeZ = %f\n" ,sizeZ&#41;;
				// write new values
				for &#40;unsigned int i=0;i<lmesh.vertexCount;i++&#41;
				&#123;
					
					lmesh.verticesV3&#91;i&#93;.x /= fSizemax;
					lmesh.verticesV3&#91;i&#93;.x *= scale;

					lmesh.verticesV3&#91;i&#93;.y /= fSizemax;
					lmesh.verticesV3&#91;i&#93;.y *= scale;
					
					lmesh.verticesV3&#91;i&#93;.z /= fSizemax;
					lmesh.verticesV3&#91;i&#93;.z *= scale;
				&#125;   	
 	
	      for&#40; unsigned long i = 0; i<lmesh.vertexCount; i++ &#41;
	      &#123;
	        printf&#40;"%f %f %f 0x%X %f %f %f\n", lmesh.verticesV3&#91;i&#93;.nx, lmesh.verticesV3&#91;i&#93;.ny, lmesh.verticesV3&#91;i&#93;.nz,
	               lmesh.verticesV3&#91;i&#93;.color,   lmesh.verticesV3&#91;i&#93;.x,  lmesh.verticesV3&#91;i&#93;.y,  lmesh.verticesV3&#91;i&#93;.z&#41;;
	      &#125;
     
	      break;
would be awesome if someone finds my fault
this seems to be one of my last 2 bugs! (centering works on 9/10 meshes)

thanks in advance
lumo

PS: on 13th June i have to publish my work in university, do an presentation and so on; when this is done sourcecode will go public! so guys, possibly one of you will use my code soon ;)
"Good artists copy, great artists steal."
Pablo Picasso
go2lumo.com
SSpeare
Posts: 63
Joined: Tue May 23, 2006 11:45 pm
Contact:

Post by SSpeare »

Why are you dividing by 2? That doesn't seem right...

Code: Select all

            // resize values
            sizeX = &#40;maxX - minX&#41;/2;
            sizeY = &#40;maxY - minY&#41;/2;
            sizeZ = &#40;maxZ - minZ&#41;/2;
if minX is 0 and maxX is 50, then you'll get sizeX = 25. If minX = -50 and maxX is 50 then you'll get sizeX = 50, but it's really 100.
memon
Posts: 63
Joined: Mon Oct 03, 2005 10:51 pm

Post by memon »

So... what you want to do is to use the 16bit coords, right? There are several ways you could do it, but I thinkg the easiest is not to use the same pivot as in the original mesh. If you want to get the most precision out of the 16bits, you have to translate the mesh too.

Something like this should work fine:

Code: Select all

for&#40;each vertex&#41;
&#123;
  meshMin = min&#40;meshMin, v&#91;i&#93;&#41;;
  meshMax = max&#40;meshMax, v&#91;i&#93;&#41;;
&#125;

vec3 scale;
scale.x = max&#40;abs&#40;meshMin.x&#41;, meshMax.x&#41;;
scale.y = max&#40;abs&#40;meshMin.y&#41;, meshMax.y&#41;;
scale.z = max&#40;abs&#40;meshMin.z&#41;, meshMax.z&#41;;

for&#40;each vertex&#41;
&#123;
  p.x = v&#91;i&#93;.x / scale.x;
  p.y = v&#91;i&#93;.y / scale.y;
  p.z = v&#91;i&#93;.z / scale.z;
  out&#91;i&#93; = p;
&#125;
That code will fit the whole mesh into unit cube, that is the vertices will be in range -1..1. IIRC the 16bit coords have that range. You need to store the scale along with the mesh and then create scale matrix later.

If the nonuniform scaling fucks up the lighting--as I assume--you can use the max scale value instead.

If you wan to use the full range of the values, then you need to also offset. The followin bit of code should do that. It assumes you know the min/max already.

Code: Select all

center = &#40;meshMin + meshMax&#41;/2;
extend = &#40;meshMax - meshMin&#41;/2;
scale = max&#40;max&#40;extend.x, extend.y&#41;, extend.z&#41;;

for&#40;each vertex&#41;
  out&#91;i&#93; = &#40;v&#91;i&#93; - center&#41; / scale;
In thing case you store the center and scale. To convert back you should use:

Code: Select all

p = v&#91;i&#93; * scale + center;
Hope it helps.
LuMo
Posts: 410
Joined: Sun Aug 21, 2005 2:45 am
Location: Austria
Contact:

Post by LuMo »

@memon
you are absolutely right!
what i should have noticed is that i center the mesh before i scale it!
so its already done before i scale it
@SSpeare good point :) will test without div 2
EDIT: div2 is cause... + and - values!

so i finally think the point is here:

Code: Select all

float fSizemax=max&#40;max&#40;sizeX,sizeY&#41;,sizeZ&#41;*2;
"Good artists copy, great artists steal."
Pablo Picasso
go2lumo.com
memon
Posts: 63
Joined: Mon Oct 03, 2005 10:51 pm

Post by memon »

When you say center, you mean that you use the center of the same bounding box as you calculate in the provided code? If not, then your scale should be like this:

Code: Select all

vec3 ext;
ext.x = max&#40;abs&#40;meshMin.x&#41;, meshMax.x&#41;;
ext.y = max&#40;abs&#40;meshMin.y&#41;, meshMax.y&#41;;
ext.z = max&#40;abs&#40;meshMin.z&#41;, meshMax.z&#41;;
float scale = max&#40;ext.x, ext.y, ext.z&#41;;
If your center is excatly at the center of the bounding box, then meshMin and meshMax should be symmetrical (meshMin = -meshMax) and you can use the mesh max of all components of mesh max.

One thing to note is that there are two common ways to define bounding boxes. One is to specify the min and max of that bbox, and another is to specify the center and extend of the box. The mapping between the two is like this:

min = center - extend
max = center + extend


and vice versa

center = (max + min)/2
extend = (max - min)/2


So if you want to map any point in a bounding box to "normalized" -1..1 range, then the formula is:

v' = (v - center) / extend

or if you have the min/max bounding box

v' = -1 + 2 * (v - min) / (max - min)
white rabbit
Posts: 60
Joined: Wed Jul 06, 2005 7:03 pm

Post by white rabbit »

Hmm, I hadn't thought about scaling the model to make it fit the boundaries better...

Has anybody tried - what are the issues with the normals?
... How can you deal with this? .. capture the normals pre-scale I guess, and somehow stick them back in with the new position data... sounds hard...
LuMo
Posts: 410
Joined: Sun Aug 21, 2005 2:45 am
Location: Austria
Contact:

Post by LuMo »

i had no problems with my normals...
i calculated em when converting the mesh...

note: no probs with normals when keeping aspect ratio nor when you discard it.
"Good artists copy, great artists steal."
Pablo Picasso
go2lumo.com
Post Reply