I need someone to fix my code...really! [ent_buffer and normals]

Posted By: EvilSOB

I need someone to fix my code...really! [ent_buffer and normals] - 05/17/12 16:24

OK Im really having to lower myself to this, but its driving me nuts.

I STILL cant find any way to manipulate the mesh of a model and then
update their normals to be correct to the new surface...

Yes, there are multiple threads around on this, but they either
confuse me, dont suit my problem, or dont work for me.


So, below you will find a complete script showing my problem.
All you need to do to test is create or rename a model (not terrain)
to "testmodel.mdl" and run the code.

It then displays the normal of 'A' vertex during the whole manipulation process.
It should change when the normals get corrected (I understand)
but they never do...

Can a few of you guys test this (un-modified) with verious
models to see if there is some form of pattern...


BUT ... most importantly, I need someone to "fix" the broken
part of my code ... or insert the missing piece ... or whatever.

The active code in this script is pretty simple, and I would LIKE to be able
to just call ent_fixnormals, but if I need to manually calculate and
set the normals, its do-able, BUT I DONT KNOW HOW...

So somebody ... please ... make this code work, and then I
will be able to figure out HOW it works, and fix the hole
in my understanding...


Thanks muchly guys...


Click to reveal..
Code:
#include <acknex.h>
#include <default.c>
//
D3DVERTEX *vbuff0;		//vertex manipulation workspace
//
TEXT* debug_txt =	
{  pos_x = 10;	  pos_y = 10;	  strings = 5;		font="courier#18";		flags = SHOW;	} 
//
//
void main()
{
	wait(1);					level_load(NULL);		wait(1);				diag("\n\n\n");
	draw_textmode("Times",0,32,100);				warn_level = 3;	def_move();
	//======================================================================================
	//
	int i=0;		ENTITY* test = ent_create("testmodel.mdl", nullvector, NULL);
	//
	//--------------------------------------------------------------------------------------
	//
	ent_buffers(test, 0,0, &vbuff0, NULL,NULL);
						str_cpy( (debug_txt.pstring)[0], "Initial values of Normal         == ");
							str_cat_num((debug_txt.pstring)[0], "%.0f, ", vbuff0[ent_status(test,0)/2].nx);
							str_cat_num((debug_txt.pstring)[0], "%.0f, ", vbuff0[ent_status(test,0)/2].ny);
							str_cat_num((debug_txt.pstring)[0], "%.0f",   vbuff0[ent_status(test,0)/2].nz);
						wait(-1);		beep();
	//
	//--------------------------------------------------------------------------------------
	//
	ent_buffers(test, 0,0, &vbuff0, NULL,NULL);
	for(i=0; i<ent_status(test,0); i++)		{	vbuff0[i].y += random(10)-5;	}
	//
						str_cpy( (debug_txt.pstring)[1], "Immediately after Randomizing    == ");
							str_cat_num((debug_txt.pstring)[1], "%.0f, ", vbuff0[ent_status(test,0)/2].nx);
							str_cat_num((debug_txt.pstring)[1], "%.0f, ", vbuff0[ent_status(test,0)/2].ny);
							str_cat_num((debug_txt.pstring)[1], "%.0f",   vbuff0[ent_status(test,0)/2].nz);
						wait(-1);		beep();
	//
	//--------------------------------------------------------------------------------------
	//
	ent_buffers(test, 0,0, &vbuff0, NULL,NULL);
						str_cpy( (debug_txt.pstring)[2], "Some Frames After Randomizing    == ");
							str_cat_num((debug_txt.pstring)[2], "%.0f, ", vbuff0[ent_status(test,0)/2].nx);
							str_cat_num((debug_txt.pstring)[2], "%.0f, ", vbuff0[ent_status(test,0)/2].ny);
							str_cat_num((debug_txt.pstring)[2], "%.0f",   vbuff0[ent_status(test,0)/2].nz);
						wait(-1);		beep();
	//
	//--------------------------------------------------------------------------------------
	//
	ent_fixnormals(test, test.frame);	wait(-1);	beep();
	ent_buffers(test, 0,0, &vbuff0, NULL,NULL);
						str_cpy( (debug_txt.pstring)[3], "Some Frames After ent_fixnormals == ");
							str_cat_num((debug_txt.pstring)[3], "%.0f, ", vbuff0[ent_status(test,0)/2].nx);
							str_cat_num((debug_txt.pstring)[3], "%.0f, ", vbuff0[ent_status(test,0)/2].ny);
							str_cat_num((debug_txt.pstring)[3], "%.0f",   vbuff0[ent_status(test,0)/2].nz);
	//
	//
}


