Dumb terrain question.. Cannot get it to move...

Posted By: EvilSOB

Dumb terrain question.. Cannot get it to move... - 09/27/11 13:09

Hiya all...

I feel kinda dumb askin this? But how can I get a terrain to move?

Im using ent_createterrrain to create it,
then setting the DYNAMIC flag (to no avail),
feeding its pointer to a function and trying
to manipulate its XYZ co-ords directly.

Ive been playing and reading for an hour now, but it remains
firmly fixed in place...

Any ideas anyone?
Posted By: Superku

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 13:13

Terrain cannot be moved, you need to remove and recreate it.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 13:22

No way ... at ALL ... EVER??

But If I gotta keep removing and re-creating, what that going to do
to my memory consumption?

Or do ent-remove'd terrains actually FREE their resources?
Posted By: Superku

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 13:25

Why do you need to move terrains anyway? Are you working on an editor?
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 13:33

No, Im looking into an endless-terrain world concept where the
terrain is generated in the distance infront of you, and erased
in the distance behind you.

I was going to have a 'store' of terrain entities and just adjust their
heightmaps as they get activated on your horizon, as low-poly terrains.
And as the get closer, they get replaced by higher-poly terrains from
a different LOD 'store' and that gets a more detailled hightmap inserted.

See where Im going? Im trying to create a "potentially" edgeless world.

I may need to go back to an older concept of using entities instead of terrains.
Its just the new addition of ent_createterrain gave me new ideas...
Posted By: 3run

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 14:35

Dude, I'm not sure, but may be this could help you?
The Sewer

Edit: I misunderstood you problem dude, sorry.
Posted By: Progger

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 14:58

why not using vertex to move it?
you go throug every vertex of the terrain and move it forward
maybe this is a solution
WFG PRogger
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 18:04

3run: It may well help with the stitching later, if I can get the entity
vertices to follow the same numbering structure as terrains, but it contains
nothing to help me at THIS stage.

Progger: I see what you mean, but its just not feasable dude.
When Im potentially moving a terrain by up to 2,000,000 quants in both
the X and Y directions, the maths will get pretty ugly. And thats assuming
Also, having a terrain with vertices as much as 1,000,000 quants away form
its origin could possible cause some serious performance issues, or odd
collision-hull behaviour...
Posted By: rojart

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 18:21

Already tried the infinite_terrain.c that uses the level.c library from sample folder, or you are looking for something special?
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 18:27

No rojart, the infinite terrain uses "special effects" to make a single
terrain look like many.

Whereas mine will be many UNIQUE terrains looking like a huge single terrain.

Im going back to using pseudo-terrain models for now anyways...
Posted By: rojart

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 21:35

ok I understand, similar to the procedural terrains like acropora, right?
Posted By: MrGuest

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 22:39

maybe a stupid question (they usually are) why are you trying to move the terrain and not just placing it where it's required on its creation?
Posted By: rojart

Re: Dumb terrain question.. Cannot get it to move... - 09/27/11 23:51

Another possible example is to use the CONTACT* struct pointer, like this:

WSAD - moving terrain

Code:
#include <default.c>

function main()
{
   d3d_lines = 3; level_load("");
	
   vec_set(camera.x,vector(-150,0,100));
   vec_set(camera.pan,vector(0,-30,0));
	
   ENTITY* terrain = ent_createterrain(NULL,nullvector,10,10,10);
   ent_setskin(terrain, bmap_fill(bmap_createblack(32,32,16),COLOR_WHITE,100), 1);
	
   you = ent_create(SPHERE_MDL,nullvector,NULL); vec_scale (you.scale_x, 2);
   ent_setskin(you, bmap_fill(bmap_createblack(32,32,16),COLOR_GREEN,100), 1);
	
   while(1){
      int i = ent_status(terrain,0);
      for (; i>0; i--) { 
         CONTACT* c = ent_getvertex(terrain,NULL,i);
         c.v.x += 10 * (key_w - key_s) * time_frame;
         c.v.z += 10 * (key_a - key_d) * time_frame; // Y = Z (DX coordinate system)
         ent_setvertex(terrain,c,i); 
      }
   c_setminmax(terrain);
   wait(1);
   }
}


Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/28/11 10:12

rojart: Yeah, much like that, but generated on-the fly inside the engine.
Each time an entiry/terrain "slab" is moved, I re-generate its vertex
height-maps to match its new locations. (and stitch it to its neibours)

MrGuest: Not so stupid, so think of it like this.
I want to cross a HUGE patch of muddy ground, and Im carrying a couple of planks.
I put one plank down, and walk along it, then I put the other plank down.
Once I step onto it, I pick up the first plank, and carry it to the end of the plank Im now on.
I then put the plank Im carrying down and step onto it, and pick up the other plank.
I now walk to the end of plank Im on and put the plank Im carrying down, ETC.
So you see I can cover a large patch of ground with only two planks.
Thats why I want to recyle my terrains(planks), because if I just keep
creating then destroying terrains, I rapidly run out of (nexus?)memory.

rojart: Nice idea, but no good. See my previous reply to progger...


Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 09/28/11 15:26

If you are creating and destroying the same terrains, I doubt it'd be consuming more memory with each creation.
Posted By: MrGuest

Re: Dumb terrain question.. Cannot get it to move... - 09/28/11 16:03

Originally Posted By: JibbSmart
If you are creating and destroying the same terrains, I doubt it'd be consuming more memory with each creation.
that's what I was thinking, plus the advantage of creating them dynamically would be to allow for a higher number of variances without making all the terrains depending on where the player goes.

this method of reusing and recycling them now seems somewhat redundant and you may aswell make them only once when the game is loaded?
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/28/11 19:13

Jibb and Mister... Thats what I USED to think, its logical right?

But NOOOO, its not!

After much discussion with JCL, this is NOT a bug, its just the way things are.

Admittedly we were disussing entities rather than terrain, so I assumed the same.

So I just did a test, to prove the point.

Run this following stand-alone script (A8 only of course), and open your
windows task manager, and watch every byte of memory get (not so) slowly consumed!

Click to reveal..
Code:
#include <acknex.h>
#include <default.c>
//
//
void main()
{
  	wait(1);	level_load(NULL);	wait(1);
	ENTITY* terr = NULL;			var count=0, x;
	BMAP* fake = bmap_createblack(128,128,24);
	//
	while(1)	
	{
		for(x=0; x<10; x++)
		{
			if(!terr)
			{	terr = ent_createterrain(fake, vector(1000,0,0), 128,128,5);
				/*ent_clone(terr);*/			count++;									}	
			else			
			{	ent_remove(terr);		terr = NULL;									}
		}
		//
		draw_text("created/removed = ", 100, 100, COLOR_WHITE);	draw_text(str_for_int(NULL, count), 250, 100, COLOR_WHITE);
		draw_text("nexus = ", 100, 130, COLOR_WHITE);				draw_text(str_for_int(NULL, nexus), 200, 130, COLOR_WHITE);
		draw_text("sys_memory = ", 100, 160, COLOR_WHITE);			draw_text(str_for_int(NULL, sys_memory), 250, 160, COLOR_WHITE);

		wait(1);
	}
}



I dont understand your final statement MrGuest? If I cant MOVE terrains, I CANT re-use them...
Posted By: MrGuest

Re: Dumb terrain question.. Cannot get it to move... - 09/28/11 21:07

I was thinking along the lines of if you're placing them dynamically, you'll only need to do so once for preventing duplication. therefore you'll place them only once without moving them.

Having them created dynamically allows for a greater variation of terrain so I don't get why you'll want to reuse them again and again.


Your example shows a problem with ent_remove for the dynamic terrain, the same test without removing the terrain shows the same memory usage.
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 03:32

Have you tried an ent_purge before you ent_remove it?
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 07:48

Jibb: ent_purge makes no significant change.

MrGuest: My expample was meant to show that creating a terrain and deleting it
later does NOT release all its used memory. And that is their limitation.
Youve got to realise that the plan is to have a never-ending world,
so that means that level_load never gets used, except when entering or leaving the world.
And the terrains Im creating are FLAT and I apply my own height-map to the vertices
during run time. And when the terrain is too far away to be seen, it gets put
into 'limbo' as a spare. When it gets pulled out of limbo for re-use,
it gets a DIFFERENT height-map applied.
So Im not re-using the terrain SHAPE, just the entity itself.
Posted By: MrGuest

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 11:52

I understand what you're saying and know the terrains are flat, but didn't realise you can't remove the terrain due to it not releasing memory.

Either moving terrains is the issue OR not releasing memory when removing terrains. As moving terrains has been like this since I remember and there's no plan on changing this, our problem is not being able to remove a terrain efficiently.

If moving terrains were possible, you'd only need to create n amount of terrain tiles and move them around which you could just make in MED or at least prior to runtime and not require using ent_createterrain.

(You will always have the problem of not being able to exceed the limitation of a VAR though).

laugh
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 12:23

Okay, last question from me: Have you tried ent_create instead of ent_createterrain?

I see how that might perhaps be what you're already doing, and the example you posted was just using ent_createterrain to be an asset-free example we can all run, but just checking. ent_createterrain inherently creates a new terrain file, while ent_create would allow you to re-use terrains. Using that in combination with ent_purge might just do it.
Posted By: MrGuest

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 13:13

I've had look at ent_create for .hmp files and still have the same problem of not releasing memory on ent_remove with or without ent_purge.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 13:33

MrGuest: (first post) Correct on all points, and an excellent summation
of this entire thread, and clear description of the reason for my first post.

Jibb: Yeah, I have GONE BACK to working with entities now. But I was HOPING
that terrains would be do-able, but at this point it looks like terrains are out.
So back to working with entities it is. I AM makeing progress with them.
But terrains would have required less 'messing about' than entities require.

MrGuest: (second post) Yeah, but BOTH HMP's and MDL's dont release ALL memory on removal.
Thats just how the engine works. And after a long discussion with JCL an age back,
it made sense how thats the only way it can work... Assuming I understood him correctly.
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 17:35

Actually, I meant ent_create-ing terrains. It's possible according to the manual, anyway.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 18:13

No can do JibbSmart. It suffers from the same memory-hungry losses.
But creating a fixed number of entities and re-using them is working so far.
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 19:58

Okay, that's ridiculous (as you're obviously already aware). Glad you got it working with MDLs.

Jibb
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 20:20

Its very IRRITATING, but not actually ridiculous, as JCL explained to me once.

We'll see how well I remember. Its all got to do with how GS caches its memory.
Im just talking about "level-cache" memory, not video memory...

Lets say you ent_create 'ModelA', and it uses 100K of memory.
Later on, you ent_remove it. This memory is no longer used, but is still cached.
Now ent_create another 'ModelA', and it uses ANOTHER 100K of memory.
Later on, you ent_remove it. This memory is no longer used, but is still cached.

Thats where all the memory goes... BUT, its not really that bad, because if
you do a level_load or a level_free, THEN the memory is completely cleared and released.

But thats no good to ME, because I NEVER DO any level_load or level_free's because
I dont want to lose ALL the game-objects created since the last level_load or level_mark.


