Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Code Snippets / DBP - VertexData manipulation

Author
Message
Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 15th Apr 2006 05:00


Simple function to show to to:
a) Create a mesh using memblocks
b) Use vertex manipulation to VERY quickly turn it into a wave generator

I get about 1900 fps for that code.

Zotoaster
19
Years of Service
User Offline
Joined: 20th Dec 2004
Location: Scotland
Posted: 15th Apr 2006 17:48
Very nice.. Could you possibly do it in a more 3D way, to make a sort of water matrix or something?

Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 15th Apr 2006 19:28 Edited at: 15th Apr 2006 19:30


Here is something I just knocked up... The normal code isn't working... :-( But apart from that, it looks pretty cool in wireframe mode

I get about 160fps with that code.

EDIT: You get a pretty cool effect if you change this line:

to


RiiDii
19
Years of Service
User Offline
Joined: 20th Jan 2005
Location: Inatincan
Posted: 15th Apr 2006 20:12
Nice work Nic!


Open MMORPG: It's your game!
Zotoaster
19
Years of Service
User Offline
Joined: 20th Dec 2004
Location: Scotland
Posted: 15th Apr 2006 20:19
Danke!

Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 16th Apr 2006 12:33
Cheers |Can anyone see why the normals aren't working?

Jess T
Retired Moderator
21
Years of Service
User Offline
Joined: 20th Sep 2003
Location: Over There... Kablam!
Posted: 17th Apr 2006 09:51
Not sure, but it looks like you're not actually calculating them correctly.

Given:


To find the normal of A, all you want to do is make a vector which extends from A to B, and another from A to C, cross Product them, then Normalize it ( so it's between 1 and -1 ), and you should have your normal.

This won't have any smoothing, so once you've calculated all the normals, then you may want to do another pass which would check it with it's 8 neighbouring normals, and becomes an average of those.

Rinse, and repeat.

Team EOD :: All-Round Nice Guy
Want Better dbHelp Files?
Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 17th Apr 2006 11:32
@Nicholas Thompson

I think you've made the normals more complicated than they need to be. Since you know the function which defines the height of each vertex, it is a simple matter to calculate the function which represents the normal. The following code illustrates what I have in mind. I have merely written a short function createNormal2 to replace yours.

The result doesn't seem quite right though - probably because I've misunderstood the relation between your vertices and the x,z and height values. I think it's moving along the right lines though. Will have another look later on - got a shader wave program of my own to debug!

Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 17th Apr 2006 12:51 Edited at: 17th Apr 2006 12:52
I suspect that another problem with your code is that you only need to fix the height (y) of each vertex as a function of its (x,z) coordinate. I think your code sets all the vertices of a single quad (i.e. two triangles) to be the same height. My suggested code for the normals assumed that the height of an individual vertex was just Heights(x, z). I see now that it isn't - hence the strange results.

I would reorganise your code as follows:

1. do a single pass through all vertices
2. for each vertex, set (xv, zv) = actual (x, z) coords of the vertex
3. set the vertex height to be "sin((timer()+xv*zv)*1.440)", i.e. use the actual (x,z) coords of the vertex instead of the values of x and z which are the quad indices in the present code
4. calculate the normals using createNormal2(t#,xv,zv).

The result might be somewhat shorter and simpler code. There certainly shouldn't be any need for averaging to calculate the normals.

Hope this helps.
Jess T
Retired Moderator
21
Years of Service
User Offline
Joined: 20th Sep 2003
Location: Over There... Kablam!
Posted: 19th Apr 2006 10:11
Hmmm...

The VertexData commands don't work the way I would expect.

It binds vertecies together... That's interesting!

I'm used to standard MemBlock Vertex manipulation ( it uses the FVF 338, which is a redundent format instead of... I can't remember the number, but it's a vert list, then a reference list for the polygons... Much neater ) whereby every single vertex has it's own data, and each vertex is generally repeated multiple times for each polygon that uses it.

That way, you set the normals of all the verts at that point based on the polygon it belongs to, then you average out those to 'smooth' the normal.

Also, if you want to get the 'flat shaded' effect, then you must have individual vertecies for each polygon, otherwise you'd get weird things a-happening

Team EOD :: All-Round Nice Guy
Want Better dbHelp Files?
Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 19th Apr 2006 10:54
Jess - the vertexes ARE seperate, that why I have the 0-5 loop. For every height I calculate there are 6 vertices at that point (2 of the squares have a corner with 1 vert and the other 2 squares have the corner with 2 verts where the triangles join in the corner, so 1 + 1 + 2 + 2). That loop takes the 6 predetermined polys for a point and sets them all to the same height. I'd personally prefer the poly's to be joins at the vert - I cant see a need to ever have them seperate!

Jess T
Retired Moderator
21
Years of Service
User Offline
Joined: 20th Sep 2003
Location: Over There... Kablam!
Posted: 19th Apr 2006 11:52
Urg... You'll have to forgive me, lack of sleep, etc, etc, and so-on and so-forth...

At any rate, my discussion is still valid to some extent, it's just off on a little tangent

Team EOD :: All-Round Nice Guy
Want Better dbHelp Files?
Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 19th Apr 2006 12:03
Quote: "For every height I calculate there are 6 vertices at that point (2 of the squares have a corner with 1 vert and the other 2 squares have the corner with 2 verts where the triangles join in the corner, so 1 + 1 + 2 + 2). That loop takes the 6 predetermined polys for a point and sets them all to the same height."


OK, I see. In that case I really don't see why either of you are doing any averaging at all! The height of all six vertices (the SAME vertex really) is just a simple mathematical function of x and z which means a bit of calculus gives you the direction of the normal at that point - hence the cosine in my code.

Anyway, I'll look at this again when I've got access to DBP.
Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 19th Apr 2006 14:02
Ok, take this as an example:
You have point x,y,z where y is a function of x and z (say sin(x*z)). Now, each point (x,z) has 4 attached points:
x+1, z
x-1, z
x, z+1
x, z-1

The normals for x,z is a function based on those 4 attached verticies as those 4 determine what "angle" our current vertice is facing.

The 6 vertices I mentioned are the 6 overlapping verts at each coord. so there are 6 at x,z, another 6 and x+1,z and so on. I need to set the height and normal of all 6 for each function of x,z (height).

Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 19th Apr 2006 17:00
Wrong. Just draw a one dimensional sine wave, i.e. sin(x) vs x, to see the error. Your vertices correspond to points on the curve at regular intervals of x. The direction of the normal, i.e. the perpendicular to the curve, at a vertex depends purely on the height AND whether the curve is rising or falling at that point. Absolutely nothing to do with what other vertices are doing - unless you want to accept an unnecessarily crude approximation. The sign of the cosine just tells you which way the normal is facing, whereas its magnitude tells you the angle (loosely speaking).

I know perfectly well what the 6 vertices relate to - the vertices of the six triangles which meet at a given point. You certainly do NOT need to do six different calculations - they all relate to the same vertex in 3D space.
Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 19th Apr 2006 19:13
My original code forgot to include the factor 1.44 and the (x,z) scale factors. The normals now line up with the waves correctly.

Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 20th Apr 2006 11:49
@GG: Cheers for that, I'll take a look later. I know that you dont need 6 calculations, you can do it once and apply the same to all six (I think thats what my loop is doing).

I agree that the normal is dependant on whether the vertex is rising or falling, but equally, the rise and fall of the vertex is easily determined by the surrounding vertices, eg:


Say I want to know the normal of the middle dot - then (the way I'd do it) is look at the dot to the left and to the right and I can then assume that the middle dot's normal is to the right and up a bit. All I had to do was pull two height values up from a list I'd already calculated once. I didn't need to run the height function again.

I dont think the vertex has anything to do with its height, at least not in an absolute sense - it does in a relative sense.

Lost in Thought
20
Years of Service
User Offline
Joined: 4th Feb 2004
Location: U.S.A. : Douglas, Georgia
Posted: 20th Apr 2006 13:02 Edited at: 20th Apr 2006 13:12
What I want to know is how your vectors are working in that function. I get invalid index errors when trying that. Vectors and matrix4 seems totally local here and only work outside functions. 0_o

[edit] OMG even my old code that crashed works now 0_o In any case I'll look at the normals now

Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 20th Apr 2006 16:22
Quote: "Say I want to know the normal of the middle dot - then (the way I'd do it) is look at the dot to the left and to the right and I can then assume that the middle dot's normal is to the right and up a bit. All I had to do was pull two height values up from a list I'd already calculated once. I didn't need to run the height function again."


Yes, that's a fair point - it all depends on how fast the cosine function is compared to averaging about six neighbouring points. On my machine your version achieves approx 36 or 37 fps, whereas my version achieves 40 or 41 suggesting the cosine method is slightly faster (as it ought to be). (It's the cosine not the height function that's needed for the normal.)

The main problem, however, with your method is that it only gives an approximation to the true normal and can be poor if the steps between adjacent points are comparable to the wavelength you've chosen. If you want sensible results regardless of the wavelength of your sine wave then you need the cosine method. The cosine method I used involves a calculus calculation of the slope of the surface in the x and z directions and something called the Jacobian - I guess the same result would be obtained by calculating the vector product of the "tangent vectors" in the x and z directions. Either way, if you do it exactly via calculus, rather than approximately using a coarse grid of x, z values, you will end up with the cosine formula for the normals which I used (barring silly algebraic errors of course!).

[quote]I dont think the vertex has anything to do with its height, at least not in an absolute sense - it does in a relative sense./quote]

I think you meant "normal", not "vertex". The normal IS defined by the height function when it's a simple sine function. Just look at your original sine wave in your first post - as you approach the crest (or trough) of each wave the normal gradually approaches the vertical in a consistent predictable manner. The sign of the angle from the vertical depends on which side of the peak or trough you are on (and the cosine function tells you that among other things - try it).
Lost in Thought
20
Years of Service
User Offline
Joined: 4th Feb 2004
Location: U.S.A. : Douglas, Georgia
Posted: 20th Apr 2006 20:37
I would have to re-write this for all my normal codes to work. They all work on poly normals (all 6 normals will be different at each point).

Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 20th Apr 2006 23:55
Quote: "I would have to re-write this for all my normal codes to work. They all work on poly normals (all 6 normals will be different at each point)."


I'm not sure I follow. Which 6 normals? If you have 6 polys (i.e. triangles) on a surface meeting at a common point and you want the normal to the true surface (i.e. not the approximate surface corresponding to the triangles) then you need only one normal (copied 6 times, one for each poly). Perhaps you mean an alternative which is to have a common normal for each of the three vertices on any given poly - in that case you would, in general, have 6 different normals at a common vertex, i.e. one for each of the 6 polys. I cannot say which gives the better effect visually. If I find time, I'll write some code to compare them, but my preference is to go for the mathematically "exact" answer when it is easily calculated as in Nick's example.

As a side issue, I've written a vertex shader which gives a similar effect - and it runs at a much higher fps on my machine. Anyone interested?
Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 21st Apr 2006 11:22
Definately!! Not entirely sure what you mean by a vertex shader in this context...

Thanks for all your feedback on the GG and LiT.

@GG: I see your points. I'm not sure which should be quicker... Generally speaking, sin/cos functions are often (at a low level) "hi-res" array's containing accurate results of the function at regular intervals. When you provide the "interval" you want, the result is actually and interpolated value between two known values. The drawback is that its not 100% accurate, its more of an estimate but its often more than accurate enough for our needs. The advantage is that the function is MUCH quicker when it only has to do two array lookups and a little bit of very simple maths to get an "in between" value. A function which does recursive division quickly becomes slow, especially seeing as it has to do a good few itterations before it becomes accurate enough for our needs.

So I'm not sure - the vector functions in DBP are pretty quick in my experience... Hmmm...

I understand what you're saying - its much better to represent the heights mathematically rather than on a coarse grid...

Quote: "as you approach the crest (or trough) of each wave the normal gradually approaches the vertical in a consistent predictable manner"

I agree - that is a noticable pattern, however if you refer to my model I explained earlier where the normals (you are correct, I meant normal not vertex) are dependant not on the absolute height of the point, but on the relative height then this pattern also makes sense. The reason the peaks and troughs have vertical normals is because, relativly, the surrounding points are almost all exactly the same height. As they are all the same, this makes the normal perpendicular to a "horizontal plane". As you go down one side of a peak, the points on one side are higher and the points on the other are lower. This results in a "slanted plane" and therefore the perpendicular normal points diagonally.
This is the way my vector method works. It takes the surrounding heights and adds them all together. The result should be the difference in average height. You then apply a simple vector function to it which finds the perpendicular vector (tangent).

Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 21st Apr 2006 12:49
Quote: "This is the way my vector method works. It takes the surrounding heights and adds them all together. The result should be the difference in average height. You then apply a simple vector function to it which finds the perpendicular vector (tangent)."


Yes, but I think you've made it more complicated than it needs to be - you should only need one vector product command. I'll see what I can do later on.

In the meantime, I've attached the current version of my shader effect with sample program and media. I'm still trying to understand how shaders work so there are almost certainly bits that could be improved, especially the lighting. There are several adjustable parameters in the FX code - you can either change their default values in the FX file or do it in the DBP program using set effect constant commands. A simple one to play with is the "cent" vector in the FX file - the values should be in the range -0.5 to 0.5 (zero corresponds to the centre of the "water"). I get an fps of about 200 using the shader.

Quote: "Not entirely sure what you mean by a vertex shader in this context..."


Hopefully you'll find out! The vertex "shader" is actually moving the vertices and re-calculating the normals using the method I described for your project (with a couple of "fudge factors" thrown in).

Let me know if you have problems - it depends on your GFX card. I'm particularly interested in how the fps compares with your example on your machine. I recently upgraded my GFX card and am learning how to play with it.

Attachments

Login to view attachments
Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 21st Apr 2006 13:56
I doubt I can use it here at work - I have an onboard intel "accelerator" which can only manage 30fps in DBP no mater what I do! (I had a 32x32 sphere mapped with a 10Mb DDS + a 8Mb Normal Map DDS and I got 30fps... I then made a spinning cube and got - thats right - 30fps!!

I'll try it on my home machine which is a smidge better.. (AMD X2 4400+, 7800GTX 256Mb (PCIe), 1Gb DDR 400)

Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 21st Apr 2006 17:12
@Nicholas Thompson

Just had another look at your code and an obvious problem (obvious now I've spotted it!) is that you havn't normalised the vector containing the normal - I think it should be normalised to have length 1. You need a division at the end of your createNormal function as follows:



with that change you can see the waves.

I still think the code could be simplified - will look at that now.
Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 21st Apr 2006 17:25
Done it - you just need two lines as follows:



The set vector3 line replaces your earlier code. Looks OK - but you might be able to improve it's appearance by adjusting the constants in the expression



Hope you approve.

[Aside: the nx, nz values are effectively your discrete approx to my earlier "exact" cosine formula.]
Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 21st Apr 2006 17:41
there is a NORMALIZE VECTOR command I think... I'll take a look at that!!! Cheers GG

Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 21st Apr 2006 17:52
Just tried it on my work machine - it looks like it works... Although I'm not sure why!!

Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 21st Apr 2006 19:14
Quote: "there is a NORMALIZE VECTOR command I think"


You're right - I didn't notice that. If it works it should be faster than my divide vector etc (should be doing same thing - but directly in machine code, therefore faster). Will try it out.
Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 10th May 2006 01:48
Ah ha!! Fixed code - tweaked your normal calculator a little. Works a treat!! MUCH quicker... Also took your advice on the heights - converted it from array to mathematical function. Might not be quicker, but its boundless so I can get the edges to wave too now...



Xander
21
Years of Service
User Offline
Joined: 3rd Mar 2003
Location: In college...yeah!
Posted: 10th May 2006 23:02
I've got a quick question:

When changing the positions of the vertices using the vertex manipulation commands, they are relative to the object's position, right? So if you position a vertex at 0,0,0, then move the object to 0,100,100, then the actual vertex position will be at 0,100,100, but if you get its position using the commands it will still be 0,0,0, right?

Xander Moser - Bolt Software - Firewall
Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 11th May 2006 00:38
correct. To get a verts absolute position, its the verts x,y,z coord + the objects x,y,z coord.

Xander
21
Years of Service
User Offline
Joined: 3rd Mar 2003
Location: In college...yeah!
Posted: 11th May 2006 14:50
Alright, thank you.

Vertex manipulation was a little intimidating, but it doesn't look too bad. I really like the ability to take a mesh and put its data into the locked vertices' data so I don't have to store the data for the original positions of the vertices

Xander Moser - Bolt Software - Firewall
Phaelax
DBPro Master
21
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 12th May 2006 10:24


I thought it was ordered like this:



Nicholas Thompson
20
Years of Service
User Offline
Joined: 6th Sep 2004
Location: Bognor Regis, UK
Posted: 12th May 2006 13:26
I dont think it mattes - as long as it is clockwise...

Login to post a reply

Server time is: 2024-11-23 07:39:05
Your offset time is: 2024-11-23 07:39:05