Posted By: Wjbender

Re: I need someone to fix my code...really! [ent_buffer and normals] - 05/20/12 19:20


okay this is what i see happening here ,could be wrong
but dont think so..

Code:
//it appears to me that when altering the
	//vertices buffer all that happens is 
	//the vertices alone are manipulated 
	//and not the normals because
	//when i tested your code it became
	//aparent to me that ent_fixnormals resets the vertices
	//back to their original states (which is kinda weird (bug)?)
	for(i=0; i<ent_status(test,0); i++)
		{
			vbuff0[i].y += random(10)-5;	
		}
	//but when manipulating the normals directly 
	//ent_fixnormals then fixes the altered normals
	for(i=0; i<ent_status(test,0); i++)
		{	
			vbuff0[i].nx += random(10)-5;	
		}


Posted By: txesmi

Re: I need someone to fix my code...really! [ent_buffer and normals] - 05/20/12 23:08

Originally Posted By: Wjbender

//when i tested your code it became
//aparent to me that ent_fixnormals resets the vertices
//back to their original states (which is kinda weird (bug)?)


same issue here
Posted By: sivan

Re: I need someone to fix my code...really! [ent_buffer and normals] - 05/21/12 07:15

just a question: no updatehull is required before fixnormals? (in case of terrain I had to use updatehull, but hmp is a slightly different thing... e.g. instead of fixnormals I had to set normals by myself)
Posted By: EvilSOB

Re: I need someone to fix my code...really! [ent_buffer and normals] - 05/21/12 08:31

Thanks for the replys guys...

Wjbender: Yes, thats what Im getting too.
But if you just randomise the normals and run fix_normals, will the 'fixed'
normals match my modified vertices, or just to its neighbouring normals?

I know what I want my vertices to be (+5 to -5 from flat) but I have no idea
how to randomise the normals into a 'controlled' level of randomness.

AND, this initial ranomising isnt the only time I need to fix the normals.
The vertices will be adjusted during gameplay, and will need fixing each time.
So ONLY adjusting the normals is no good to me then.
(unless you are making a point that I am sompletely missing)


txesmi: yus.


sivan: I dunno... I havent tried updatehull cause its a passable entity.
I will give it a try with both updatehull, and leaving PASSABLE unset, and
both together. I will post results.

Also, you say you had to 'set normals by yourself'? Is there any way I could
get my hands on the mathematics you used? Please? I would PREFER to do it that way,
cause at the moment stitching any models together is tricky with normals at the edges,
and if Im adjusting just a few vertices 'in the middle' of a model, it would
be nice to be able to adjust JUST the affected normals, rather than fixnormals
on the whole entity, and having to re-stich the normals on all used edjes of the model.


Thanks guys.
Posted By: sivan

Re: I need someone to fix my code...really! [ent_buffer and normals] - 05/21/12 08:46

here is a code for setting normals of a multi-chunk terrain I use in A7 (it updates chunk border vertices which are wrong in A7 but okay in A8).
Code:
LPD3DXMESH dx_mesh;
	for (i=0; i<(var)(ent_status(terrain_entity,16)); i++)
		{
			dx_mesh = ent_getmesh(terrain_entity,i,0);		// ent , chunk start with 0 , lod
			D3DXComputeNormals(dx_mesh,NULL);
			ent_setmesh(terrain_entity,dx_mesh,i,0);			
		}



I have to set again the normals by some c_tracing (but in case of models I have no idea). And I also needed a setminmax and an updatehull to work everything fine.