Do you want further reasoning about WHY the ent_removed memory stays allocated?
I cant remember sorry, all I can remember is that the memory DOES get used for
other stuff, but never re-used by entities.
I THINK it was something like that GS doesnt know how much level-cache an entity
will need until it is FINISHED loading into cache, and so to avoid trying to load
it into a 'gap' that is too small, and thereby corrupting following data,
they simply avoid the issue by always getting loaded on the end of the cache.

Thats my understanding anyway...
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 20:43

Yuck. I never, ever level_load either (except on startup). That's really awful. But in my game I can probably handle it with some careful level_mark and level_free, as everything created after a certain point is temporary. In your situation that obviously doesn't work.

At least I learned something. Thanks.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 09/29/11 22:27

my pleasure.
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 10/31/11 14:32

I had the very same idea for an infinite terrain system (endless world) I came up with and am running into the same problems...

I load a certain number of terrains around the player and I also load a heightmap to terrains at runtime depending on the character's position. I first tried to move them (like your first attempts) but they cannot move. So I started to remove the ones left behind and create the new ones the player is coming close to...

Then I found this thread and it is like a slap on the face, lol!

If I understood you correctly, you are trying to achieve the same thing as I am? And the old entities being removed never free the memory? So I will end up running out of memory even though I always only have 25 (5x5) terrain entities loaded at once?

Did I understand everything correclty? even when removing entities the memory usage just keeps growing and growing?
So then your solution is to make huge models with lots of vertices that look like a terrain so you can use them instead and move them around?

