|
Re: Dumb terrain question.. Cannot get it to move...
[Re: EvilSOB]
#386404
11/02/11 13:19
11/02/11 13:19
|
Joined: Oct 2008
Posts: 513
Carlos3DGS
User
|
User
Joined: Oct 2008
Posts: 513
|
I was also having problems with ent_fixnormals when I started using it for runtime edited models (even terrains). ent_fixnormals(entity*,frame); I also had no idea what to put in the frame parameter for un-animated entities. i tried with NULL, tried with 0, and tried with 1... always getting no result. So I started using an entity propety: ".frame" i dont set .frame anywhere, it sets itself. so now whenever I use something like ent_fixnormals i always do: ent_fixnormals(entity,entity.frame); I am also a noob when it comes to normals, this is the first time I do anything with them. Which frame? Its an un-animated entity pretending to be a terrain.. so where the hell does a frame number come from? I don't use .frame because I know what I'm doing. I actually use .frame because I have abolutely no idea what I am doing and don't know what value to put in there for un-animated entities, so I let engine decide for me. Even when using real terrains that cannot be animated i have to use this entity.frame thing, but I honestly have no idea why... As Socrates said: "the more you learn the more you realize how little you know" (this frase is becoming more and more evident to me when learning to program new stuff for videogames. I might even set it as my signature, lol!)
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: MrGuest]
#386409
11/02/11 14:14
11/02/11 14:14
|
Joined: Oct 2008
Posts: 513
Carlos3DGS
User
|
User
Joined: Oct 2008
Posts: 513
|
I have been reading both functions and am trying to come up with a clever way to implement it but I have to admit I have absolutely no idea what to do... lets say this is a 16x16 square with these vectors: D=(0,0,-1) A=(0,15,6) B=(15,0,7) C=(15,15,0) the coords are (x,y,height)How would I calculate which triangle H1 or H2 are on? How would I get the height of H1? How would I get the height of H2? H1 inside triangle ACD or BCD? H2 inside triangle ACD or BCD? H1=(3,11,?) H2=(13,3,?)
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: Carlos3DGS]
#386412
11/02/11 14:38
11/02/11 14:38
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Thanks Carlos... You've reminded me...
I was just using 'ent.frame' blindly too...
As for how to use lerp to get what you want ... NFI
"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]
#386413
11/02/11 14:51
11/02/11 14:51
|
Joined: Oct 2008
Posts: 513
Carlos3DGS
User
|
User
Joined: Oct 2008
Posts: 513
|
I was just using 'ent.frame' blindly too... Getting something to work withought fully understanding how all the elements involved in the solution work. This is the pro way of getting stuff done (I do it all the time, and I'm not only talking about programming hahaha)
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: Carlos3DGS]
#386414
11/02/11 14:56
11/02/11 14:56
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
If it aint broke, dont fix it...
If it works this way, stop playing around with it...
"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]
#386444
11/03/11 03:46
11/03/11 03:46
|
Joined: Oct 2008
Posts: 513
Carlos3DGS
User
|
User
Joined: Oct 2008
Posts: 513
|
I finally achieved it! (I think)
var get_height(VECTOR P, int SW, ENTITY* Terrain)
{
//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
//Terrain we are calculating for
CONTACT* c1;
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)
c1= ent_getvertex(Terrain,NULL,SW);
Triangle[0].x=c1.v.x;
Triangle[0].y=c1.v.z;
Triangle[0].z=c1.v.y;
//retrieve second point of containing triangle (diagonal to base)
c1= ent_getvertex(Terrain,NULL,SW-32);
Triangle[1].x=c1.v.x;
Triangle[1].y=c1.v.z;
Triangle[1].z=c1.v.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)
{
c1= ent_getvertex(Terrain,NULL,SW-33);
}
else
{
c1= ent_getvertex(Terrain,NULL,SW+1);
}
Triangle[2].x=c1.v.x;
Triangle[2].y=c1.v.z;
Triangle[2].z=c1.v.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);
}
A short summary: Planes can be expressed in two ways, either by three points, or by one point and a normal vector to the plane's surface. (we have the first way of expressing a plane but need the second) First I determine which of the two triangles (that form our square) our point is on. Then I retrieve the vertex positions that form that triangle. With those three points we have a plane, now I translate that way of expressing a plane to the point and normal version. Then I store the coeficients of the formula we are building. I multiply all the coeficients with the independant terms and store it all together to have those parts pre-calculated and solved. Now we have to use another formula for the line, and plug it into our unfinished formula or the plane to find out where the line and plane intersect eachother. I plug in to the formula the rest of our known data and multiply by the formula coeficients we calculated before. We need to isolate the variable we are searching for using basic algebra, that was automatically done re-arranging the formula in the previous step taking into account what needed to go to where and how to solve for z. And finished! OMG I HATE calculus! Finally I can sleep! It surprizes me how short and simple the function looks after spending most of the the afternoon and night (it's 4:30 in the morning here) learning calculus. Untested but it should work, I am too tired to test it now and risk feeling pulled into the code for god knows how many more hours... When I program hours fly and I lose track of time... This was a nightmare for me to figure out, hope it saves you some sleep hours in the future.
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: Carlos3DGS]
#386445
11/03/11 04:02
11/03/11 04:02
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Whoa! I aint going NEAR this code.
Just reading your 'short summary' is giving me a headache.
I hope it does work for you, and I hope I never need it.
Well done all the same. Enjoy your sleep, you earned it!
"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]
#386497
11/03/11 21:40
11/03/11 21:40
|
Joined: Oct 2008
Posts: 513
Carlos3DGS
User
|
User
Joined: Oct 2008
Posts: 513
|
Had to make some modifications to get it working, but finally it is done! Video working on 100 terrains: http://www.youtube.com/watch?v=CnODODp4fegaround one second for all of the following: -generating random height data (diamond-square algorithym) for 100 terrains. -splicing 100 terrains -ent_updtatehull x100 -ent_fixnormals x100 -4 corner normal fix for shadows 4x100 = 400 function calls -4 edge normal fix for shadows 4x100 function calls around 32 seconds just for this: painting 100 512x512 textures... Painting was incredibly slow, I heavily modified my painting function to optimize as much as I could. I don't think I can make it faster than it is now though (32 secs for 100 512x512 textures). Any suggestions are welcome to help me speed things up. HEIGHT FUNCTION:
var get_height(var Px, var Py, int SW, ENTITY* Terrain)
{
//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
//Terrain we are calculating for
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;
CONTACT* c1;
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)
c1= ent_getvertex(Terrain,NULL,SW);
Triangle[0].x=c1.v.x;
Triangle[0].y=c1.v.z;
Triangle[0].z=c1.v.y;
//retrieve second point of containing triangle (diagonal to base)
c1= ent_getvertex(Terrain,NULL,SW-32);
Triangle[1].x=c1.v.x;
Triangle[1].y=c1.v.z;
Triangle[1].z=c1.v.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)
{
c1= ent_getvertex(Terrain,NULL,SW-33);
}
else
{
c1= ent_getvertex(Terrain,NULL,SW+1);
}
Triangle[2].x=c1.v.x;
Triangle[2].y=c1.v.z;
Triangle[2].z=c1.v.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);
}
TERRAIN PAINTING FUNCTION:
void Terrain_Paint(int x, int y)
{
//wait(1);
ENTITY* Terr = Terrain[x][y];
int i; //vertex info for terrain
BMAP* Source_BM;
//BMAP* NewSkin = bmap_createblack(512,512,24);
BMAP* NewSkin = bmap_create("Terrain_Sand.tga");
BMAP* OldSkin;
//bmap_for_entity (Terr,Terr.frame);
VECTOR Pixel_pos; //pixel coordinates for skin bmap
var height;
var slope;
var pixel_source; var pixel_dest;
//var t_format1; var t_format2;
COLOR* t_color; var t_alpha;
t_format1=bmap_lock(NewSkin,0);
// t_format2=bmap_lock(Sand_BM,0);
// t_format2=bmap_lock(Grass_BM,0);
// t_format2=bmap_lock(Rock_BM,0);
// t_format2=bmap_lock(Snow_BM,0);
for(Pixel_pos.y=0;Pixel_pos.y<512;Pixel_pos.y++)
{
for(Pixel_pos.x=0;Pixel_pos.x<512;Pixel_pos.x++)
{
// (0to31)+1 (((0to31)+1)*33)+1
i = (integer((Pixel_pos.x)/16)+1) + (((integer((Pixel_pos.y)/16)+1)*33));
height = get_height(Pixel_pos.x,Pixel_pos.y,i,Terr);
//slope = get_slope(Pixel_pos.x,Pixel_pos.y,i,Terr);
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(Source_BM);
}
}
// bmap_unlock(Sand_BM);
// bmap_unlock(Grass_BM);
// bmap_unlock(Rock_BM);
// bmap_unlock(Snow_BM);
bmap_unlock(NewSkin);
OldSkin=ent_getskin(Terr,1);
ptr_remove(OldSkin);
ent_setskin(Terr,NewSkin,1);
}
Call Example:
var t_format1; var t_format2;
t_format2=bmap_lock(Sand_BM,0);
t_format2=bmap_lock(Grass_BM,0);
t_format2=bmap_lock(Rock_BM,0);
t_format2=bmap_lock(Snow_BM,0);
for(x=0;x<TERRAIN_COUNT;x++)
{
for(y=0;y<TERRAIN_COUNT;y++)
{
Terrain_Paint(x,y);
wait(1);
}
}
wait_for(Terrain_Paint);
bmap_unlock(Sand_BM);
bmap_unlock(Grass_BM);
bmap_unlock(Rock_BM);
bmap_unlock(Snow_BM);
Turns out bmap_lock & bmap_unlock calls were making my paint function extremely slow. I don't have an exact number, but believe me, EXTREMELY slow. I used to lock a bmap when i draw a pixel, then unlock (per pixel) since i might not need that same texture for the next pixel, so I would only lock each texture while I'm using it. With that version I never saw the completion of a terrain (waited several minutes) before closing realizing something was terribly wrong or terribly slow... After that I moved the bmap_lock in my painter function before the loops and just locked all of them before hand, and moved the bmap_unlock after the loops, so they were locked and unlocked only once per terrain function. (lock*4 + unlock*4)*100 terrains = 1600 lock/unlock calls. This time I did manage to see the terrains painted after several minutes, but these times were still unacceptable. So I decided to move the lock/unlock calls out of my painter function. they are called once before painting ALL terrains consecutively, and called the unlocks after ALL terrains have painted. There have been more tweaks for speed, but lock/unlock seem to be what had the most impact on speed. hope this experience is a usefull warning for anyone using these functions when they attempt to paint several large textures. An example of the calls and the paint function are in the spoiler above. Also the height detection function was not working correctly, an updated version is also in the spoiler. I had also programmed separate cliff textures to be drawn on steep angles, but they didn't blend well with the rest no matter what textures I used. The overall look was terrible so I removed that code. @EvilSOB: even though you don't like calculating height between vertex, i hope this will help you out when you get to painting. The problem with random terains is that you can't have a pre-made texture looking good on it due to its randomness. And infinite worlds benefit greatly from randomized terrains. In my first attempt at painting I coloured each polygon entirely based on the average height of it's vertexs, and believe me it looks horrible. At least if you decide to take this route you have a head start I have another question regarding this memory problem we are working around... Does this also include textures? I mean, if I remove textures with ptr_remove(BMAP) and create new ones with bmpa_create will that also leave behind unused texture memory and end up growing till the system is saturated like with models?
|
|
|
Re: Dumb terrain question.. Cannot get it to move...
[Re: MrGuest]
#386514
11/04/11 05:07
11/04/11 05:07
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
OP
Expert
|
OP
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
Video looks good.
So lets look at the slow painting problem. Do some horsepower tests for me IF you can. We will slowly disable segments of your painting to see where all the horsepower is going by doing a speed-test on each of the below steps.
0> I cant see any, but if there are any wait commands WITHIN a single terrain calculations, disable them. Waits between terrains is OK. Dont speed test this step.
1> Disable ONLY the pixel_for_bmap and pixel_to_bmap COMMANDS. Just the individual LINES, not chunks of code. We still want all the height and color CALCULATIONS to take place.
2> Now disable ALL the COLOR/PIXEL calculations as well, leaving the height calcs in.
3> Next disable all the HEIGHT calculations as well. All that should be left is the bmap_lock and bmap_unlock's, and bmp_create's.
4> Next disable all the BMAP_CREATEs if you can find a way. Maybe create a single global 512x512 bmap and just keep re-using it in place of the bmap_creates. All that should be left is the bmap_lock and bmap_unlock's.
5> Finally, disable all the bmap_locks and bmap_unlocks.
Post the approximate results (in seconds) that you can measure for each step. Until we know which PART is eating CPU, it going to be hard to optimise. Also please do all the steps if you can. Dont stop just because it appears that you've found 'the one', later-step results may be important too. If you need to skip a step because it is just not possible code-wise, then so be it...
Also ... can you use shaders? Do you own a 'high' enough version of gamestudio?
Any of this is "unlikely" to help me, as I wont be doing any REAL painting. My map isnt random. It comes from a monster height-map. (16384*12288 ATM and may grow) So I plan on storing a simple color mask for using with a multi-tex shader in it too. The simple color mask (128x128) get loaded at the same time I load my vertex heights(128x28), and "blurred" into a 512x512 texture that the multi-tex shader will use. At LOD-change time those heights will get lerped up into a 256x256 terrain if it is LOD_0 or down to 32x32 for an LOD_3 terrain.
And I can say concisely that the textures WILL completely free their memory when you use BOTH bmap_purge then bmap_remove. (dunno about ptr_remove though)
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
|