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.

DarkBASIC Professional Discussion / Welding Vertex Data?

Author
Message
Alquerian
19
Years of Service
User Offline
Joined: 29th Mar 2006
Location: Reno Nevada
Posted: 20th Apr 2007 02:59 Edited at: 20th Apr 2007 03:17
This *appears* to look right. I do not know exactly what should be used but 2*pi() produces somewhat believable results (on spheres anyways)







Edit: I am not sure why but in order to load dbo's and cylinders I have to change this:


to this:



It doesn't seem to make sense to me currently, I will play with it and see if I can figure it out. Also, I wonder why cylinders have 0 indecies?

Visit the Wip!
Green Gandalf
VIP Member
20
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 20th Apr 2007 13:33
Quote: "umm... dunno ask Ian "


Didn't realise you'd used IanM's code, sorry.

Quote: "This *appears* to look right. I do not know exactly what should be used but 2*pi() produces somewhat believable results (on spheres anyways)"


I don't think you need the 2pi. What IS needed is that the normals should be, guess what, NORMALISED. This should be done just before the new normals are assigned to vertices. The code you are using doesn't seem to do this (unless set vertexdata normals does this for you which I doubt ).

What I think is needed is something like:



I haven't tested this though...
TinTin
19
Years of Service
User Offline
Joined: 16th May 2006
Location: BORG Drone Ship - Being Assimilated near Roda Beta (28)
Posted: 20th Apr 2007 15:04 Edited at: 20th Apr 2007 15:16
If you guys get this working I can see a whole new batch of functions that can generate optomised objects.
i.e. a cube that has sixteen polys using eight verts instead of fortyeight.
A gain of that magnitude over a complete world hints that what was once 2 FPS would be running well in excess of 100 FPS or just for the hell of it more detailed objects...

It was pointed out by GG on my earlier post that you'd just have a load of verts with the same coordinates...
as far as I can figure an object format goes something like this ...

All polys have 3 verts each verts have three coordinates, once you've checked that the verts are within a weldable range, you just change the polys pointer to that vert then delete the old vert.

say poly_1_vert_1 pointed to vert_10 and vert_5 = vert_10 then we change the pointer so that poly_1_vert_1 now points to vert_5 and we can delete vert_10 from the list.
Although I'm not sure how the u/v and normals would be handled.
I've often wondered why the normals were attached to the verts instead of the poly, I guess it helps with smoothing.

for 1 poly you have 3 verts each vert has 3 coords + 3 normals + 2 u/v etc. poly(say 3 dwords)*vert(say 8 dwords)=24
Where 1 poly could have 3 verts + 1 normal + 1 u/v and the verts would just hold 3 coords. poly(say 3 dword)*vert(3 dword)+norm(3 dword)+u/v(2 dword)=14
on 1 poly there isn't that much of a gain on more complex objects the gain is exponential.

Cyberspace was becoming overcrowded and slummy so I decided to move. These nice chaps gave me a lift.
IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 20th Apr 2007 15:37
The pluses in the normals recalculation should be divides - if the normals are normalised before the welding takes place, then the result will be automatically normalised after the recalculation. But instead of trying to reuse the existing normals, it might be better to completely recalculate the normals from the faces instead - I'll add that to the TODO list for tonight to try it out.

@TinTin,
You can only share a vertex if all the information you need to use is identical between the two vertices - my example comparison function was only interested in position, but you'd need to add texture coordinates at a minimum to make it useful for general use.

All vertices that are no longer used are removed at the end of the function. That's why I went to the effort of sorting the vertices by their usage count and stop updating the vertexdata from the array when a vertex with a zero usage count is hit.

Oh, and a cube has 24 vertices, 36 indices, and 12 poly's before welding, and 8/36/12 after welding

tiresius
22
Years of Service
User Offline
Joined: 13th Nov 2002
Location: MA USA
Posted: 20th Apr 2007 15:47
This is great, I was hoping for something like this with my level generation code, that stitches many primitives into a big single level. I'll keep an eye on this one!