This does not seem like a viable solution to me if all other entities also behave this way (I don't know how your game works, if your game is empty and only uses terrains and a player model it might work fine. But in mine I need to load more things on the terrains).
If all models behave this way with memory, this brings another concern for me: what about other types of entities? (my plants, enemies, and buildings are the frist examples that come to mind...)
Even if I start using entities to simulate terrains like you do, so I can move them and never have to remove/create them all the time, won't the other entites (enemies, plants) that are also being created/removed leave behind alot of unused memory?

I am not sure if I understood everything correctly, but if I did... Then even if I fix the memory problem for terrains like you did (using huge models and moving them), everything else that gets leaded/removed will still produce this memory problem?

What are your thoughts on this new problem? Have you already thought about it? Do you have a solution for this also?
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 10/31/11 15:12

Yes.
Not all of it.
Eventually.
Yes.
Yes.
Yes.
Me too.
They will cause the same problems too.
Sure will.
Certainly.
I hate it!
Many months of it.
Maybe.



grin BTW, a more detailled post will follow soon...
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 10/31/11 15:30

Originally Posted By: Carlos3DGS
I had the very same idea for an infinite terrain system (endless world) I came up with and am running into the same problems...

I load a certain number of terrains around the player and I also load a heightmap to terrains at runtime depending on the character's position. I first tried to move them (like your first attempts) but they cannot move. So I started to remove the ones left behind and create the new ones the player is coming close to...

Then I found this thread and it is like a slap on the face, lol!

If I understood you correctly, you are trying to achieve the same thing as I am? And the old entities being removed never free the memory? So I will end up running out of memory even though I always only have 25 (5x5) terrain entities loaded at once?
Yes, Im trying to do the same thing. Ive been trying on and off for over a year.
MOST of the entities memory gets removed, but always some remains, so eventually it WILL reach critical levels.


Did I understand everything correclty? even when removing entities the memory usage just keeps growing and growing?
So then your solution is to make huge models with lots of vertices that look like a terrain so you can use them instead and move them around?
Yup, you got it ALL right, and have both hit, and foretold, the same problems that are giving me so much grief.
By re-using the same models/entities over and over, in different places, we dont have the memory problem.


This does not seem like a viable solution to me if all other entities also behave this way (I don't know how your game works, if your game is empty and only uses terrains and a player model it might work fine. But in mine I need to load more things on the terrains).
If all models behave this way with memory, this brings another concern for me: what about other types of entities? (my plants, enemies, and buildings are the frist examples that come to mind...)
Im HOPING the solution will be to pre-create a ship-load of entities and keep unused ones in storage,
and just use ent_morph on them when I need some. And put em back in storage when they are no
longer need to be 'active'.


Even if I start using entities to simulate terrains like you do, so I can move them and never have to remove/create them all the time, won't the other entites (enemies, plants) that are also being created/removed leave behind alot of unused memory?
Yes. See my above comment.

I am not sure if I understood everything correctly, but if I did... Then even if I fix the memory problem for terrains like you did (using huge models and moving them), everything else that gets leaded/removed will still produce this memory problem?
Yes. See my above comment.

What are your thoughts on this new problem? Have you already thought about it? Do you have a solution for this also?
Yes. See my above comment.


Hope this helps clarify things a bit...

YOU ... ARE ... NOT .. ALONE
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 10/31/11 16:44

I was thinking about this after I posted and I came up with a terrible solution (but that has some similarities with yours): loading on startup a certain number of each type of entity that will be repeated alot on the terrain. For example load 100 of tree1.mdl, another 100 of bush5.mdl, 100 of tree3.mdl, etc, etc etc... and moving them all to somewhere well hidden from (like lower than any terrain (vec_set(my.x, vector(0,0,-1000000))). whenever I need a tree instead of ent_load I just set its pos to the correct location, and instead of deleting one I just set it back to (0,0,-100000000). But I didn't really like this idea and it seemed like a very sloppy workaround with many limitations.

After reading your answers, ent_morph + storing unused entities seems like a very smart approach to this problem (and much better than my terrible&&painfull idea).

I have been thinking about this for a while and come up with a another concept to fix some of the problems both systems have. My idea has severe limitations. Your approach of loading a ship-load of entites + ent_morph for re-use is much better but also has certain limitations and a potencially extreme load time.

In another aspect of my game I have been working alot with malloc() sizeof() and free() for several linked lists, and this is what gave me the idea. We create an empty linked-list on startup and program our own ent_create_2 and ent_remove2 functions.

The linked list would just be a struct of 2 pointers, one entity pointer, and one struct pointer.

The ent_create_2 function first looks at the linked list, if it is empty it creates a new entity with our position and model parameters. else if there is already an item in the list, it modifies it position properties and uses ent_morph with the model parameter, and removes the item from the linked list.

The ent_remove_2 function sets the model's invisible and passable flags, morphs it to a very simple dummy model (one centered vertex), places it in a hidden location well under our terrains (0,0,-1000000000), and add the item to the linked list.

with this system you avoid having to create a ship-load of entites on launch, saving alot of load time. it only increases the amount of entities loaded when needed (you reach an area with more entities than the previous areas you visited). and in the worst-case scenario you will never have more entites loaded (used + not_used) than the zone you visited that had the most entities. This system also solves the problem of not knowing how many entities you will need before reaching a certain area.

My only concerns now are the free() and ent_morph() instructions... Seeing how ent_remove() works I am now scared that any other removal/modification instruction may also leave behind unused memory. But even though ent_remove() is terrible, if these other two instructions do work how they are supposed to we might have solved the problem with free() and ent_morph(). Do you think it is worth a try? Do you know if free() and ent_morph() also leaves behind unusable memory?

If this system works I will probably make it a separate module and include it in every future project and never ever use ent_remove again. (even on projects that dont have infinite worlds! After reading this thread I have developed a passionate hatred of the ent_remove function!)

The only problem I see with your approach (and also my linked-list approach) is that action functions cannot be used with entities using this system (and that potencially also includes events).

I will post back in a while with a modified version of my current linked-list system adapted for this problem.

EDIT: You made me laugh with this answer when re-reading my initial post:
Quote:
-What are your thoughts on this new problem?
-I hate it!

Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 10/31/11 17:38

This is the entity system I talked about above that should solve our problems (or at least most of them). I have to leave and it is untested, but it should work. If it dosn't work I will revise it when I come back home later tonight or tomorrow.

Code:
typedef struct StackNode
{
	ENTITY* StoredEnt;
	struct StackNode* prev;
} StackNode;

StackNode* StackFirst = NULL;//needed pointer to start of list
StackNode* StackLast = NULL;//needed pointer to end of list
int StackCount=0;//counter of items in list

void StackAdd(ENTITY* myent)
{
	StackNode* StackNew;//new pointer
	StackNew = malloc(sizeof(StackNode));//reserve memory
	StackNew.StoredEnt = myent;//assign values
	
	if(StackCount==0)//if the list is empty
	{
		StackFirst=StackNew;
		StackNew.prev=NULL;
	}
	else
	{
		StackNew.prev=StackLast;
	}
	StackLast=StackNew;
	
	StackCount++;
}

void StackPop()
{
	StackNode* StackCurrent;
	
	StackCurrent=StackLast;
	if(StackCurrent!=NULL)//if the list is NOT empty
	{
		StackLast=StackCurrent.prev;
		free(StackCurrent);
		StackCount--;
	}
}

ENTITY* Ent_Create2(STRING model, VECTOR pos, ANGLE angle)
{
   ENTITY* myent;
	if(StackLast!=NULL)//if there are availabe entities to recycle in our list
	{
	   myent=StackLast.StoredEnt;
		ent_morph(myent,model);
		vec_set(myent.x,pos);
		vec_set(myent.pan,angle);
		reset(myent, PASSABLE| INVISIBLE);
		c_setminmax(myent);
		StackPop();
		return(myent);
	}
	else
	{
	   myent=ent_create(model,pos,NULL);
	   vec_set(myent.pan,angle);
	   c_setminmax(myent);
	   return(myent);
	}
}

void Ent_Remove2(ENTITY* myent)
{
   set(myent, PASSABLE| INVISIBLE);
   vec_set(myent.x,vector(0,0,-1000000));
   ent_morph(myent,"DummyEnt.mdl");
   StackAdd(myent);
}



The code is slightly commented, but if there are any questions feel free to ask.

I hope this helps us!

If you come up with any problems derived from using a system like this for recycling entities please post and I will think of another solution.

The only thing I see failing with this is that entity actions are not supported for recycled entities, but for trees, buildings, and most static objects it shouldn't be a problem. If you come up with a better version/system to support actions and events for recycled entities feel free to modify, and mabe post your ideas so I can implement also, I am very interested in giving this system as much flexibility as possible to never have to use ent_remove ever again! grrrr (IMHO, if entities leave some unused memory behind when removed... then this is how ent_create and ent_remove should have been made from the start)
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 10/31/11 17:41

After looking back over my old code, which I havent played with in quite a few of months,
I found my "partially" developed linked-list system that I was going to use with my terrains...
Since then Ive gone for an array(grid) with a fixed number of pre-created entities.

My old stuff has MUCH in common with yours, including a NOTATION suggesting more research/testing
of an "ent_create as needed with limit" approach. Sound familiar?
Some other 'notes to self' were as follows.

Dual linked lists. Identical structure, one is 'active' other is 'spare'. Entity moves from list to list as its status changes.

Dual-priority ent_recreate [you called yours ent_create_2]. Dual priority calling.
HIGH priority = use first found 'spare' entity. LOW priority = search list to try to find matching model to requested one.

ent_idleize (your ent_remove_2) PASSABLE, INVISIBLE, Z=-5000, kill any actions.


And thats just a few.

I too am concerned about ent_morph, and because I normally need to use ent_clone alot, I worry about it too.

With your usage of Malloc, Free etc, you should shift to SYS_malloc and SYS_free etc.
More engine friendly, and they DO release all memory for re-use...

ALSO!!! BEWARE OF sizeof.... check my posting in the BugHunt forum.


Actions are not a problem. But they are 'faked' actions. Like so...
Code:
void My_Action(ENTITY* ME)
{
   me = ME;
   ...
   everything else as normal


And you just call it from inside the ent_recreate function, with the 'new' entity as the parameter.

And inside the entities action-loop, just watch to see if "I" am in the ACTIVE linked-list,
or in the IDLE linked-list. If I am in the IDLE list, just execute a RETURN;
I would never do something this 'dirty', but you get the idea.


But Im not actively working on this ATM... A few sub-projects stand in the way.

Im helping Esper out with his menu system, and I've got some outstanding weapon-system stuff for 3run I gotta get to,
and then I have to take a look at my ancient port-IO contribution for someone...

Busy, busy, busy...
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 10/31/11 20:56

The second linked-list for stopping the action feels like overkill to me. It seems to complicate the linked lists alot to controll something that dosn't need a second list. It would probably be easier to set a skill to 1 when creating/recycling an entity, and setting that skill to 0 when adding to the "inactive list", then in the function that acts like a "fake action" instead of using a while(1) and a return just use a simple while condition that uses that skill.
Code:
void False_Action(ENTITY* ME)
{
   me=ME;
   my.emask |= (ENABLE_BLOCK | ENABLE_ENTITY);
   my.event = blablabla_event;

   while(my.skill25==1)
   {
      //do whatever the action would do
      wait(1);
   }

}


This would remove the need for a second linked-list, and it would also avoid the need for the linked lists to be dual (or bi-directional) for searches. That way you could keep the list working like a simple stack as in my previous post's example.

About the actions: I see how a function recieving a ent pointer could substitute an action. But how do I tell my ent_create_2 function which function it needs to run for the ent? is there any way to set a pointer to a function and pass that as a parameter to my ent_create_2()? Or to use a string containing the funtion name to use some macro to run a function?

About the events: I havn't tested it but it seems with that function acting as an action it should be possible to set the events and all... But how would I invert the process later when recycling the entity to remove its events? the my.event could be easily redirected to an empty "dummy" event function and reset later to whatever new event function the ent needs. But how would I know what flags were previously enabled to disable them? (like ENABLE_BLOCK or ENABLE_ENTITY)



EDIT: Being so busy is a good sighn. It means 1.You enjoy what you do, and 2.you are good at what you do

wink


Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/01/11 03:04

The IDLE link-list does more than JUST allow the action to self-terminate.
It is also an INSTANT way to grab an idle entity. Just grab the first in the list.
That way you dont need to wade through potentially dozens of active entities
when trying to find an idle one to re-use.
And (from memory) it was only like 3 lines of code to make an entity switch lists.
The IDLE list was only implemented single-directional searches. Thats all it needed.


How do you NORMALLY tell ent_create what action to use? Do the same for ent_create_2!
Code:
void action_ptr(ENTITY* ME);	//an empty function pointer

...


ENTITY* ent_create_2(STRING* filename, VECTOR* position,  EVENT my_action)
{
	ENTITY*  entity_to_reuse = something;
	...
	action_ptr=my_action;	action_ptr( entity_to_reuse );	action_ptr=NULL;
}



As for the events... have the funct/action ITSELF shut them down. Put the event-disabling
code AFTER the while loop. So when the entity recognises it is idle, and exists the loop,
it will then disable its own events...

Code:
void False_Action(ENTITY* ME)
{
   me=ME;
   my.emask |= (ENABLE_BLOCK | ENABLE_ENTITY);
   my.event = blablabla_event;

   while(my.skill25==1)
   {
      //do whatever the action would do
      wait(1);
   }

   my.emask &= ~(ENABLE_BLOCK | ENABLE_ENTITY);  
   my.event = NULL;
}



Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/01/11 10:47

Quote:
With your usage of Malloc, Free etc, you should shift to SYS_malloc and SYS_free etc.

I have been reading sys_malloc and sys_free in the manuall but I don't uderstand what it does. Why is it different/better?

Quote:
action_ptr=my_action;

wow, I had no idea functions could behave like a pointer. I thought it would be much more complicated to get that working. Thanks alot for the info!
I also have a uni directional linked-list for the "inactive" entities, and use it as a stack for pulling the last one for re-use. When I said mabe two linked lists might not be necessary I meant the other one, the "active" linked-list.

And now that I am using models for my terrains I am having trouble with the shadows... It looks terrible where they join. Did you have the same problem? How did you fix it?
It looks like its a problem with smoothing the gourad shading on each model individually.
I tried with the UNLIT flag and setting its ambient high so it would be lit. But it seems I cannot get rid of its gourad shading that way.

Here is link to a quick video I just made showing how the edges of the terrains are shading separatly for each model:
http://www.youtube.com/watch?v=emOdg111H4Q

I tried with setting unlit, cast, and also resetting the shadow flag. But it still looks awfull, I can't think of how to get rid of those terrible shadows that make the edges of my terrains so obvious...
Any suggestions?
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/01/11 11:52

Well, functions and pointers are really the same.
An ACTION (and also an EVENT) are really just VOID function, and by passing its address
as a parameter is as easy as passing any other VOID*. Then assign that address
to an unused function pointer... easy.


I see your shadowing problem, and I EXPECT to hit the same, but Im not that far yet...
Im still trying to get the entities to arrange themselves properly around the focus point.
Not so easy because I have a circle of LOD_0 at the focus, surrounded by a thick
ring of LOD_1 entities, etc. out to LOD_3. Getting them to arrange based on a
single formula is the tricky bit, as I need a single formula to to this .
Because the game (at boot up) calculates the clip_far to use, and how "big" each lod circle is.
This result gets fed to the terrain-management, and the entities are created/arranged.
So... for low-power PC's, the total terrain "circle" is small (115 entities),
and for higher-powerd PC's it is bigger (465 entities).
[/i]See spoiler at the bottom for some preliminary calculations.[/i]

Ive not gotten to changing heights yet. Once the entities are arranging correctly,
then I'll implement the height mapping. So I expect your problem, even though
I havent had to deal with it "yet".

What I expect to need to do is integrate a "normal recalculation" into the stitcher code
that looks at BOTH entities, and adjusts BOTH their normals for the edge pixels/polys,
based on the value one entity normal plus the other entity normal divided by two.



My entity LOD rings. (still in preliminary testing ATM)
This is only showing THREE of the seven steps possible.
Click to reveal..
Code:
100% = 50,000 quants = 465 tiles

........3333333333........
......33333333333333......
....33333333333333333.....
...3333333333333333333....
..333333333333333333333...
..3333333333333333333333..
.333333333322223333333333.
.333333332222222233333333.
33333333222222222233333333
33333332222222222223333333
33333332222111122223333333
33333322221100112223333333
33333322221000012222333333
33333322221000012222333333
33333322221100112223333333
33333332222111122223333333
33333332222222222223333333
33333333222222222233333333
.333333332222222233333333.
.333333333332233333333333.
..3333333333333333333333..
...33333333333333333333...
....333333333333333333....
.....3333333333333333.....
......33333333333333......
........3333333333........


75% = 37,500 quants = 261 tiles

....333333333.....
...33333333333....
..3333333333333...
.333333333333333..
33333332222333333.
33333222222233333.
333332221222233333
333322210112233333
333322100012233333
333322210012233333
333322211122233333
33333222222233333.
33333322222333333.
.333333333333333..
..33333333333333..
...333333333333...
....333333333.....
......33333.......


50% = 25,000 quants = 115 tiles

..3333333...
.333333333..
33333333333.
33322222333.
333221123333
333210022333
333210122333
33322222333.
33333223333.
.333333333..
..3333333...
....333.....


Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/01/11 18:52

thankyou very much for the idea of vertex normals, i probably would not have thought that on my own and kept trying different flags and mabe even some shaders and stuff before giving up!

Here is a video of the new look thanks to modifying normals:
http://www.youtube.com/watch?v=6RvUfXQ8_ZA

an example code for how I implemented one of the edges (works for terrains with 33x33 vertexs)
Code:
void avg_normals_N(int x, int y)//NORTH EDGE SMOOTH NORMALS (SHADOWS)
{
	int tx; //vector counter
	VECTOR nml[2];
	VECTOR mid_nml; //average height of touching vertex's
	CONTACT* c1; //contact vertex for Terrain
	
	
	if(y<TERRAIN_COUNT-1)
	{
		for(tx=1;tx<32;tx++)
		{
			vec_set(mid_nml,nullvector);
			vec_for_normal(nml[0],Terrain[x][y],1+tx);
			vec_for_normal(nml[1],Terrain[x][y+1],1057+tx);
			vec_add(mid_nml,nml[0]);
			vec_add(mid_nml,nml[1]);
			vec_normalize(mid_nml,1);
			
			c1 = ent_getvertex(Terrain[x][y],NULL,1+tx);
			//vec_set(c1.v.nx,mid_nml);
			c1.v.nx=mid_nml.x;
			c1.v.ny=mid_nml.z;
			c1.v.nz=mid_nml.y;
			ent_setvertex(Terrain[x][y],c1,1+tx);
			
			c1 = ent_getvertex(Terrain[x][y+1],NULL,1057+tx);
			//vec_set(c1.v.nx,mid_nml);
			c1.v.nx=mid_nml.x;
			c1.v.ny=mid_nml.z;
			c1.v.nz=mid_nml.y;
			ent_setvertex(Terrain[x][y+1],c1,1057+tx);
		}
	}
}



notice how I commented this line:
//vec_set(c1.v.nx,mid_nml);
I forgot ent_setvetex uses dx coordinate system so z and y are swapped. I was getting really odd results till I realized and simply setting the parameters manually changing the axsis solved everything:
c1.v.nx=mid_nml.x;
c1.v.ny=mid_nml.z;
c1.v.nz=mid_nml.y;

The corners get more complicated though, here is an example of one of my corner functions:
Click to reveal..
void avg_normals_SE(int x, int y)
{
int tv; //vector counter
VECTOR nml[4];
VECTOR mid_nml; //average height of touching vertex's
int nml_count;
CONTACT* c1; //contact vertex for Terrain


vec_for_normal(nml[0],Terrain[x][y],1089);
nml_count=1;
if(x<TERRAIN_COUNT-1)
{
vec_for_normal(nml[1],Terrain[x+1][y],1057);
nml_count++;
}
if(y>0)
{
vec_for_normal(nml[2],Terrain[x][y-1],33);
nml_count++;
}
if(x<TERRAIN_COUNT-1 && y>0)
{
vec_for_normal(nml[3],Terrain[x+1][y-1],1);
nml_count++;
}

if(nml_count>1)
{
vec_set(mid_nml,nullvector);
for(tv=0;tv<nml_count;tv++)
{
vec_add(mid_nml,nml[tv]);
}
vec_normalize(mid_nml,1);

c1 = ent_getvertex(Terrain[x][y],NULL,1089);
//vec_set(c1.v.nx,mid_nml);
c1.v.nx=mid_nml.x;
c1.v.ny=mid_nml.z;
c1.v.nz=mid_nml.y;
ent_setvertex(Terrain[x][y],c1,1089);

if(x<TERRAIN_COUNT-1)
{
c1 = ent_getvertex(Terrain[x+1][y],NULL,1057);
//vec_set(c1.v.nx,mid_nml);
c1.v.nx=mid_nml.x;
c1.v.ny=mid_nml.z;
c1.v.nz=mid_nml.y;
ent_setvertex(Terrain[x+1][y],c1,1057);
}
if(y>0)
{
c1 = ent_getvertex(Terrain[x][y-1],NULL,33);
//vec_set(c1.v.nx,mid_nml);
c1.v.nx=mid_nml.x;
c1.v.ny=mid_nml.z;
c1.v.nz=mid_nml.y;
ent_setvertex(Terrain[x][y-1],c1,33);
}
if(x<TERRAIN_COUNT-1 && y>0)
{
c1 = ent_getvertex(Terrain[x+1][y-1],NULL,1);
//vec_set(c1.v.nx,mid_nml);
c1.v.nx=mid_nml.x;
c1.v.ny=mid_nml.z;
c1.v.nz=mid_nml.y;
ent_setvertex(Terrain[x+1][y-1],c1,1);
}
}
}


Hope this helps and saves you headache and time for when you get to that part in your version.
You are not alone either grin

And thanks again for pointing me in the right direction!

Your LOD idea is pretty good though im not sure I will implement something like that. I am going for a cartoony/goofy look to my game. Mainly for 2 reasons, its more friendly for an indie's time budget, and because with simpler models I can load tons more. My trees will probably be a deformed low poly cylinder for the stump, and either a deformed low poly cone or sphere for the leaves. My trees will probably have less polygons than a low LOD tree normally has in one branch.


Uploaded with ImageShack.us
(and I'm considering lowering the poly count even more, LOL!)
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 06:53

Ive set this thread to watched, and I HOPE I will remember to come back here
when I reach this point. This code WILL be useful. Thank you.

And Im glad to have helped you out... The video looks MUCH better now.

And you think your code is tricky at corners? I cant wait tongue to get to
trying to stich together entities of differing LOD levels...
One has half the vertices of the other...

And I need my LOD's because my view-range is like 25,000 to 50,000 quants,
depending on users available horsepower.
And Im aiming at NEAR-photo-realistic graphics. (terrain anyway)


I look forward to seeing your progression. So if you need help, or just
want to "show off" your progression, feel free to PM me.

Best of luck, and keep up the good work. grin
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 10:59

I see your problem there, but cannot think of a solution even for the first sewing/splicing step.


Code:
high detail terrain viewed from side:
.    .    .
 .  . .  .
  ..   ..

low detail terrain viewed from side:
.    .    .

both terrains spliced/sewn:
.____.____.
 .  . .  .
  ..   ..
(lines represent low vertex count terrain result)




How are you going to achieve that if they have a different amount of vertex?


EDIT: I just came up with an idea that might help. Since we are not working with terrains but with models that look like them... You have an advantage over terrains, you don't need to make all the rows the same.

Code:
Low detail terrain:
.  .  .  .  .  .

.  .  .  .  .  .

.  .  .  .  .  .

.  .  .  .  .  .

Mid terrain (used for between HighLOD and LowLOD for splicing):
.  .  .  .  .  .

. . . .  . . . .

. . . .  . . . .
................
................

High detail terrain:
................
................
................
................
................
................
................
................



the vetex calculations for the middle terrain will be a pain, but it should be achievable this way.
The array (or whatever) holding the height data should be the same as any high detail terrain for all of them. on the high detail one loading is strightforward, on the low detail just skip x vertexses in the height data for each row, and also skip x rows in between. The tough part will be the middle terrain that is used to connect one LOD step to the other. The values to take and skip from the height array will probably have to be hardcoded (at least per row)

to make the coding simpler each LOD sep must be a multiple of the prevois one. and in the middle terrain each row must be a multiple of the previous rows... and you will special versions of these "middle terrains" for the corner terrains.
And if you plan on having several LOD steps, than that is just going to be h3ll to program and get working, but it should be possible (painfull, but possible)
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 11:26

I think Im just going to 'average' them, by sewing the points I have,
and ignoring the points I dont.

The LODS vertices-per-side is like so...
LOD_0=256(+1), LOD_1=128(+1), LOD_2=64(+1), LOD_3=32(+1)
So EVERY lod vertices line up with the higher lod vertices...
Like so.
Code:
LOD_0 =    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
LOD_1 =    *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
LOD_2 =    *       *       *       *       *       *       *       *       *
LOD_3 =    *               *               *               *               *



Also, the 'border' between lod_0 and lod_1 is 4,000 quants MINIMUM away from the camera,
so I think its unlikely to be noticable to the player.

If it ends up that is IS noticable, I'll think of some way of hiding it.
For example, when stitching low-poly to higher-poly, the low-poly's vertices
get their z-height "halved" so ALL its edge is below the 'horizon' created by the
high-poly terrain.
Like so...
Code:
Side View...

       /            _    /--\___     ____   _____     /---
camera*        ____/ \__/       \___/      /     \___/    \_____  
       \                                  /                 
               +------ high poly -------+ +------ low poly ----+
                                          ^^ left-most vertex dragged downward




[EDIT]Hehe, you came up with a new idea, WHILE I was typing up how Im ALREADY doing it...

Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 11:35

when I started with terrains (before i learned to splice them) i saw that no matter how far away a blue(or whatever sky texture you use) line (or even a tiny dot) in the middle of terrains is very noticable.

I think your idea of the border vertex z value halved to hide the seams is the best option. even if they are not sewn together it will look like it, and will be much less painfull than using those "mid terrains" i talked about to sew them perfectly. I would go with that, because your concept is much simpler to program and probably achieves a good result also
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 11:45

I'll see when I get there, thats my usual workflow...

One question though... how do you re-calculate the normals for the terrain/entity
once youve finished setting all the vertex heights?

You posted code of how you do the 'edges', but what about the main-body of the entity?

Im not working on this ATM, but small trials in the past using ent_fixnormals just
kept resetting all the new heights back to zero. (ie before re-heighting)
Was I using ent_fixnormal badly? Did I need a wait between the re-heighting and the fixnormal?

I know its do-able, cause Ive done it in the past, and I spent very little time on this test,
as the test was primarily to test setting heights in a second 'thread', which was a fail.

I cant show code, cause its gone... Deleted in order to streamline workflow, and
avoid re-hashing dead-end tests.
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 12:25

now I am running into another problem... Painting the terrains.

Since they are randomly generated during runtime there are no masks etc textures created beforehand for any shader to work with.

and i am thinking that if i have to create the masks at runtime and then pass them to the shaders... i would rather direclty generate the final bmaps myself and save a step!

the problem is I dont know how. I already have my separate textures i want to use (and they are the same size as each terrain).

My idea is this:

create at runtime empty bmap for each terrain, assign each one as skin to each terrain, and then for each bmap do the folowwing:

1. fill its full texture to the base texture (grass for example).
2. going through the bitmap comparing to the respective height data, set any part lower than (for example 16) to sand. (for beach, river lines, and uderwater terrain).
3. set any part of the bmap covering a part of the terrain with a height > 50 to my rocky texture.
4. set any part of the bmap covering terrain height > 100 to my snowy texture.
5 go through the whole terrain again and replace any part with a slope angle > 60º with my cliff texture.

The bmaps i want to use for my terrains are 512x512, my terrains are 33x33 vertixes with a spacing of 16q between each vertex (which also gives 512x512 size). That was planned beforehand to have the size of the terrains = the size of their texture and not nned any tiling of textures or anything.

My problem is the height data... I dont have 512x512 height data, i only have 33x33 height data. How do I know what to paint on the spaces in between my height data? and how do I detect what parts have an angle > 60º?

The first solution that came to my mind was using c_trace to detect heights of each pixel and also calculate angles with those c_trace... but it seems crazy... it will mean 252144 c_trace instructions per terrain just to get the data to draw the texture.

I thought of averaging out the diference between each point based on distance from any vertex, but i realized that the calculations would be wrong in most cases. as illustrated below the program would assume from A to B everything was the same height. i also thought of calculating the mid point but that does not work either. Any ideas would be greatly apreciated, I have hit a brick wall and cannot see around it!

Posted By: MrGuest

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 12:35

have a look at vec_lerp for its height and vec_dot for its angle
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 12:39

Quote:
One question though... how do you re-calculate the normals for the terrain/entity
once youve finished setting all the vertex heights?
You posted code of how you do the 'edges', but what about the main-body of the entity?

Mabe when you fix the normals you forget the frame? Or are using the wrong frame? (use .frame to be sure you are editing normals for the frame the entity is at at this moment)

first I use my algorithm to load random height for each height-data array

for(x=0;x<32;x++)
{
for(y=0;y<32;y++)
{
diamond_square_fractals(x*32,y*32,random(200)+25);
}
}

then i load the hieght data to each terrain vertex:
for(x=0;x<32;x++)
{
for(y=0;y<32;y++)
{
load_to_terrain(Terrain[x][y],x*32,y*32);
}
}

after that is done I just set the normals with ent_fixnormals:
for(x=0;x<32;x++)
{
for(y=0;y<32;y++)
{
c_updatehull(Terrain[x][y],Terrain[x][y].frame);
ent_fixnormals(Terrain[x][y],Terrain[x][y].frame);//BODY NORMALS
}
}

(NOTE: code up to here is how i got the ugly shadows on the edges)

Then all I have to do is fix the corners and edges with my functions:
for(x=0;x<32;x++)
{
for(y=0;y<32;y++)
{
avg_normals_NE(x,y);//CORNER NORMALS
avg_normals_NW(x,y);//CORNER NORMALS
avg_normals_SE(x,y);//CORNER NORMALS
avg_normals_SW(x,y);//CORNER NORMALS
avg_normals_N(x,y);//SIDE NORMALS
avg_normals_E(x,y);//SIDE NORMALS
avg_normals_S(x,y);//SIDE NORMALS
avg_normals_W(x,y);(x,y);//SIDE NORMALS

}
}
NOTE: notice I dont have any wait calls in between my loops for function calls (and I dont have any wait() inside those functions either).

EDIT: after posting and seeing the result I have to say... WOW what a colorfull post!
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 13:03

Carlos: OK no waits or anything I get, and thanks for the code of your flow...
I think my problem boils down to the frame.

Which frame? Its an un-animated entity pretending to be a terrain.. so where
the hell does a frame number come from? Do you assign it one at some point or what?
I am really in-experienced with animations, so I always thought that ".frame"
was ONLY for animated entities... Obviously thats incorrect...

As for your current problem, I think MrGuest has got it for the heights, but I
have no idea how to get the normals using vec_dot... Im noob with normals...


I am watching with baited breath for more details from MrGuest about how to best
implement the vec_lerp because later I'll need to to similar.
My 256X256 terrains need building from 128x128 height-data...
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 13:19

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.
Quote:
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" wink
(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!)
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 14:14

Originally Posted By: MrGuest
have a look at vec_lerp for its height and vec_dot for its angle

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,?)


Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 14:38

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
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 14:51

Originally Posted By: EvilSOB
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)
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/02/11 14:56

If it aint broke, dont fix it...

If it works this way, stop playing around with it...
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/03/11 03:46

I finally achieved it! (I think)

Code:
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.
tired sleep
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/03/11 04:02

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!
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/03/11 21:40

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=CnODODp4feg

around 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.
Click to reveal..
HEIGHT FUNCTION:
Code:
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:
Code:
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:
Code:
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 wink


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?

Posted By: MrGuest

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 00:29

I've not encountered these problems through testing for bmap_remove though obviously can't say concisely due to the way you're creating / editing the bmaps

Great video btw, you should look at using interpolation to allow strength of paints rather than anything over a certain point
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 05:07

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)
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 14:55

Ok, started doing tests to see if you guys can help me out.

firstly... I will detail the method I am using to get the times (just in case this is not a good option and it screws up all my timings).

I declare this globar variable:
Code:
double STOPWATCH;


And then I do this before and after my paint function calls:
Quote:
beep();
dtimer();


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);

STOPWATCH=dtimer();
STOPWATCH/=1000000;
beep();

NOTE: I am now using 9x9 (81) Terrains, because I want an odd number for the future when I want everything centerd around a central terrain the player is on, but that will come later...


-Times with my current code: all around 25.5 secs

0> No wait calls during my my single paint functions or height calculation function, only between terrains.

1>Only have one pixel_for_bmap and one pixel_to_bmap instructions, disabled both of them:
around 25.1 secs
Code:
//pixel_source = pixel_for_bmap(Source_BM,Pixel_pos.x,Pixel_pos.y);
//pixel_to_bmap(NewSkin,Pixel_pos.x,Pixel_pos.y,pixel_dest);



2>I think I only have two pixel colour calculation instructions, disabled both of them:
around 24.7 secs
Code:
//t_color = pixel_to_vec(NULL, t_alpha ,t_format2,pixel_source);
//pixel_dest=pixel_for_vec(t_color,t_alpha,t_format1);



3>enabled all my previously disabled pixel & colour instructions. Disabled my height funcion call and substituted it with a random number:
around 5 secs
Code:
//height = get_height(Pixel_pos.x,Pixel_pos.y,i,Terr);
height=random(200);



4>pulled bmap_create out of the function to set it as a global and only create it once on startup after level_load. I also disabled "if(height>16)", since the bmap will be fully substituted each time because we don't start off from sand texture for consecutive paint calls. Enabled height calculations again:
around 26 secs
NOTE: does not work correctly, all skins are modified since the same bmap is reused for all terrains, they all end up having the same texture as the last terrain created.

5> Cannot disable bmap_lock, they have to be locked to read from (or write to), causes an E1513. No viable way to solve this unless I disable absolutely everything else.



The culprit seems to be the height calculations... only 5 secs withought that... 5 secs for painting 100 512x512 textures?!?!? That is awesome!!!! (but sadly this paint speed is only with random heights instead of my height calculations), but still the paint speed is pretty impressive for retrieving 100 textures, creating 100 textures, reading 26214400 pixels, calculating their respective 78643200 colour vector values, setting those 26214400pixels again, removing 100 ent skins, and setting 100 skins! all in 5 secs!
http://www.youtube.com/watch?v=CbNp-rD4Jog

EDIT: my get_height() function mostly does simple add, subtract, multiply and divide operations. Besides that it uses some vector operations that also are fairly simple vec_set and vec_sub. besides that I only have one vec_cross and one vec_to_angle instruction (that also do nothing extraordinary besides a few basic multiplications and additions). So I think the only instructions left in that function that could be causing the problem are the ent_getvertex calls?

I havn't used shaders yet, so I am not sure if I can. But I own A8 Commercial.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 17:00

Excellent testing technique.

But Im sorry.... my bad. I only skimmed over your get-heights,
so I didnt see the ent_getvertex's in there.
They are a well-known SERIOUS issue with speed when calling on a pix-by-pixel basis.

As you are certainly aware, when you just call ent_getvertex(?,?,xx) you get
just ONE vertex worth of data. Obviously..
But were you aware, if you call ent_getvertex(?,?,1) then ent_setvertex(?,?,1),
it gives you access to ALL the vertices, without any more ent_getvertex calls?
(At least until the next wait(), and then the buffer gets flushed away.)

I know your code, to my un-familiar eye, doesnt look friendly to the idea,
but is it PLAUSABLE to fit the following concept into a SINGLE frame...?
[because if you hit any wait(), you need to re-call ent_getvertex(?,?,1) & ent_setvertex(?,?,1)]

1> Call ent_getvertex(?,?,1) then ent_setvertex(?,?,1) to access the vertex buffer.

2> Set all your heights DIRECTLY into this buffer. Do a ent_setvertex to lock it in.
[note: even though you did a ent_setvertex(?,?,1) to save, the buffer is STILL THERE until the next wait()]

3> Paint your skin using the data from the buffer rather than individual ent_getvertex calls.

Does that sound within the realms of possibility?
And YES, I am aware thats a LOT of changes...

I am CERTAIN this will give you a serious improvement, but I GUESSTIMATE
it will actually give a HUGE improvement, based on my rough understanding
of the sheer number of times your get_height gets called, which looks large.
BUT, will it be enough? And will the improvement be worth that much re-coding?

I certainly HOPE so.... But only time and MUCH effort will tell...

Best of luck...
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 17:04

Oh... BTW....

A8 commercial gives full access to all possible shader techniques.

So it may be worth your while to post a 'help' in the shader section.
I suspect it is possible to write a shader that will do this calculation
on the GPU as a form of single-frame object shader...

Im no shader guru, so its out of my league. but if you do post there, I will
keep an eye on the thread in case a guru asks any questions too tricky for you...
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 17:59

I will try to adapt my code to do 3 at a time for each call.
But I don't know how to achieve that... Could I get a call example?

Lets say I want verts 1,2,34... how would I build the new get_vertex() call?

Currently I would do it like this:
c1= ent_getvertex(Terrain,NULL,1);
c1= ent_getvertex(Terrain,NULL,2);
c1= ent_getvertex(Terrain,NULL,34);
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 18:13

EvilSOB's idea of a single-frame object shader to handle the painting with height calculations is totally doable and would be very quick.

Alternatively, you could re-think your use of get_height -- you may want to have a height_init function or something that prepares a terrain for height calculations, and then a new get_height function that uses data from height_init:
Originally Posted By: manual
The c.v pointer points into the mesh vertex buffer, which is an array of D3DVERTEX structs with a total size given by ent_status(ent,1)*ent_status(ent,22) . Calling ent_getvertex(ent,NULL,1) followed by ent_setvertex(ent,c,1) retrieves a pointer to the start of the vertex buffer, and allows to modify the whole vertex buffer without further ent_getvertex or ent_setvertex calls. However this fast method only affects one mesh chunk of multi-mesh entities, and the row/column order of the vertices in the buffer correspond to the chunk size in that case, and not to the whole terrain size.
Direct manipulation of the data should be quite a bit faster, although it's still a lot to do for the CPU and I definitely recommend exploring the pure shader-based option.

I hope this is helpful -- I haven't read the whole thread.
EDIT -- I didn't realise EvilSOB had already covered the ent_getvertex optimisation as well.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 19:17

I would suggest trying to do more than three at a time, but if this is for a trial, then OK...

In a ROUGH conversion of your actual code, I would take your OLD code...
Code:
//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;


And turn it into THIS
Code:
//retrieve the three points of containing triangle

	//first, open the buffer
	ent_getvertex(Terrain,c1, 1);	ent_setvertex(Terrain,c1, 1);

	//retrieve the first point of containing triangle (diagonal to base)
	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_to_angle(temp_ang.pan, vec_sub( vec_set(temp_vec, P),Triangle[0].x));
	
	//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;
	}


