1 registered members (TipmyPip),
18,561
guests, and 5
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: Carlos3DGS]
#386576
11/05/11 12:07
11/05/11 12:07
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
The shader code would LIKELY be recognisable enough to 'tweak' as your needs change. Once someone else has dont he conceptual groundwork for you...
I would advise against making the CONTACT a global, ut you couls always pass a pointer to a local one as a parameter to the get-height function. Just do one call at the same time as your bmap_lock, and pass the contact pointer to all the get_heights, should save a serious amount of horsepower, without any 'radical' code changes...
Can you post the relevent code you are using with the 'global' version?
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: Carlos3DGS]
#386577
11/05/11 12:30
11/05/11 12:30
|
Joined: Oct 2008
Posts: 513
Carlos3DGS
User
|
User
Joined: Oct 2008
Posts: 513
|
NEW PAINT FUNCTION:
void Terrain_Paint(int x, int y)
{
ENTITY* Terr = Terrain[x][y];
CONTACT* c1;
int i; //vertex info for terrain
BMAP* Source_BM;
BMAP* OldSkin;
VECTOR Pixel_pos; //pixel coordinates for skin bmap
var height;
var pixel_source; var pixel_dest;
//var t_format1; var t_format2;
COLOR* t_color; var t_alpha;
BMAP* NewSkin = bmap_create("Terrain_Sand.tga");
t_format1=bmap_lock(NewSkin,0);
c1 = ent_getvertex(Terr,NULL,1);
for(Pixel_pos.y=0;Pixel_pos.y<512;Pixel_pos.y++)
{
for(Pixel_pos.x=0;Pixel_pos.x<512;Pixel_pos.x++)
{
i = (integer((Pixel_pos.x)/16)+1) + (((integer((Pixel_pos.y)/16)+1)*33));
height = get_height(Pixel_pos.x,Pixel_pos.y,i,c1);
if(height>16)
{
if(height<=16)//sand
{
Source_BM=Sand_BM;
}
else if(height<75)//grass
{
Source_BM=Grass_BM;
}
else if(height<150)//stone
{
Source_BM=Rock_BM;
}
else//snow
{
Source_BM=Snow_BM;
}
pixel_source = pixel_for_bmap(Source_BM,Pixel_pos.x,Pixel_pos.y);
t_color = pixel_to_vec(NULL, t_alpha ,t_format2,pixel_source);
//paint pixel on selected terrain's texture
pixel_dest=pixel_for_vec(t_color,t_alpha,t_format1);
pixel_to_bmap(NewSkin,Pixel_pos.x,Pixel_pos.y,pixel_dest);
}
}
}
bmap_unlock(NewSkin);
OldSkin=ent_getskin(Terr,1);
ptr_remove(OldSkin);
ent_setskin(Terr,NewSkin,1);
}
NEW HEIGHT FUNCTION:
var get_height(var Px, var Py, int SW, CONTACT* c1)
{
//P = point that we want the height of (x,y,0)
//SW = vertex number of terrain ent closest towards the lower left corner of the square
//c1 = pointer to our terrain vertex info
VECTOR P;
//TRANSFORM SKIN PIXEL COORDS TO LOCAL ENT COORD SYSTEM
vec_set(P,vector(Px,Py,0));
P.x-= 256;
P.y = 256-P.y;
VECTOR Triangle[3];
VECTOR temp_vec;
ANGLE temp_ang;
VECTOR Director[2];
VECTOR formula;
var ind_term;
//retrieve first point of containing triangle (base corner)
Triangle[0].x=(c1.v)[SW].x;
Triangle[0].y=(c1.v)[SW].z;
Triangle[0].z=(c1.v)[SW].y;
//retrieve second point of containing triangle (diagonal to base)
Triangle[1].x=(c1.v)[SW-32].x;
Triangle[1].y=(c1.v)[SW-32].z;
Triangle[1].z=(c1.v)[SW-32].y;
//determine third point of containing triangle (varying point)
vec_set (temp_vec, P);
vec_sub (temp_vec,Triangle[0].x);
vec_to_angle (temp_ang.pan,temp_vec);
//retrieve third point of containing triangle (varying point)
if(temp_ang.pan>45)
{
Triangle[2].x = (c1.v)[SW-33].x;
Triangle[2].y = (c1.v)[SW-33].z;
Triangle[2].z = (c1.v)[SW-33].y;
}
else
{
Triangle[2].x = (c1.v)[SW+1].x;
Triangle[2].y = (c1.v)[SW+1].z;
Triangle[2].z = (c1.v)[SW+1].y;
}
//calculate the triangle's plane normal for the formula coeficients
vec_set(Director[0],Triangle[1]);
vec_sub(Director[0],Triangle[0]);
vec_set(Director[1],Triangle[2]);
vec_sub(Director[1],Triangle[0]);
vec_cross(formula,Director[0],Director[1]);
//set the independant term of the formula
ind_term=(-1*formula.x*Triangle[0].x)+(-1*formula.y*Triangle[0].y)+(-1*formula.z*Triangle[0].z);
//calculate our point's height plugging our values into the formula
P.z=(-1*((formula.x*P.x)+(formula.y*P.y)+ind_term))/formula.z;
return(P.z);
}
EDIT:relevant changes are: -CONTACT* now being declared in paint function -c1 = ent_getvertex(Terr,NULL,1); being called only once in the paint function before the loops -paint function now passes a contact pointer to the height function instead of a entity pointer height = get_height(Pixel_pos.x,Pixel_pos.y,i,c1); -height function now recieves a contact pointer instead of a ent pointer var get_height(var Px, var Py, int SW, CONTACT* c1) -removed all ent_getvertex calls from the height function (adittional speed tests will be posted soon)
Last edited by Carlos3DGS; 11/05/11 12:51.
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: Carlos3DGS]
#386579
11/05/11 13:17
11/05/11 13:17
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
WTF! We only saved a THREE WHOLE SECONDS after dropping 786,431 ent_getvertex calls???? Are you SURE there is no wait calls between each terrain that may be causing a delay? And are you sure each terrain only gets called once?
I cant really see anything wrong here, nor anything to eat significant horsepower.
And you've coded it pretty much how I would have, so there is not much room for optimisation, if any.
I expected MUCH more of an improvement than this...
One last test though.
Disable the pixel_for_bmap and pixel_to_bmap lines and see if we get any significant speed improvements. Othersize I think we've hit the limit...
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: Carlos3DGS]
#386581
11/05/11 13:33
11/05/11 13:33
|
Joined: Oct 2008
Posts: 513
Carlos3DGS
User
|
User
Joined: Oct 2008
Posts: 513
|
Method used for new speed tests: placing " return(random(200));" in different places of my get_height function var get_height(var Px, var Py, int SW, CONTACT* c1) { //P = point that we want the height of (x,y,0) //SW = vertex number of terrain ent closest towards the lower left corner of the square //c1 = pointer to our terrain vertex info VECTOR P; VECTOR Triangle[3]; VECTOR temp_vec; ANGLE temp_ang; VECTOR Director[2]; VECTOR formula; var ind_term; //1 //TRANSFORM SKIN PIXEL COORDS TO LOCAL ENT COORD SYSTEM vec_set(P,vector(Px,Py,0)); P.x-= 256; P.y = 256-P.y; //2 //retrieve first point of containing triangle (base corner) Triangle[0].x=(c1.v)[SW].x; Triangle[0].y=(c1.v)[SW].z; Triangle[0].z=(c1.v)[SW].y; //3 //retrieve second point of containing triangle (diagonal to base) Triangle[1].x=(c1.v)[SW-32].x; Triangle[1].y=(c1.v)[SW-32].z; Triangle[1].z=(c1.v)[SW-32].y; //4 //determine third point of containing triangle (varying point) vec_set (temp_vec, P); //5 vec_sub (temp_vec,Triangle[0].x); //6 vec_to_angle (temp_ang.pan,temp_vec); //7 //retrieve third point of containing triangle (varying point) if(temp_ang.pan>45) { Triangle[2].x = (c1.v)[SW-33].x; Triangle[2].y = (c1.v)[SW-33].z; Triangle[2].z = (c1.v)[SW-33].y; } else { Triangle[2].x = (c1.v)[SW+1].x; Triangle[2].y = (c1.v)[SW+1].z; Triangle[2].z = (c1.v)[SW+1].y; } //8 //calculate the triangle's plane normal for the formula coeficients vec_set(Director[0],Triangle[1]); vec_sub(Director[0],Triangle[0]); vec_set(Director[1],Triangle[2]); vec_sub(Director[1],Triangle[0]); //9 vec_cross(formula,Director[0],Director[1]); //10 //set the independant term of the formula ind_term=(-1*formula.x*Triangle[0].x)+(-1*formula.y*Triangle[0].y)+(-1*formula.z*Triangle[0].z); //11 //calculate our point's height plugging our values into the formula P.z=(-1*((formula.x*P.x)+(formula.y*P.y)+ind_term))/formula.z; //12 return(P.z); //NONE }
1- 5.4 secs 2- 6.2 secs 3- 7.9 secs 4- 9.5 secs 5- 9.9 secs 6- 10.1 secs 7- 16.3 secs 8- 18.1 secs 9- 20.7 secs 10- 21.6 secs 11- 22.7 secs 12- 24.0 secs NONE- 22.7 secs EDIT: I was doing some other speed tests centered around get_height while you answered since the first test pointed to this function being the problem that slows everything down. After seeing the results of these tests it seems that this is the problem... Don't know hot to optimize it though... Any suggestions?
Last edited by Carlos3DGS; 11/05/11 13:41.
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: Carlos3DGS]
#386582
11/05/11 13:50
11/05/11 13:50
|
Joined: Mar 2006
Posts: 3,538 WA, Australia
JibbSmart
Expert
|
Expert
Joined: Mar 2006
Posts: 3,538
WA, Australia
|
I do actually suggest the shader route. If you know how to write shaders, it should actually be pretty easy to do. I've found the official shader workshops to be very helpful and fairly simple (especially the first 4 parts, which are the most important). HLSL (the shader language) certainly has differences from Lite-C, but a lot of similarities as well, and some conveniences that (once you learn them) you'll wish Lite-C had.
Formerly known as JulzMighty. I made KarBOOM!
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: JibbSmart]
#386583
11/05/11 13:56
11/05/11 13:56
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
I agree with Jibb, shaders is a better option I believe... Try this (possibly) optimised get_height. Make sure to test it with full painting enabled, because my logic may be flawed around the final formulas...
var get_height(var Px, var Py, int SW, CONTACT* c1)
{
//P = point that we want the height of (x,y,0)
//SW = vertex number of terrain ent closest towards the lower left corner of the square
//c1 = pointer to our terrain vertex info
VECTOR P, Triangle[3], temp_vec, Director[2], formula;
ANGLE temp_ang;
var ind_term;
// ### NOTE ### All VECTOR calculations are working in D3D Vertex format!
// That is X-Z-Y instead of X-Y-Z
//TRANSFORM SKIN PIXEL COORDS TO LOCAL ENT COORD SYSTEM
vec_set(P,vector(Px-256,0,256-Py));
//retrieve first point of containing triangle (base corner)
vec_set(Triangle[0], (c1.v)[SW].x);
//retrieve second point of containing triangle (diagonal to base)
vec_set(Triangle[1], (c1.v)[SW-32].x);
//determine third point of containing triangle (varying point)
vec_to_angle (temp_ang.pan, vec_sub( vec_set(temp_vec, P) , Triangle[0]) );
//retrieve third point of containing triangle (varying point)
if(temp_ang.pan>45) vec_set(Triangle[2], (c1.v)[SW-33].x);
else vec_set(Triangle[2], (c1.v)[SW+1].x);
//calculate the triangle's plane normal for the formula coeficients
vec_sub( vec_set(Director[0],Triangle[1]) ,Triangle[0]);
vec_sub( vec_set(Director[1],Triangle[2]) ,Triangle[0]);
vec_cross(formula, Director[0], Director[1]);
//set the independant term of the formula
ind_term=(-1*formula.x*Triangle[0].x)+(-1*formula.y*Triangle[0].y)+(-1*formula.z*Triangle[0].z);
//calculate our point's height plugging our values into the formula
P.y=(-1*((formula.x*P.x)+(formula.z*P.z)+ind_term))/formula.y;
return(P.y);
}
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: Carlos3DGS]
#386585
11/05/11 14:22
11/05/11 14:22
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
You shouldnt have any trouble with HLSL, as you seem to have a good grasp of vector-mathematics. Thats important. Mine aint so good so I struggle.
I think yOu should ask for HELP with the shader, especially the concepts, as its not quite the DEEP end of the pool, but it aint the shallow end either.
I will shortly post a bacic concept of how I feel this shader can achieve what you want.
You will be all-right, theres plenty of people to help out. And even I managed to knock out a few shader myself, but mostly i 'hack' other peoples to suit my needs.
So if you have any CODING problems, I can help to some degree, but the CONCEPTUAL side of things Im pretty weak...
And thanks to you too, our banter has helped me get a few things straight in my head, and pointed out a few 'holes' in my planning...
Best of luck. And see ya around...
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: EvilSOB]
#386587
11/05/11 14:56
11/05/11 14:56
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
My basic premise works like this...
Firstly, set up your terrain textures as global BMAPs, if you havent already. The bmaps Sand_BM, Grass_BM, Rock_BM, & Snow_BM, that is. They can now be referenced directly from the shader using the line texture Sand_BM_bmap, Grass_BM_bmap, Rock_BM_bmap, Snow_BM_bmap;
Then (in the 'Terrain_Paint' script), you want to FIRST create an empty BMAP, ([/i]using bmap_createblack(512,512,24);[/i]) and apply it to the entity as a skin. Then apply our new shader-material to the entity too.
Then we wait one frame for the shader to do its work, and create a new texture straight into the skin. Then remove the shader material and thats the painting part completed.
Now, in the shader itself, I feel it SHOULD go something like !this.
You want to set up 'sampler' pointers for all the terrain texture maps, like so... sampler2D SandSrc = sampler_state { texture = <Sand_BM_bmp>; };, etc
Then we set up the vertex-shader portion to ignore camera angle and to just generate a heightmap for all vertices of the model. I DUNNO how to do this!
Finally we reach the pixel-shader part. if I understand correctly, the height-map-data cant be retrieved from the POSITION0.Z value passed into the pixel shader. I think. You can then use this height to extract pixels from the texture of your choice... Its just a simple if ... ifelse ... proxess. People will say IF's in shaders is 'dirty' but its just a ONE frame shader so that makes it acceptable...
[EDIT] woohoo! Thats a lot of time for the SEEMINGLY minimal changes I made... but the important thing is .... Was it still 'painting' correctly, or had I mangled the results of get_height?
Last edited by EvilSOB; 11/05/11 14:59.
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
|