Code:
c_setminmax(terrain_entity);
	wait(1);
	c_updatehull(terrain_entity,0);
	//	c_updatehull(terrain_entity,my.frame);
	wait(3);	
		
	for (i=1; i<=(var)(ent_status(terrain_entity,0)); i++)
		{	
			CONTACT* c = ent_getvertex(terrain_entity,NULL,i);   			// vertex number begins with 1 !			
			c_trace( vector((var)c.v.x,(var)c.v.z,vgroundmax.z+500), vector((var)c.v.x,(var)c.v.z,vgroundmin.z-500), IGNORE_ME | IGNORE_SPRITES | IGNORE_MODELS | IGNORE_MAPS | IGNORE_PASSABLE ); 			
			if (HIT_TARGET)	
				{
					// normal 
//					c.v.nx = (float)normal.x; 			
//					c.v.nz = (float)normal.y; 
//					c.v.ny = (float)normal.z; 	
					// or the same with hit
					c.v.nx = (float)hit.nx; 			
					c.v.nz = (float)hit.ny; 
					c.v.ny = (float)hit.nz; 																													
					ent_setvertex(terrain_entity,c,i);
					// or more precisely it should be the average of normals of all neighbouring faceces !!! 
					// it is stored in hmp in an approximated value of 162 stored normal vectors !!!
				}
			
		}


that updatehull with 0 works, but in theory wrong.
Posted By: Wjbender

Re: I need someone to fix my code...really! [ent_buffer and normals] - 05/21/12 09:16

Point im making is that even if altering the vertices could alter
the normals (which seems it doesnt) entfixnormals seems to realter
the vertices back to original position so normals wil be unaltered (posibly bug).
Best would be to alter vertices like you do but recalculate normals with
a algoritm or use a diffrent function instead of entfixnormals if there is one.
Perhaps gamestudio has a function that alters the normals along with
altering the vertices? I would just go with a algoritm depending
on if you aim for goraud or flat shading.could perhaps help you with flat
but its c++ code..should be easy to find math examples on google..that's
if sivans alternate solution does not work...
Posted By: txesmi

Re: I need someone to fix my code...really! [ent_buffer and normals] - 05/21/12 09:35

The normal of a triangle can be computed with the cross product of two of its sides.



Code:
normalize ( vec_cross ( vec_diff ( B.x, A.x ), vec_diff ( C.x, A.x ) ) );



but as sivan said, the normal of a vertex should be the average of normals of all neighbouring faces.

I don't know how the vertexes are ordered into the triangel buffer, so you should check to compute them in clockwise order.

Salud!
Posted By: txesmi

Re: I need someone to fix my code...really! [ent_buffer and normals] - 05/21/12 12:11

doble post! xP

i gived a try to this problem and here is the result:

Code:
#include <acknex.h>
#include <default.c>

D3DVERTEX *vbuff0;
short *tbuff;

VECTOR vtemp;

TEXT* debug_txt =	
{  pos_x = 10;	  pos_y = 10;	  strings = 5;		font="courier#18";		flags = SHOW;	}


function show_normals ( ENTITY *ent )
{
	D3DVERTEX *vb;
	int vnum = ent_status ( ent, 0 );
	int i;
	
	ent_buffers ( ent, 0, 0, &vb, NULL, NULL );
	
	for ( i=0; i<vnum; i++ )
	{
		vec_set ( vtemp, vector ( vb[i].nx, vb[i].nz, vb[i].ny ) );
		vec_scale ( vtemp, 10 );
		vec_add ( vtemp, vector ( vb[i].x, vb[i].z, vb[i].y ) );
		
		draw_line3d ( vector ( vb[i].x, vb[i].z, vb[i].y ), COLOR_WHITE, 0 );
		draw_line3d ( vector ( vb[i].x, vb[i].z, vb[i].y ), COLOR_WHITE, 100 );
		draw_line3d ( vtemp, COLOR_RED, 100 );
		draw_line3d ( vtemp, COLOR_RED, 0 );
	}
}

function true_fixnormals ( ENTITY *ent )
{
	D3DVERTEX *vb;
	short *tb;
	long *at;
	int i, ii;
	VECTOR vNormal, vOldNormal, v1, v2, v3;
	
	int tnum = ent_status ( ent, 4 );
	int vnum = ent_status ( ent, 1 );
	
	ent_buffers ( ent, 0, 0, &vb, &tb, &at );
	
	for ( i=0; i<vnum; i++ ) // reset normals
	{
		vb[i].nx = vb[i].ny = vb[i].nz = 0;
	}
	
	for ( i=0; i<tnum*3; i+=3 ) // compute normals
	{
		vec_set ( v1, vector ( vb[tb[i]].x, vb[tb[i]].z, vb[tb[i]].y ) ); // we can't operate with floats as vectors
		vec_set ( v2, vector ( vb[tb[i+1]].x, vb[tb[i+1]].z, vb[tb[i+1]].y ) );
		vec_set ( v3, vector ( vb[tb[i+2]].x, vb[tb[i+2]].z, vb[tb[i+2]].y ) );
		
		vec_cross ( vNormal, vec_diff ( NULL, v3, v1 ), vec_diff ( NULL, v2, v1 ) );
		vec_normalize ( vNormal, 1 );
		
		for ( ii=0; ii<3; ii++ ) // add the new normal to each vertex
		{
			vec_set ( vOldNormal, vector ( vb[tb[i+ii]].nx, vb[tb[i+ii]].nz, vb[tb[i+ii]].ny ) );
			vec_add ( vOldNormal, vNormal );
			vec_normalize ( vOldNormal, 1 );
			vb[tb[i+ii]].nx = vOldNormal.x;
			vb[tb[i+ii]].ny = vOldNormal.z;
			vb[tb[i+ii]].nz = vOldNormal.y;
		}
	}
}