Please bear in mind, Ive just done this in a text editor, so beware of syntax errors or typo's.

One thing that may hitch up is my referencing of the vertex array...
You may need to add parentheses like so...
Code:
this format
...  c1.v[SW].x  ...
may need changing to
...  (c1.v)[SW].x  ...


I can never remember that bit... grin ... until the compiler bitches at me...
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 19:18

Oh... and you dont NEED to finish with an ent_setvertex unless you want
to SAVE any changes you made inside the buffer...


[EDIT] BTW... This seems a popular thread for lurkers...
Check the number views this thread has had...

Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 19:22

I am interested in the shader option both of you have suggested, but have no clue where to start. I have never worked with shaders before. When I started with 3dgs I downloaded one that someone contributed on the forum, and when opening it nothing made any sense to me and I have never looked at one since then.
Would it be faster for the computer to do it with a shader?
Would it be easier to program it with a shader?

If so, any help to get started with this shader would be awesome ;D
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/04/11 19:30

I BELIEVE it would be hellishly faster, as it is being handled by
vertex and pixel dedicated hardware of the video card.

So to answer your questions ..
Faster to execute? Hell YES
Easier to program? GOD NO!

Programming shaders is a language all its own.
If you CHOOSE to get into it, it is a great advantage, but it is
LITERALLY like learning a new language. You gotta learn to speak before
you can sing lead role in an opera...