I'm not a real programmer but I play one with DBPro!
TinTin
19
Years of Service
User Offline
Joined: 16th May 2006
Location: BORG Drone Ship - Being Assimilated near Roda Beta (28)
Posted: 20th Apr 2007 15:51
@ IanM I agree, my post was just a generalization that skipped over the fine detail just to put the idea across.
It looks like were all working on the same wavelength, some day we might come up with something awsome (or should I just stick to usefull) hehe...

Cyberspace was becoming overcrowded and slummy so I decided to move. These nice chaps gave me a lift.
Alquerian
19
Years of Service
User Offline
Joined: 29th Mar 2006
Location: Reno Nevada
Posted: 20th Apr 2007 18:31 Edited at: 20th Apr 2007 18:32
Does anyone know why a cylinder and loaded DBOs require you to use this:



instead of this?



I don't really understand it, all of the other objects work with the latter.

Visit the Wip!
IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 20th Apr 2007 20:05
The cylinder appears to be made up of an index-less strip rather than an indexed list. Use the few extra lines I suggested last night and that'll solve the problem

These ones...


I don't have any DBO objects, so I can't test, but they may be fixed by the same method - you'll need to test.

Alquerian
19
Years of Service
User Offline
Joined: 29th Mar 2006
Location: Reno Nevada
Posted: 20th Apr 2007 20:57
IanM - Right I tried that when you posted it the first time, and it works but only if you dim Vertex() with the vertex count, not the vertex count -1 like all the other objects do. Give it a shot, let me know if you run into the same problem.

Visit the Wip!
IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 20th Apr 2007 21:57
Yes, I see it when the object is rotated sometimes - either a missing poly, or an extra one zooming out to infinity.

In the examples coded by Lee, all vertices are indexed from 0 to the vertex count - 1. It seems that under some circumstances, they can range from 0 to vertex count instead.

The problem we have now is that we can either ignore the extra vertex like we're doing now, corrupting the model, or we can include the extra vertex, potentially corrupting memory when the extra isn't needed.

I'll keep on looking for now.

Green Gandalf
VIP Member
20
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 21st Apr 2007 00:26
Quote: "In the examples coded by Lee, all vertices are indexed from 0 to the vertex count - 1. It seems that under some circumstances, they can range from 0 to vertex count instead."


This is definitely something to watch. Can you reduce it to a very simple example, with minimal number of polys?
IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 21st Apr 2007 00:54
There's no need ...

I've made some changes - both large and small - to the code.

It now also:
- Doesn't crash if no vertices are removed
- Welds a cylinder properly without losing data
- Welds a memblock produced mesh
- Recalculates all normals from scratch

First, there was an off-by-one error in my code for the index data. That's why the lost data on cylinders (and hopefully for DBO's too).

Next, I've done some highly dodgy object manipulation by calling internal routines from the Basic3D DLL, and using Peek/Poke functions - I've deliberately stayed away from using my plug-ins for this so hopefully I haven't introduced any dependencies.

This allowed me to locate the mesh data in memory so that I can call routines a) to convert the mesh to tri-list format if it isn't already, b) to generate index data (in a highly dodgy way IMO) if there isn't any already there, and c) to recalculate normals - you'll see that I've cut out all code that dealt with normals as there's no need for it any more.

To be honest, this probably takes it out of the range of most people to modify, but it should still be relatively easy to use if all they want to do is weld vertices.



About the only thing that doesn't seem quite right is the normals recalculation - run it and you'll see a seam on the cylinder - this happens on most objects. It might end up being better if I did it myself.

Alquerian
19
Years of Service
User Offline
Joined: 29th Mar 2006
Location: Reno Nevada
Posted: 21st Apr 2007 01:06 Edited at: 21st Apr 2007 01:07
Ian - I see what you mean about the seam in the cylinder, odd.