void main()
{
	int i=0;
	
	random_seed ( 0 );
	
	wait(1);
	level_load(NULL);
	wait(1);
	
	ENTITY* test = ent_create("ball.mdl", nullvector, NULL);
	camera.x = -300;
	camera.z = 300;
	camera.tilt = -45;
	
	while ( !key_space )
	{
		draw_text ( "Press space to continue...", 10, 10, COLOR_WHITE );
		show_normals ( test );
		wait(1);
	}
	
	ent_buffers ( test, 0,0, &vbuff0, NULL, NULL );
	
	for(i=0; i<ent_status(test,0); i++)		{	vbuff0[i].y += random(10)-5;	vbuff0[i].x += random(10)-5;	vbuff0[i].z += random(10)-5;	}
	true_fixnormals ( test );
	
	while ( 1 )
	{
		show_normals ( test );
		wait(1);
	}
}



It looks that works good but can't be sure. It really needs more precise computations than vec operations with those unit vectors...

Salud!
Posted By: EvilSOB

Re: I need someone to fix my code...really! [ent_buffer and normals] - 05/22/12 13:46

Finally! Im back. Damn the real-world for interferig in my lite-c lifestyle!

Sivan: Ypu, figured that one out from hitting the Microsoft.net web.
Here is MY version that doesnt need d3d9/h included.
Code:
#define PRAGMA_API D3DXComputeNormals;D3DX9_30!D3DXComputeNormals
void __stdcall D3DXComputeNormals(void* pMesh, DWORD *pAdjacency);
void ent_normals(ENTITY* ent)
{	void* mesh_ptr;	D3DXComputeNormals(mesh_ptr=ent_getmesh(ent,0,0), 0);
	ent_setmesh(ent, mesh_ptr, 0, 0);                                   }

Its a little dirty, but it does the job... well ...only HALF the job, as you will see by reading my reply to txesmi.


Wjbender: Precicely my problem. I put ent_fixnormals in there, even though
it doesnt work, in the hopes I was just using it badly. It resetting the
vertices just seems plain wrong. But I was hoping I was just applying it badly.
Going for a discrete algorithm is the way I would LIKE to go, but I just
havent been able to google anything that gives me the 'basics' of how to construct
said algorithm... But, see my reply to txesmi, he's got the answer!


txesmi: (post#1): AHHH! My friend, my hero, you LEGEND! That is precicely the 'golden nugget'
of information I was looking for! I understand about the averaging and can figure that out,
but I dont understand the need or the clockwise valuations. Do you know why?
I will aim for that, but if it gets ugly, I will try it without checking first.

txesmi: (post#2): I havent tried your code yet, so I will leave that just for reference, and
to look at if I hit any problems trying to to it 'my way' from scratch.
And yes, I agree about the VEC_? functions being imprecise due to vectors being VARs,
so If I find I NEED the precision, I will just write float-versions of the
vector functions needed.


Thanks again to all involved. Once Ive had a serious attempt to get this going,
I will post the rests and associated code too.

Cheers!
Posted By: txesmi

Re: I need someone to fix my code...really! [ent_buffer and normals] - 05/22/12 23:32

glad for helping!

Quote:
but I dont understand the need or the clockwise valuations. Do you know why?

That is because the normal can point in the two opposite directions and the result of the cross product depends on the order of the factors.

Sorry, but it is not clockwise but the opposite blush

Better read: http://en.wikipedia.org/wiki/Cross_product

Salud!
© 2024 lite-C Forums