There are plenty of Opera singers who hide in the shader forums here,
so Im sure someone will help out purely for the mental exercise of it...


And dont look to me for help with shaders, it makes my brain hurt too much.
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 09:32

If it is like a completely different language and will be much harder to program I am not so sure about taking the shader route then.
I really don't want to get myself into something like that now, so the only option would be to get someone to do it for me. And even if someone did do it for me... I like to tweak my settings ALOT. Mabe next week I decide I want grass to be drawn at a higer altitude than it does today, and mabe the week after that I decide I want a fifth texture for dirt to be in a new layer between the grass and stone, etc...
So even if I got someone to do it for me, if I don't understand the shader code I would be forced to stick with what I had initially and I don't want to end up in that situation either.


The example code you provided is very interesting, I had no idea you could access all the vertexes so easily like an array. Thanks alot! That will be very usefull to speed things up!

The only thing is that the height function gets called for each pixel. so it will still mean 512x512 ent_getvertex per terrain. I am thinking of mabe making the contact pointer a global variable. setting it at the start of my terrain paint function before the loops. And making my height function work the way you showed me but with that global contact instead. that way I would reduce even more the ent_getvertex calls to only one call per terrain.

P.S: I hadn't noticed that. almost up to 1500 views now!?!? Wow! Seems like alot of people are interested in this stuff

EDIT:
-the original speed tests with my old code were around 25.5 secs
-speed tests with your version around 23.9 secs
-speed tests with global c1 pointer around 22.5 secs

-old version = 786,432 ent_getvertex calls per terrain
-your version = 262,144 ent_getvertex calls per terrain
-my newest version = 1 ent_getvertex call per terrain

I just don't get it! Why such a little speed boost? I don't understand what is going on... Somebody help me from this nightmare! Anybody! Arrggggg
[rant]I thought this would be an incredible speed boost, this is sooooo frustrating! FFS! I feel like ripping my brain out (or just crying in a corner, lol)[/rant]


Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 12:07

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?
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 12:30

NEW PAINT FUNCTION:
Code:
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:
Code:
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)
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 13:17

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...
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 13:33