Is there a list of all of the resources/functions that DBProBasic3DDebug.dll contains somehwere (without me using one of those dll resource hackers)?

Visit the Wip!
Green Gandalf
VIP Member
20
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 21st Apr 2007 02:37
Quote: "About the only thing that doesn't seem quite right is the normals recalculation - run it and you'll see a seam on the cylinder "


For some inexplicable reason I am not surprised.

Do you happen to know how that function calculates normals, both generally and along the "seam"?

And, if vertices are welded, what do you mean by a "seam" anyway (apart from the one that is obviously visible when it shouldn't be)? Or is it a UV issue?
david w
19
Years of Service
User Offline
Joined: 18th Dec 2005
Location: U.S.A. Michigan
Posted: 21st Apr 2007 04:36
Sweet job on this. I have already put this to use on the terrain system that I am developing under Ultimate Terrain/Landscapes thread. I really have to say, Welding these vertices has really given me some great Ideas for things I can do other than just manipulate a terrain.

Thank you for your effort and this great code.
Johaness
18
Years of Service
User Offline
Joined: 20th Sep 2006
Location:
Posted: 21st Apr 2007 10:07 Edited at: 21st Apr 2007 10:08
Quote: "To be honest, this probably takes it out of the range of most people to modify, but it should still be relatively easy to use if all they want to do is weld vertices."

Yeah. So true.
Question: To use a loaded X file - I need to convert it into a mesh and back into an object for it to work, is that correct?


Quote: "
And, if vertices are welded, what do you mean by a "seam" anyway (apart from the one that is obviously visible when it shouldn't be)? Or is it a UV issue?"


I exported a cylinder from max and it welds with no seam. If textured, the dbp cylinder looks right but the x file has the texture crimped at the end. The same happens with a sphere I exported. Untextured, the normals look correct. When textured,you can see the UV's are not. Just wondering if its the function, or do I need to setup the mesh differently? ie.memblock,FVF,etc?

Attached media I used.
IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 21st Apr 2007 11:18 Edited at: 21st Apr 2007 20:13
Quote: "I need to convert it into a mesh and back into an object for it to work, is that correct?"


No - it welds the meshes in place. You just need to specify the object & the limb that you need to carry out the welding on.

Quote: "If textured, the dbp cylinder looks right but the x file has the texture crimped at the end."


That's because of the comparison function. The existing code takes no account of texture coordinates, because for this testing I was just interested in the positions of the vertices.

Replace the CheckMatchingVertex function in the above code with the following to include texture coordinates:


If you test it with a textured object, it now works fine:


Obviously, it won't remove quite so many vertices, but it's now correct for textures too.

... I probably should have switch to this function earlier though to avoid all confusion

@Green Gandalf,
The seam I'm talking about is visual only. It's where normals from the beginning of the vertex array match those at the end of the vertex array - it looks like there's no 'wrap-around' of the normals calculation.

I don't know how the built-in routine calculates normals, but it's almost right. Writing my own for this is an exercise I'll take up later - it's close enough for now

Johaness
18
Years of Service
User Offline
Joined: 20th Sep 2006
Location:
Posted: 21st Apr 2007 19:04
Ack! My bad. I was running it on the wrong limb of my object. Works great except for the uv's.

Is that a little type in the new CheckMatchingVertex function? The last line Vertex.z <> should be Vertex.v <>?

My test object's vertex index = 468 and vertex count = 128 verts. If all shared verts are welded it should be 80 verts. Using this I get a vertex count of 117. Texture gets mapped on correct, with a seam where it wraps.

But its great as it is already. Thanks Ian.
IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 21st Apr 2007 20:15
Yep - typo. Post has been edited.

If you aren't getting the results that you are expecting, then one thing to look at is the comparison function again. The code is looking for exact matches - you might change it to do near matches on the vertex position, for example:


Johaness
18
Years of Service
User Offline
Joined: 20th Sep 2006
Location:
Posted: 22nd Apr 2007 10:13
Well I thought I was getting unexpected results.My bad, I didn't take into account the extra vertices for uv's.

A box is supposed to give me 8 verts but I was getting 20. Each quad on the box was invidually planar mapped thus breaking the uv's. When I used just a single planar uv on all the quads I get the expected 8 verts.

Thanks again.
Green Gandalf
VIP Member
20
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 3rd May 2007 18:59
@IanM

I've just been trying to sort out someone's problem with their terrain and one of my shaders and (eventually ) realised that the simple solution was your vertex welding code.

I've just tried it and it worked perfectly first time (once I'd got my bugs out of the rest of the code ). One comment though. Your WeldLimbVertices routine seems to work just as well if you replace the final line:



with:



which means one of your functions is unnecessary.

Is your solution purely to cover the situation where you might want to set the normals for some limbs and not others? If you don't want to do this then presumably set object normals is sufficient - or are there other situations where this doesn't work?

Nice code though and I'll definitely be using it, or variations of it, for my objects - although I'd prefer a pure DBP solution.
IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 3rd May 2007 21:39
Yep - that's why I used the DLL call. If you weld vertices for a single limb, it seemed a bit strange to recalculate the normals for the whole object. Calling the DLL routine directly was the quickest fix I could think of as I didn't want to spend the time to write my own normals calculation routine. It also avoided unnecessary recalculation of normals that may be perfectly OK on your other limbs.

Green Gandalf
VIP Member
20
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 4th May 2007 02:03
Quote: "Calling the DLL routine directly was the quickest fix I could think of as I didn't want to spend the time to write my own normals calculation routine. "


I can appreciate that, having calculated them myself several times in the past.

But I have noticed a visual "blemish" using the normal averaging idea. At certain parts of the object a slight "kink" appears - using either your generate normals thing or the DBP command. I suspect this happens because at many vertices certain directions are more represented in the averaging than others. To see what I mean, just draw on paper the polygons corresponding to a 2x2 array of plains stuck side by side - and ask yourself how the average will be made up at the centre point. You should see that only one diagonal occurs at the middle. This obviously distorts the normal averaging. This can be overcome by alternating the directions of the diagonal split of the quads - and will probably cure the visual kink as well (but haven't tried yet). I guess this is why some modelling software gives you a choice of how quads are split into polys. Of course, calculating them yourself, using the appropriate mathematical formula rather than relying on averaging, will cure this particular problem. But, of course, there is a downside (or two).

Quote: "It also avoided unnecessary recalculation of normals that may be perfectly OK on your other limbs."


Agreed. And you may have deliberately set them to be something other than the default averaging.
Visigoth
20
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 11th May 2007 10:43 Edited at: 11th May 2007 10:52
I may have accidentally stumbled onto another way to do this. I too was looking for a way to weld verts for my draw curved roads function. It seems there is an undocumented command called perform csg union (object1,object2). On a lark, I passed in the same object as both parameters. The original object was 72 vertices; after the perform csg union, it was 48. I'm still testing this out, but thought I'd throw it out there for you smarter fellows.

edit:
Ok, it cuts out SOME, but there are still some duplicate vertices, so its not going to work.
Alquerian
19
Years of Service
User Offline
Joined: 29th Mar 2006
Location: Reno Nevada
Posted: 11th May 2007 18:32
One thing about the undocumented CSG commands is that they will not work with tristrip objects, which I believe is the output of welding the vertexdata.

I have been able to obtain some very remarkable results by converting a large number of objects into a single object with multiple limbs then welding the vertexdata. In my particular 'test scenario' I have seen a framecount increase of 83 FPS to 171 FPS. Definately worth while

Visit the Wip!

Login to post a reply

Server time is: 2025-08-08 20:58:41
Your offset time is: 2025-08-08 20:58:41