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, another method

Author
Message
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 22nd Jun 2007 07:24
I know there is a thread already open about welding vertices, but, this is different enough, and I think cool enough, it deserves its own thread. So, here it is, a function to weld vertices on static objects. And what I mean by static is objects that have no animations. I haven't tested that yet, so can't say if it will work. The function has just one parameter, the object ID of the object you want welded.
To try it out, just add it to your program, and pass an object into it. It will recreate the object with the same ID. You have to put the type at the top of your code, and there is one global variable, as well, the creation of the type.

Now, I have to admit I could have never wrote this without seeing IanM's code, so I thank him right now for getting me to think about this. Now, the key differences between my method and his.

1. You only need 1 type array
2. Uses DBPros built in command, SET OBJECT NORMALS for calculating normals values, if you wish.
3. All manipulation of the vertexdata is done within the array, so only two write backs to the vertexdata.
4. Writes a "before" and "after" .x file of the mesh, so you can see the actual effect of the weld operation.

Things left to do:
actually, just UV mapping, but that should actually be a function by itself, because you need to know the order the polys are drawn to map properly.

I did this so I can create my own matrixs, because the built in DBPro matrix and terrain commands are not doing what I want them to do. After doing this, I discovered that those few vertexdata commands we have access to are REALLY REALLY powerful. I now have a complete, firm grasp of every command relating to vertexdata, so if you have any questions, fire away!
tiresius
21
Years of Service
User Offline
Joined: 13th Nov 2002
Location: MA USA
Posted: 22nd Jun 2007 07:30
What's the benefit of welding vertices? Does it make the object a lot smaller in memory? Quicker to render? Thanks.

I'm not a real programmer but I play one with DBPro!
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 22nd Jun 2007 07:37 Edited at: 22nd Jun 2007 07:38
ah, the BIG question. Welding vertices allows faces, or polys that share the same point in 3d space to be manipulated by moving just the one point. The way a DBPro cube is drawn, it has 12 polys, two triangles per side. Since there are six sides to a cube, thats 12 polys. Now, it also creates the cube with 36 veritices, three per triangle, 6 per face, 6x6 is 36. You only need 8. All the rest are duplicates. Now, since each triangle has its own set of vertices, if you want to move the corner of the cube, without welding you'd have to move 6 vertices individually, because 6 triangles actually touch that one corner. So, by eliminating the duplicates, and you really aren't eliminating anything, you are just telling the vertexdata to look at only the unique ones, you can move all 6 triangle points by moving just one vertice. This will allow for EASY creation of your own matrixs. And, since they are just objects, you can put them anywhere you want.
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 22nd Jun 2007 08:11 Edited at: 22nd Jun 2007 08:16
I'm going to give you an example, here of what I am talking about. this is also giving up a big secret I've been playing with for a while. I think its ready now.

There is a line of code in there that is commented out. It is xrotate object 1,90
take the coment line out after you run it, you are going to get a kick out of the result.
Yup, a modifiable mesh that you can put anyway you want. What can I do with it?
Well, some ideas, use for ceilings in caves, simulate stalagtites(sp?). Really bumpy walls. Wanna be able to WALK on walls?
Break into a grayscale .bmp. sized to the same size as the grid. Read the color value, and set it to the y value in the grid. Yup. A heightmap for a matrix. There is one flaw with this, and it's the same flaw with all the matrixs, and thats how the triangles are drawn. For a real matrix, the triangles should alternate, so if you pull up on the middle vertex of a four square, it looks like a pyramid. I am working on fixing that.
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 22nd Jun 2007 10:46 Edited at: 22nd Jun 2007 10:47
well, after some more testing, it seems I jumped the gun here. It works, but when you get BIG meshes, over 15,000 polys, things really bog down. But the good news is, there is no reason this could not be converted to memblocks. So, back to the drawing board.
Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 22nd Jun 2007 12:56
Quote: "well, after some more testing, it seems I jumped the gun here. It works, but when you get BIG meshes, over 15,000 polys, things really bog down"


The same thing happens to IanM's code so don't be put off by that. Have you compared the two methods for speed?

I haven't looked at your code but the problem with IanM's code is probably the way vertices are searched for matches - when you are constructing your own meshes, as in simple terrain examples, that step is not really necessary because you should know which vertices are repeated in your mesh (since you created them yourself).

Having said that, I'm still using IanM's code and am just putting up with the 10 minute wait while it searches for matching vertices. But one day I'll write my own code to use the vertex matching information that I already have ...
IanM
Retired Moderator
21
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 22nd Jun 2007 15:33
@Visigoth,
Well done
with texture coordinates, my code just assumes that they are present and correct. If they are, this avoids welding vertices that need to have different texture coordinates - if you are building a big terrain object though, there's no need to worry to much about it as you can add them afterwards based upon the vertex positions.