Method used for new speed tests:
placing "return(random(200));" in different places of my get_height function

Quote:

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?
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 13:50

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.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 13:56

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...

Code:
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);
}


Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 14:04

I was trying to avoid shaders thinking that even if this was not the optimal route I could optimize to get it fast enough to at least be acceptable. I think I have optimized as much as I can and I have only gained a few seconds, but the result is not even close to acceptable speeds.

So I have no option but to start to learn HLSL. I hope I can understand shaders with those workshops because if I can't I will have to stick to using my current code... Thanks alot for the link!

and thanks alot EvilSOB for helping me optimize this code as much as we could (and the previous stuff we did for terrains). Even if I can't use this last part I have learned alot while doing it thanks to you, and if I don't manage to understand HLSL at least we got this working as fast as it can possibly go.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 14:22

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...
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 14:40

Just if your interested, with your latest optimization you shaved off another 4 secs, were down to 18.7 wink

Off to the shader workshops I go!
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/05/11 14:56

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?
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 12:11

First shader version:

TerrainPainter.fx
Code:
//Application fed data
const float4x4 matWorld; // World matrix
texture Sand_BM, Grass_BM, Rock_BM, Snow_BM;

// ColorMap Samplers
sampler SandSampler = sampler_state 
{ 
	Texture = <Sand_BM>;
	MipFilter = Linear; 
	AddressU  = Wrap; 
	AddressV  = Wrap; 
}; 

sampler GrassSampler = sampler_state 
{ 
	Texture = <Grass_BM>;
	MipFilter = Linear; 
	AddressU  = Wrap; 
	AddressV  = Wrap; 
};  

sampler RockSampler = sampler_state 
{ 
	Texture = <Rock_BM>;
	MipFilter = Linear; 
	AddressU  = Wrap; 
	AddressV  = Wrap; 
};  

sampler SnowSampler = sampler_state 
{ 
	Texture = <Snow_BM>;
	MipFilter = Linear; 
	AddressU  = Wrap; 
	AddressV  = Wrap; 
};  

// Vertex Shader: 
void TerrPaintVS( 
in float4 InPos: POSITION, 
in float2 InTex: TEXCOORD0, 
out float4 OutPos: POSITION, 
out float2 OutTex: TEXCOORD0) 
{ 
	// Transform the vertex from object space to world space: 
	OutPos = mul(InPos, matWorld); 
	// Pass the texture coordinate to the pixel shader: 
	OutTex = InTex; 
}

// Pixel Shader: 
float4 TerrPaintPS(
in float4 InPos: POSITION, 
in float2 InTex: TEXCOORD0): COLOR 
{
	float4 Color;
	if(InPos.y<16)	Color = tex2D(SandSampler, InTex); 
	else if(InPos.y<50)	Color = tex2D(GrassSampler, InTex); 
	else if(InPos.y<75)	Color = tex2D(RockSampler, InTex); 
	else Color = tex2D(SnowSampler, InTex);
	
	return Color; 
} 

// Technique: 
technique AmbientTechnique 
{ 
	pass P0 
	{ 
		VertexShader = compile vs_2_0 TerrPaintVS(); 
		PixelShader  = compile ps_2_0 TerrPaintPS(); 
	} 
}



Material Definition inside my game script:
Code:
MATERIAL* mtlTerrain =
{
   effect = "TerrainPainter.fx";
   flags = AUTORELOAD; // allows to edit the shader at runtime
}



How I assign the material in my game script:
Code:
int x; int y;
for(x=0;x<TERRAIN_COUNT;x++)
{
	for(y=0;y<TERRAIN_COUNT;y++)
	{
		Terrain[x][y]=ent_create("Terrain33.mdl",vector(x*512,y*512,0),NULL);
		ent_clone(Terrain[x][y]);
		Terrain[x][y].material = mtlTerrain;
		//ent_cloneskin(Terrain[x][y]);
	}
}



Does not even compile, I get this error message:
Quote:
Malfunction W1550
Can't compile effect:
TerrainPainter.fx(53,18): error X4502: invalid ps_2_0 input semantic
'POSITION'
D:\TERRAIN TEST\memory(71,18):
ID3DXEffectCompiler::CompileEffect: There was an error compiling expression
ID3DXEffectCompiler: Compilation failed
> in float4 InPos: POSITION, <

any help with this is welcome


@EvilSOB: Seems I am not an opera singer yet, but I am trying... At the moment it feels like I can't even sing in the shower, LOL!
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 13:28

Good start -- the pixel shader doesn't accept the "position" semantic. Instead, your vertex shader should also output the position to TEXCOORD1 or so, and have the pixel shader take in InPos through that semantic.
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 14:17

Thanks for pointing me in the right direction!

New version of TerrainPainter.fx:
Code:
//Application fed data
const float4x4 matWorld; // World matrix
texture Sand_BM, Grass_BM, Rock_BM, Snow_BM;

// ColorMap Samplers
sampler SandSampler = sampler_state 
{ 
	Texture = <Sand_BM>;
	MipFilter = Linear; 
	AddressU  = Wrap; 
	AddressV  = Wrap; 
}; 

sampler GrassSampler = sampler_state 
{ 
	Texture = <Grass_BM>;
	MipFilter = Linear; 
	AddressU  = Wrap; 
	AddressV  = Wrap; 
};  

sampler RockSampler = sampler_state 
{ 
	Texture = <Rock_BM>;
	MipFilter = Linear; 
	AddressU  = Wrap; 
	AddressV  = Wrap; 
};  

sampler SnowSampler = sampler_state 
{ 
	Texture = <Snow_BM>;
	MipFilter = Linear; 
	AddressU  = Wrap; 
	AddressV  = Wrap; 
};  

// Vertex Shader: 
void TerrPaintVS( 
in float4 InPos: POSITION, 
in float2 InTex: TEXCOORD0, 
out float2 OutTex: TEXCOORD0,
out float4 OutPos: TEXCOORD1) 
{ 
	// Transform the vertex from object space to world space: 
	OutPos = mul(InPos, matWorld); 
	// Pass the texture coordinate to the pixel shader: 
	OutTex = InTex; 
}

// Pixel Shader: 
float4 TerrPaintPS(
in float2 InTex: TEXCOORD0,
in float4 InPos: TEXCOORD1): COLOR 
{
	float4 Color;
	if(InPos.y<16)	Color = tex2D(SandSampler, InTex); 
	else if(InPos.y<50)	Color = tex2D(GrassSampler, InTex); 
	else if(InPos.y<75)	Color = tex2D(RockSampler, InTex); 
	else Color = tex2D(SnowSampler, InTex);
	
	return Color; 
} 

// Technique: 
technique AmbientTechnique 
{ 
	pass P0 
	{ 
		VertexShader = compile vs_2_0 TerrPaintVS(); 
		PixelShader  = compile ps_2_0 TerrPaintPS(); 
	} 
}



Now I get the following error:
Quote:
Malfunction W1550
Can't compile effect:
TerrainPainter.fx: error X4541: vertex shader must minimally write all four components of POSITION
D:\TERRAIN TEST\memory(70,18):
ID3DXEffectCompiler::CompileEffect: There was an error compiling expression
ID3DXEffectCompiler: Compilation failed

What have I gotten myself into? I'm starting to regret it already! (But I won't stop till I get it done, I'm too stubborn to give up so easily)
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 14:35

Im getting close too, I just dont know how to make sense of the
Height data Ive captured...

Click to reveal..
Code:
//Application fed data
const float4x4 matWorldViewProj;
const float4x4 matWorld;

texture Sand_BM_bmap, Grass_BM_bmap, Rock_BM_bmap, Snow_BM_bmap;

// ColorMap Samplers
sampler SandSampler  = sampler_state  { Texture = <Sand_BM_bmap>;  };
sampler GrassSampler = sampler_state  { Texture = <Grass_BM_bmap>; };
sampler RockSampler  = sampler_state  { Texture = <Rock_BM_bmap>;  };
sampler SnowSampler  = sampler_state  { Texture = <Snow_BM_bmap>;  };


// Vertex Shader: 
void TerrPaintVS( in  float4 InPos:  POSITION,	in  float2 InTex: TEXCOORD0, 
						out float4 OutPos: POSITION,	out float2 OutTex: TEXCOORD0, 
						out float  Height: TEXCOORD1 											)	 
{ 
	// Temporarily transform the vertex from object space to world space: 
	OutPos = mul(InPos, 	matWorld);
	// Capture the HEIGHT data of the vertices
	Height = 1-(OutPos.y/OutPos.w);
	// Transform the vertex from object space to projected world space: 
	OutPos = mul(InPos, 	matWorldViewProj);
	// Pass the texture coordinate to the pixel shader: 
	OutTex = InTex; 
	// Pass the calculated depth to the pixel shader: ... APPARENTLY
}

// Pixel Shader: 
float4 TerrPaintPS(	in float4 InPos: POSITION,	 in float2 InTex: TEXCOORD0,
							in float  Height:TEXCOORD1											): COLOR 
{
	float4 Color;	
			if(Height < 0.16)		Color = tex2D(SandSampler,  InTex); 
	else	if(Height < 0.50)		Color = tex2D(GrassSampler, InTex); 
	else	if(Height < 0.75)		Color = tex2D(RockSampler,  InTex); 
	else 								Color = tex2D(SnowSampler,  InTex);

	
	return Color; 
} 

// Technique: 
technique AmbientTechnique 
{ 
	pass P0 
	{ 
		VertexShader = compile vs_2_0 TerrPaintVS(); 
		PixelShader  = compile ps_2_0 TerrPaintPS(); 
	} 
}


Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 14:35

Modified again now it outputs the position twice in two different variables.
The error has dissapeared.
I Don't understand why I need to output the pos twice if I don't use one them.

Even though I don't get any error now my terrains are just invisible... Something is not working correctly:

Code:
// Vertex Shader: 
void TerrPaintVS( 
in float4 InPos: POSITION, 
in float2 InTex: TEXCOORD0, 
out float2 OutTex: TEXCOORD0,
out float4 OutPos: POSITION,
out float4 OutCoords: TEXCOORD1) 
{ 
	// Transform the vertex from object space to world space: 
	OutPos = mul(InPos, matWorld); 
	OutCoords=OutPos;
	// Pass the texture coordinate to the pixel shader: 
	OutTex = InTex; 
}

// Pixel Shader: 
float4 TerrPaintPS(
in float2 InTex: TEXCOORD0,
in float4 InCoords: TEXCOORD1): COLOR 
{
	float4 Color;
	if(InCoords.y<16)	Color = tex2D(SandSampler, InTex); 
	else if(InCoords.y<50)	Color = tex2D(GrassSampler, InTex); 
	else if(InCoords.y<75)	Color = tex2D(RockSampler, InTex); 
	else Color = tex2D(SnowSampler, InTex);
	
	return Color; 
}


My brain hurts...
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 14:51

Quote:
I Don't understand why I need to output the pos twice if I don't use one them.
You use TEXCOORD1. Your graphics card uses POSITION laugh That's all I've got for you for now -- I'm heading out the door.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 14:53

Dude ... you really nee to terminate this thread,
and go to the shaders forum...

We are SO FAR off topic, light from the big bang hasnt got here yet!


I love shaders SO MUCH!!! I think I will just go and shoot myself now...
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 15:05

To the best of my knowledge, WHICH IS PROBABLY WRONG, the
POSITION output from the VS is needed by the PS even though it is not accessable to YOU.
Thats why you need to send another copy of it via a 'spare' TEXTCOORD.

And I THINK the reason you can see anything, is cause you are translating the
model using the "matWorld" matrix. It doesnt account for camera position I believe.
So you should be translating "Out_Pos" with "matWorldViewProj" to see the model,
even if you continue using "matWorld" with "OutCoords".
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 15:12

@EvilSOB, tested your version "as is" and with yours I can at least see the terrains. They do get painted but in a wierd way:
http://www.youtube.com/watch?v=2bAfOV1rA9s
(they are in the inverse order and in very thin layers)


Edit:
took a closer look at your height var and modified a couple things.

in your vertex function:

changed this:
Code:
Height = 1-(OutPos.y/OutPos.w);



to this:
Code:
Height = OutPos.y;




in your pixel function:
changed the ifs to this:
Code:
float4 Color;	
			if(Height < 16)		Color = tex2D(SandSampler,  InTex); 
	else	if(Height < 50)		Color = tex2D(GrassSampler, InTex); 
	else	if(Height < 75)		Color = tex2D(RockSampler,  InTex); 
	else 								Color = tex2D(SnowSampler,  InTex);


Results:
http://www.youtube.com/watch?v=a6aU_ntY6iw

OMG it works!
THANKYOU very very very very very very very very very much!

New painting speed tests:
UNMESURABLY fast, super humanly, out of this world, superman gets owned by this speed, even the flash cannot paint this fast... (these are the results of the average times measured in a millionth of a second, taken with superhuman stopwatch)

EDIT2:

Yeah, sorry for the offtopic, started out talking about terrains and memory issues and this has slowly progressed to other terrain related topics, and now into a shader...
Back on topic:
Now I will start coding the moving of terrains based on my character position, reusing the old ones left behind (and for the rest of the stuff moving with the terrains, like trees etc, I will use the recycling linked-lists I posted before this turned into a shader discussion).
I will update in this thread with any problems derived specifically from moving terrains and their sub-components, and in a separate thread anything related to your shader that I am now using for my terrains.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 15:31

Yeah, it does seem a little faster then before... grin

Gimme a few minutes and I'll have another version for you.
I think I have thouht of a wat to 'blend' the different maps
at the changeover points to give a smoother transition...

Let see how we go...



[EDIT] Not as smooth as I wanted, but take a look and see what you think.

Im gunna continue and TRY to make it actually SMOOTH, cause I need
a rest from MY movement code. Im at the 'tidy and optimize' stage.
And there is one particulat chunk of code Ive TRIED to optimize like 10 times,
But it keeps going wrong and I need to backtrack the optimise.

But theres my current shader, let me know what you think.

Click to reveal..
Code:
//Application fed data
const float4x4 matWorldViewProj;


texture Sand_BM_bmap, Grass_BM_bmap, Rock_BM_bmap, Snow_BM_bmap;

// ColorMap Samplers
sampler SandSampler  = sampler_state  { Texture = <Sand_BM_bmap>;  };
sampler GrassSampler = sampler_state  { Texture = <Grass_BM_bmap>; };
sampler RockSampler  = sampler_state  { Texture = <Rock_BM_bmap>;  };
sampler SnowSampler  = sampler_state  { Texture = <Snow_BM_bmap>;  };


// Vertex Shader: 
void TerrPaintVS( in  float4 InPos:  POSITION,	in  float2 InTex: TEXCOORD0, 
						out float4 OutPos: POSITION,	out float2 OutTex: TEXCOORD0, 
						out float  Height: TEXCOORD1 											)	 
{ 
	// Transform the vertex from object space to projected world space: 
	OutPos = mul(InPos, 	matWorldViewProj);
	// Pass the texture coordinate to the pixel shader: 
	OutTex = InTex; 
	// Capture the Height of this vertex from object space... SEEMINGLY
	Height = abs(1-(InPos.y/InPos.w));
}

// Pixel Shader: 
float4 TerrPaintPS(	in float4 InPos: POSITION,	 in float2 InTex: TEXCOORD0,
							in float  Height:TEXCOORD1											): COLOR 
{
	float4 Color;

		if(Height <  16)		Color = tex2D(SandSampler,  InTex); 
	else	if(Height <  26)		Color = lerp(tex2D(SandSampler,InTex), tex2D(GrassSampler,InTex), 0.5);
	else	if(Height <  50)		Color = tex2D(GrassSampler, InTex); 
	else	if(Height <  55)		Color = lerp(tex2D(GrassSampler,InTex), tex2D(RockSampler,InTex), 0.5);
	else	if(Height <  75)		Color = tex2D(RockSampler,  InTex); 
	else	if(Height <  85)		Color = lerp(tex2D(RockSampler,InTex), tex2D(SnowSampler,InTex), 0.5);
	else 					Color = tex2D(SnowSampler,  InTex);



	return Color; 
} 

// Technique: 
technique AmbientTechnique 
{ 
	pass P0 
	{ 
		VertexShader = compile vs_2_0 TerrPaintVS(); 
		PixelShader  = compile ps_2_0 TerrPaintPS(); 
	} 
}


Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 16:19

That was going to be my next step for the shader, thanks for saving me the headache.

Originally Posted By: EvilSOB
take a look and see what you think

I think I love you!

(There is only one small problem, it now paints in both directions, upwards and downwards. I'm working on a quickfix.
http://www.youtube.com/watch?v=vDD66R_hIIg

For the fix I just changed this line from your vertex function:
Quote:
Height = abs(1-(InPos.y/InPos.w));

to this:
Quote:
Height = InPos.y;

http://www.youtube.com/watch?v=FrJyLcX49sk
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 16:28

hehe... thats what i get for testing with a model that is entirely above 0.
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/06/11 19:25

how is that smoother version going? I'm really interested in it, I am reading alot of stuff about shaders meanwhile to add some stuff to it later. Lighting and stuff like that (at least I'm good with those parts that rely heavily on vectormath)

Edit:
I played around with the code a bit to get smoothing working.

I only needed to edit the pixel function's "if" statement's calculations like this:
Quote:
if(Height < 32) Color = tex2D(SandSampler, InTex);
else if(Height < 42) Color = lerp(tex2D(SandSampler,InTex), tex2D(GrassSampler,InTex), (Height-32)/10);
else if(Height < 75) Color = tex2D(GrassSampler, InTex);
else if(Height < 85) Color = lerp(tex2D(GrassSampler,InTex), tex2D(RockSampler,InTex), (Height-75)/10);
else if(Height < 120) Color = tex2D(RockSampler, InTex);
else if(Height < 130) Color = lerp(tex2D(RockSampler,InTex), tex2D(SnowSampler,InTex), (Height-120)/10);
else Color = tex2D(SnowSampler, InTex);


Preview:
http://www.youtube.com/watch?v=gjGJeNkAO3M

Note: I used a height of 10 for the smoothing between each layer (mainly for mathematical conveniance).

Note2: In all of the "shader versions" we posted previously you have probably noticed that the original lighting and shadows have dissapeared. Entities have their default shader which does things like that. But now that we are using our own, it dosn't use that default shader and since we are not takng those things into acount, any lighting or shadows have dissapeared from our terrains... I will modify the current code to calculate shadows and lighting and repost the final version when it is done.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/07/11 06:43

I dont think I'll get any better than what youve done already,
so Ive integrated yours into mine (below).

Yeah, I knew shadows and lighting needs to be redone but ORIGINALLY I just
wanted this shader to run ONCE and calculate a new skin for the terrain.
Not to be kept running like this one is...

Im still going to keep heading in that direction, for educational purposes.

Im posting my 'current' so you can see the height 'randomiser' Ive added
to the VERTEX shader, in order to 'roughen up' the 'flat' edges.
But its is NOW hard to spot with my existing test-model with your smoothing.
So IF you take a look, disable your smoothing to actually see whats happening.

Click to reveal..
Code:
//Application fed data
const float4x4 matWorldViewProj;


texture Sand_BM_bmap, Grass_BM_bmap, Rock_BM_bmap, Snow_BM_bmap;

// ColorMap Samplers
sampler SandSampler  = sampler_state  { Texture = <Sand_BM_bmap>;  };
sampler GrassSampler = sampler_state  { Texture = <Grass_BM_bmap>; };
sampler RockSampler  = sampler_state  { Texture = <Rock_BM_bmap>;  };
sampler SnowSampler  = sampler_state  { Texture = <Snow_BM_bmap>;  };




#define cMult 0.0001002707309736288
#define aSubtract 0.2727272727272727

float random(float4 t)
{ 
	float a, b, c, d;
	a=t.x+t.z*cMult+aSubtract-floor(t.x); 
	a*=a; 	b=t.y+a; 	b-=floor(b); 
	c=t.z+b; 	c-=floor(c); 	d=c; 
	a+=c*cMult+aSubtract-floor(a); 
	a*=a; b+=a;		b-=floor(b); 
	c+=b; c-=floor(c); 
	return ((a+b+c+d)/4); 
}


// Vertex Shader: 
void TerrPaintVS( in  float4 InPos:  POSITION,	in  float2 InTex: TEXCOORD0, 
						out float4 OutPos: POSITION,	out float2 OutTex: TEXCOORD0, 
						out float  Height: TEXCOORD1 											)	 
{ 
	// Transform the vertex from object space to projected world space: 
	OutPos = mul(InPos, 	matWorldViewProj);
	// Pass the texture coordinate to the pixel shader: 
	OutTex = InTex; 
	// Capture the Height of this vertex from object space... SEEMINGLY
	Height = InPos.y;
	// OPTIONALLY add some randomness to the demarkation line
	Height += (random(InPos)*30)-10;
}


// Pixel Shader: 
float4 TerrPaintPS(	in float4 InPos: POSITION,	 in float2 InTex: TEXCOORD0,
							in float  Height:TEXCOORD1											): COLOR 
{
	float4 Color = 0;

	if(Height < 32) Color = tex2D(SandSampler, InTex); 
	else if(Height < 42) Color = lerp(tex2D(SandSampler,InTex), tex2D(GrassSampler,InTex), (Height-32)/10);
	else if(Height < 75) Color = tex2D(GrassSampler, InTex); 
	else if(Height < 85) Color = lerp(tex2D(GrassSampler,InTex), tex2D(RockSampler,InTex), (Height-75)/10);
	else if(Height < 120) Color = tex2D(RockSampler, InTex); 
	else if(Height < 130) Color = lerp(tex2D(RockSampler,InTex), tex2D(SnowSampler,InTex), (Height-120)/10);
	else Color = tex2D(SnowSampler, InTex);

	return Color; 
} 



// Technique: 
technique AmbientTechnique 
{ 
	pass P0 
	{ 
		VertexShader = compile vs_2_0 TerrPaintVS(); 
		PixelShader  = compile ps_2_0 TerrPaintPS(); 
	} 
}



Ill do some more playing once I get to work tonight...
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/07/11 12:05