The speed is something that I don't think is easy to get around - every time you add another vertex you add another N-1 comparisons. TBH, I didn't realise that it was being used for such large objects, and you would normally optimise your objects once and save them anyway.

There are two ways to fix this:
- Convert to a faster language, such as using a C++ plug-in. You may now be able to do your comparisons twice as fast, but you'll soon hit the same performance bottleneck although admittedly at a higher number of vertices.

Using example numbers with completely made-up timings - say that you can run an object of 5 vertices through the DBPro code in 1 second. Converting the code to a DLL means that you can now run it in half a second - now you can process more vertices in that 1 second, right? Well, disappointing as it may sound, you get to add another 2 vertices before you lose that gain.


Adding 2 extra vertices takes you from 10 comparisons up to 21 comparisons.

There's really no way to win by doing the same thing you are now, but faster. Which leads to ...

- Change the algorithm. There are one or two alternatives that could reduce the number of comparisons that I'll need to look in to. Effectively, what we have at the moment has the same complexity as a bubblesort - we need the equivalent complexity of quicksort.

Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 22nd Jun 2007 19:02
Quote: "There are two ways to fix this"


For general "unseen" objects I agree - but not for simple terrain objects which you might be building yourself. We probably need two versions of your code: (1) your original one for general objects(perhaps with modifications such as the one I'm using now and those you are suggesting); (2) a version which is supplied with the vertex matching list "ready-made" as data.

Quote: "Change the algorithm. There are one or two alternatives that could reduce the number of comparisons that I'll need to look in to. Effectively, what we have at the moment has the same complexity as a bubblesort - we need the equivalent complexity of quicksort."


Agreed.

I think the order of that is nlog(n) rather than nxn which will make a BIG difference with 1000s of vertices.

That would be a very useful amendment to your original code.
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 22nd Jun 2007 22:40
Quote: "
Having said that, I'm still using IanM's code and am just putting up with the 10 minute wait while it searches for matching vertices. But one day I'll write my own code to use the vertex matching information that I already have ... "


hmm. I have been sucessful with meshes up to 15000 polys, and the function will weld them in seconds, not minutes. But the problem is objects in general. If I make a regular matrix even, with more than 15000 polys and just try to display it, it really really hits the frame rate. I think this is why I need to learn to use memblocks. I don't think you can really do anything big without them. Also, I have a better idea on how to create my matrixs. I realize now I don't have to make two triangles. I just need a list of vertices, and in index to point at the vertices. So, I'll have the grid function greatly improved later tonight after I get off work.
Thanks for your comments and insights.
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 24th Jun 2007 22:13
well, I've been playing around a bit, and I added some timer code to see just how long it takes to do the welds on my grids. Also, I don't quite know why, but all of a sudden I'm doing over 20,000 polys and no real hit on the framerate. Anyway, I am doing this at work on a real POS computer, like a 2 gig regular Athlon, I think. I'd like to see what the numbers are on a really fast pc, like a core Duo or x2. So, if someone doesn't mind, could you run this code and post the results? Start with the grid size small. When I do a 20k poly grid, I set it to 2000,2000,100,100.
Thanks if you do this for me.
BTW, for this example, 1800 polys, takes 3.25 seconds to generate, 1.51 seconds to weld.
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 25th Jun 2007 07:20
well, no takers?
ok, anyway, I'm home now, and on my Athlon 64 3000, same code returns
make: 0.79 seconds
weld: 1.90 seconds

so, cpu really makes a difference.
Green Gandalf
VIP Member
19
Years of Service
User Offline
Joined: 3rd Jan 2005
Playing: Malevolence:Sword of Ahkranox, Skyrim, Civ6.
Posted: 26th Jun 2007 00:30
On my Pentium III/930MHz machine I get:

make: 11.1 secs
weld: 4.3 secs

The display also shows "0 vertices" and "0 indices". Is that correct?

And, yes, CPU does make a difference.
Johaness
17
Years of Service
User Offline
Joined: 20th Sep 2006
Location:
Posted: 26th Jun 2007 02:51
Pentium4 2.4Mhz

make: 4.85
weld: 1.54
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 27th Jun 2007 03:22
GG-
yes, thats correct because I was using those variables for information I am no longer reporting in this code. I just forgot to strip out the line in the displaydata() function. But one thing, that is way too slow. The weld isn't too bad, but, the grid really needs work. thanks both of you guys.
dononeton
19
Years of Service
User Offline
Joined: 12th Jun 2004
Location: Tusaloosa, AL : USA
Posted: 27th Jun 2007 04:27
3800 amd athlon 2 core
make 1.3
weld 1.8

AMD Athlon 64 x2 Dual Core Processor 3800+,MMX 3DNOW (2CPUs)
1024 MB RAM
GeForce 7300 GT 512 MB
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 27th Jun 2007 04:54
dononeton-
wow, thats not what I expected, not at all. I'm running single core and am faster? Your rig should smoke mine. Is that result with the 1800 polys?
It's looking like the weld is doing fairly weld, its my grid that is real slow, BUT, and keep your fingers crossed, I think I figured out a neat little way to make the grid a whole lot faster. Testing it now, stay tuned....
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 28th Jun 2007 13:21 Edited at: 28th Jun 2007 14:18
EDIT: For some reason, spheres aren't working now, they worked fine before. So, try spheres at your own risk. Its throwing exceptions up.
Edit: ok, found the bug, spheres work now
UPDATE:
Ok, I found two spots in the code where things were really bogging down. Made a couple small changes, made a big difference. Also, I found out that after you weld an object, you can't tile a texture anymore, because of the shared verts. So, I wrote in a little block of code that will stretch an image across the entire object. I also found a way to make my grids WAY WAY WAY faster, and without memblocks, but this is also a kind of cool trick, so I think its going to get its own thread, but I want to make sure it hasn't been brought up before first. Anyway, here is the new function. It has 2 parameters now, object ID and UV flag. Set UV flag to 0 for no mapping, or 1 for stretch mapping.


I documented the changes, again they were small, one loop was searching the list of verts for matches, even if they were already marked as matches. That was the big one. The other loop was a nested loop that didn't need to search from the top every iteration. I don't think I can get this to go any faster without doing anything directly with memory.
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 2nd Jul 2007 12:25 Edited at: 2nd Jul 2007 12:36
Well, I've been busy
I decided to take the plunge and learn memblocks, which now that I have, I don't see how you can make anything serious without them. So, if you haven't used them, you better learn them, because you'll be glad you did. so, I decided to see if I could write the make_grid() function using memblocks. That was a success, and it works so well, I'll post it in the code snippets. So then I decided to try to do the weld_vertices() function. It too was a success, kind of. It doesn't really do it faster, in fact, it is slower with really large objects. But if all you are doing is primitives, which is what this whole thread was about anyway, then it does them lickety split. The biggest primitive you can have is a sphere, and it's limited to about 1100 verts in the vertexdata, so it can handle it. (100 cols x 100 rows). I know where the lag is in the code, its the two loops that search for the duplicates and order the indexes. I think its because I'm doing the loop and compares on the same memblock. I have an idea how I can speed it up by making a third memblock, and comparing between the two, but for now, this just proves it can be done. Oh, and the advantage so far over the old way, you don't need any global variables or types.


If you just add this function to the examples I already posted, then call this function with the parameters id(your object id) and texture_mode(0 for no UV map, 1 for stretch UV map), it should go. I commented it pretty good, and even have some file writing code in there so you can see what is going on in the memblock. Have fun.

EDITED TO ADD:
BTW, you must only use objects with an FVF format of 274, which is the standard format in DBPro. This can easily be modified for format 338 if need be, in fact it is on my list to do to check for format, and do either 274 or 338, and reject anything else.
Visigoth
19
Years of Service
User Offline
Joined: 8th Jan 2005
Location: Bakersfield, California
Posted: 9th Jul 2007 08:27 Edited at: 9th Jul 2007 08:39
still busy
I know this thread got buried, but, I've made some adjustments to the function. I was able to increase the speed of the search by HALF. Also, I found out by experimentation, that delete mesh from mesh() is not even needed. All you need to do is point the indexdata in the vertexdata buffer to point at the duplicate vertices. So, here it is, in all it's glory

It looks alot scarier than it is. There is alot of comment code in there. What does it do? Pass in the number of the object you want welded, and it will weld it. What is welded? Welded vertices just share the same index to a vertice in the vertxdata buffer.
If that sounds crazy, then how about this.
It means you can take a cube and twist it all around, or a sphere and make asteroids, or whatever. I have a full set ofother functions that demonstrate this. The goal was to do this without globals or types. And I'm having a blast. Right now, on my machine, it still takes about 80 seconds to weld 20,000 polys, which is still WAY TO SLOW. I know where the hold up is, thanks to Lee's Tips in the newsletters about using timers to check code block speed. But still, this is a significant improvement, and I know I'll get it even faster.

Login to post a reply

Server time is: 2024-05-01 01:41:04
Your offset time is: 2024-05-01 01:41:04