tested your code and looks alot better now that the edges are going up and down instead of straight across, and when combined with my smoothing it looks great.
Using it only once is probably a better idea for framerate, but I have no idea how to make it create an actuall texture and pass it back to the game's script so it can assign it as a skin.

EDIT: and something I have been wondering about since your first post related to shaders... Why is "if" considered dirty?
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/08/11 10:31

From what Ive read over the years, from many sources,
putting an IF in a shader, ESPECIALLY a pixel shader, is 'frowned upon'.
In much the same way as a GOTO is frowned upon in any BASIC language.

Mostly, as far as I can tell, its because GPU hardware is optimised/designed primarily for
color/position calculations (VECTORs), rather than logic/arithmatic calculations like for/if.

So using an IF in a pixel-shader is 'inefficient' at a hardware level, and can therefore
cause a shader to be significantly slower because IF itself is so slow...


Thats my theory anyway. Ive never seen a 'concise' explaination of why...

And Im going to look into the 'saving' the shader result into the entities 'skin' later tonight.
I never got a chance to do ANYTHING last night...
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 11/08/11 14:12

If I recall correctly, anything below Shader Model 3.0 (and sometimes Shader Model 3.0 if it gets "optimised" that way) will calculate the results of both sides of a branch and then use the results of the comparison to choose which results to keep. So, it works, and it doesn't really make things worse, but keep in mind performance-wise that you're not skipping branches. As such, it'd probably be best to change your if/else to get the four colours once and do some interpolation from there.

For example, in the code you (Carlos) posted above, you're probably sampling each texture twice.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/08/11 14:29

Im still 'thinking' about a way to remove the if's and replace with consecutive lerps. Something LIKE this...
Code:
float4  Color = tex2D(SandSampler, InTex); 
        Color = lerp(Color, tex2D(GrassSampler,InTex), [insert evil formula here]);
        Color = lerp(Color, tex2D(RockSampler,InTex),  [insert evil formula here]);
        Color = lerp(Color, tex2D(SnowSampler, InTex), [insert evil formula here]);


But while Im thinking about that "evil formula", Im also looking to
my own future needs with this THREAD HERE . Which, if possible,
would make this optimisation (for ME) unnecessary...
Posted By: JibbSmart

Re: Dumb terrain question.. Cannot get it to move... - 11/08/11 14:43

Yeah, that's the kind of thing I was thinking. And the evil forumla would be something like... um... [saturate(SCALE_FACTOR * (Height - OFFSET))]. OFFSET would differ per lerp, and SCALE_FACTOR will require some further thought and/or trial and error, I guess.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/08/11 15:14

Same as what Im thinking. I just want to see how the other thread goes,
so HOPEFULLY I wont need to work on this evil formula...
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/12/11 20:55

For anyone who is interested (especially Carlos), Ive completed the shader.

It can be found in my shader thread HERE.

Its also got a complete description of how to use it, and
a summary of what it does and where you would want to use it.
And is also packed with a sample script to test it with...

Carlos: Its a bit more complex LOOKING then what we've
discussed here, but thats from added flexability.
It can be made MUCH simpler to look at if we put the
cut-off heights back in as hard-coded numbers.

If you wanna do that, keep it to this thread...
Same goes for any bugs you find in getting it to suit YOUR needs...
Posted By: Carlos3DGS

Re: Dumb terrain question.. Cannot get it to move... - 11/13/11 19:41

Wow tahnks alot!!!!

I'm going to go take a look at it right away and try to understand how it works. And it will be a good break from the terrain moving code I'm working on now.
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/13/11 20:21

No problems dude!

If you got any questions on this, or any other subject, just PM me.

Its time for this thread to die...
Posted By: EvilSOB

Re: Dumb terrain question.. Cannot get it to move... - 11/13/11 21:03

Oh, and to help ease your understanding of the shader,
here is another version that works the same STRUCTURALLY,
but all the configuration settings are hardcoded into the
shader source-code itself, with descriptive variable names.

Example lite-c script
Click to reveal..
Code:
#include <acknex.h>
#include <default.c>

BMAP* sand_tex  = "sand.tga";		// Sand Texture
BMAP* grass_tex = "grass.tga";	// Grass Texture
BMAP* rock_tex  = "rock.tga";		// Rock Texture
BMAP* snow_tex  = "smoke.tga";	// Snow Texture


//
//==========================================================================
//==========================================================================
//CORE CODE
//==========================================================================
MATERIAL *RePaintSkin_mat =
{	effect= "TerrainPainter_hardcoded.fx";		event = skinChangeEvent;
	flags = ENABLE_RENDER | AUTORELOAD;											}
//--------------------------------------------------------------------------
function skinChangeEvent() {	if(me!=render_view.genius)	 return(1);	}
//--------------------------------------------------------------------------
void RePaint_Skin(ENTITY* ME)
{	if(!ME)						return;		//invalid entity to capture.
	if(!ent_getskin(ME,1))	return;		//entity has no skin to capture into.
	//-----------------------------------------------------------------------
	VIEW *view = view_create(1000);		set(view, SHOW);
	view.material = RePaintSkin_mat;		view.genius = ME;
	view.x=ME.x-(ME.max_x+ME.min_x)/2;	view.y=ME.y-(ME.max_y+ME.min_y)/2;
	view.z = ME.z + maxv(ME.max_x-ME.min_x, ME.max_y-ME.min_y)*0.75;
	vec_set(view.pan,vector(0,-90,0));	view.bmap = ent_getskin(ME,1);
	view.size_x = view.bmap.width;		view.size_y = view.bmap.height;
	//-----------------------------------------------------------------------
	wait(1);										ptr_remove(view);			beep();		}
//==========================================================================
//End of CORE CODE
//==========================================================================
//==========================================================================
//



ENTITY* Terr;

void updateView()		{	RePaint_Skin(Terr);	}



function main() 
{
	wait(1);					level_load(NULL);		wait(1);				diag("\n\n\n");
	draw_textmode("Times",0,32,100);				warn_level = 3;	terrain_chunk=256;
	
	//------------------------------------------------------------------------------------
	//
	Terr = ent_create("terr.MDL", nullvector, NULL);
	vec_set(camera.x, vector(-300,150,220));	vec_set(camera.pan, vector(350,-25,0));
	//
	on_space = updateView;
	//
	while(!key_esc) 
	{
		if(key_f1)	DEBUG_BMAP(ent_getskin(Terr,1), 0, 1);

		if(key_f2)	//swap entities
		{	if(!str_cmp(Terr.type, "PLANE01.HMP"))		
			{	ent_morph(Terr, "plane01.hmp");		vec_fill(Terr.scale_x, 0.1);	}
			else
			{	ent_morph(Terr, "Terr.mdl");			vec_fill(Terr.scale_x, 1);		}
			while(key_f2)	wait(1);					}

		wait(1);
	}
}



Shader code "TerrainPainter_hardcoded.fx"
Click to reveal..
Code:
//===================================================================================
//ColorMapping Samplers Texture-Sources
texture sand_tex_bmap, grass_tex_bmap, rock_tex_bmap, snow_tex_bmap;
sampler SandSampler  = sampler_state  { Texture = <sand_tex_bmap>;  };
sampler GrassSampler = sampler_state  { Texture = <grass_tex_bmap>; };
sampler RockSampler  = sampler_state  { Texture = <rock_tex_bmap>;  };
sampler SnowSampler  = sampler_state  { Texture = <snow_tex_bmap>;  };
//
//===================================================================================
//Configuration Settings
float Lap = 20;			// Border Overlap Range 	 		(in quants)
//
float GrassStart =  37;	// Start height of GRASS texture	(in quants)
float RockStart  =  80;	// Start height of ROCK texture	(in quants)
float SnowStart  = 125;	// Start height of SNOW texture	(in quants)
//
float SandScale  = 6;	// SAND texture scale multiplier
float GrassScale = 6;	// GRASS texture scale multiplier
float RockScale  = 2;	// ROCK texture scale multiplier
float SnowScale  = 3;	// SNOW texture scale multiplier
//
//===================================================================================
//Random Number Generator
#define cMult 0.0001002707309736288
#define aSubtract 0.2727272727272727
//
float random(float4 t)
{ 
	float a, b, c, d;
	a=t.x+t.z*cMult+aSubtract-floor(t.x); 
	a*=a; 	b=t.y+a; 	b-=floor(b); 
	c=t.z+b; 	c-=floor(c); 	d=c; 
	a+=c*cMult+aSubtract-floor(a); 
	a*=a; b+=a;		b-=floor(b); 
	c+=b; c-=floor(c); 
	return ((a+b+c+d)/4); 
}
//
//===================================================================================
//
void Painter_VS(	in  float4	inPos:  POSITION,	in	 float2 inTex:  TEXCOORD0,
						out float4	outPos: POSITION,	out float  outHgt: TEXCOORD0,
						out float2 outTexD:TEXCOORD1, out float2 outTexG:TEXCOORD2,
						out float2 outTexR:TEXCOORD3, out float2 outTexS:TEXCOORD4	)
{
	outPos	= float4(inTex.x*2-1, -inTex.y*2+1, 0,1);		//output normalized XYpos
	outHgt	= inPos.y + (random(inPos)*20)-10;	//output slightly-randomized height
	outTexD	= inTex * SandScale;		//	re-scale coords for SAND/DIRT texture lookup
	outTexG	= inTex * GrassScale;	//	re-scale coords for GRASS texture lookup
	outTexR	= inTex * RockScale;		//	re-scale coords for ROCK texture lookup
	outTexS	= inTex * SnowScale;		//	re-scale coords for SNOW texture lookup
}
//
//===================================================================================
//
float4 Painter_PS(	in float  inHgt: TEXCOORD0,
							in float2 inTexD:TEXCOORD1, in float2 inTexG:TEXCOORD2,
							in float2 inTexR:TEXCOORD3, in float2 inTexS:TEXCOORD4 ):COLOR0 
{	
	float4 color = 0;
		  if(inHgt<(GrassStart-Lap))	color = tex2D(SandSampler, inTexD);
	else if(inHgt<(GrassStart+Lap))	color = lerp(tex2D(SandSampler, inTexD), tex2D(GrassSampler,inTexG),saturate((inHgt-GrassStart)/Lap));
	else if(inHgt<(RockStart-Lap))	color = tex2D(GrassSampler, inTexG);
	else if(inHgt<(RockStart+Lap))	color = lerp(tex2D(GrassSampler,inTexG), tex2D(RockSampler, inTexR),saturate((inHgt-RockStart)/Lap));
	else if(inHgt<(SnowStart-Lap))	color = tex2D(RockSampler, inTexR); 
	else if(inHgt<(SnowStart+Lap))	color = lerp(tex2D(RockSampler, inTexR), tex2D(SnowSampler, inTexS),saturate((inHgt-SnowStart)/Lap));
	else										color = tex2D(SnowSampler, inTexS);
	return color;
}
//
//===================================================================================
//
technique terrain_paint 
{
	pass p0 
	{
		CullMode = None;
		VertexShader = compile vs_2_0 Painter_VS();
		PixelShader  = compile ps_2_0 Painter_PS();
	}
}
//
//===================================================================================
//


© 2024 lite-C Forums