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] - [Matrix1] How to use Get Vertexdata Ptr

Author
Message
MonoCoder
18
Years of Service
User Offline
Joined: 4th Dec 2005
Location: england
Posted: 12th Mar 2015 13:39 Edited at: 12th Mar 2015 13:42
The Get Vertexdata Ptr() command appears without fanfare or explanation in the DBPro help files, but it can be used to read and manipulate vertex data at least 2x faster than using the standard vertexdata access commands.

This sort-of-tutorial is mostly pieced together from a fair bit of forum searching and a little trial and error. I haven’t kept tabs on what I got where, but I believe Rudolpho and IanM have supplied the best of it.

Background

DBOData.h in DBP source code contains definition for ‘sMesh’ and supporting structures. The most relevant parts are given here:



(Disclaimer: I don’t actually know or write C++.) The sMesh struct is made by smushing together all those other sMeshXX structs and appending its own bit at the end. So if you look at it in memory you’ll first find the three DWORDs of sMeshFVF, then immediately next to it you’ll find the int, pointers, dwords etc. of sMeshDraw, and so on. Put another way, sMesh inherits from multiple other structures, whose fields are arranged in sMesh’s memory by a basic process of concatenation.

The long and short of it is, all the fields are of a fixed size, so given the address of the first field, you can offset it to get a pointer to any other. Get Vertexdata Ptr will give you that first-field address.

So for example if we want the field sMeshDraw->pVertexData, we have to skip over three DWORDs (sMeshFVF->dwFVFOriginal, dwFVF & dwFVFSize), an Int (sMeshDraw->iMeshType) and a pointer (sMeshDraw->pOriginalVertexData). All these datatypes are 4 bytes each, so we offset by (5 fields X 4 bytes) = 20 bytes.

Now truth be told, I think this is all slightly hacky, but this is DBPro ¯\_( ツ )_/¯

For a given limb, the relevant mesh data can be found like this:



Where lockMode is optional (defaults to 0, but 1 is fastest).

Now mesh properties can be accessed (even after unlocking, if you like) in this way:



The following is an example of reading vertex data. We follow the pVertexData pointer to the first vertex in a list of vertices. What data the vertices carry depends on the FVF, but position and normal data are always present unless deliberately excluded, and always occupy the first few data items, so are straightforward to read:



The easiest way to be sure that data is where it should be is to be strict about what FVF types are allowed in the program, but the layout is quite simple (a one-item-after-the-other affair like the struct) and offsets to each data item can be generated for any given FVF.

In a similar vein, requiring all objects to be indexed simplifies working with them. Here, index data are read and displayed three at a time (every group of three indices representing a triangle):



As demonstrated, vertex data can be read without first using lock vertexdata. When modifying, however, the mesh will not update until the next unlock. It may therefore seem reasonable to conclude that you should lock when editing, but not do so when reading so as to avoid the performance penalty incurred by locking; however, there is in fact little-to-no penalty and as such it seems sensible practice to always lock when accessing vertexdata. Feel free to experiment.

This example snippet modifies an object by randomly nudging vertices along their normals:




Compatibility

Meshes: works as expected.
Clones: works as expected.
Instances: remain in sync with source object when source vertexdata changes.
Animated objects: works as expected; if crashing, ensure you have accessed the limb containing the mesh and not the (meshless, transform-only) bone limbs.
Sparkys Collision: works as expected; you must re-setup object after vertexdata changes.
Standard Vertexdata Access: can mix methods without apparent issue.


Notes

Safety: Obviously, like in any instance where you’re poking about under the hood, be vigilant: perform operations in a sensible order along clear dividing lines. Be aware that changes to, say, the vertex count, causes DBP to resize (and thus reallocate) the data, and will therefore invalidate your corresponding local pointers; refresh them in the same manner you initially acquired them.

So far, I’ve encountered no unexplained crashes or memory leaks. I’ll be using direct memory access in my own project so I’ll report any peculiarities, specific case fixes or fatal flaws here if/when I encounter them in the field.

Copies: You can copy the vertex data to somewhere else in memory without issue (using copy memory for example). You can modify that copy as you please and then copy it back, overwriting the original. However, you can’t redirect the mesh pointers to your copy directly – the program will at the very least crash on exit, and will crash immediately if you try to free the original data. The problem may be inconsistent state (other places I don’t know about needing updating), and may be fixable – but its not something I’ll be looking into.


Summary

- Use direct memory access to speed up basic reading and updating of vertex data.

- Prefer the standard commands for more complex, infrequent changes.

- Remember to keep pointers up to date.


Benchmark 1 – reading vertexdata for one big object
(The file denseGeosphere32Seg.X is attached - place it in the exe folder.)



The following is a screen of the benchmark results on my desktop:




Benchmark 2 – Several primitives, clones, instances
Somewhat less rigorous than the first: run the code as is, then swap the comment-blocking and run it again.



Results on my desktop:

Direct access: about 29.5ms;
standard access: about 80.5ms;
Ratio: 1:2.7 or 0.37:1.


Comparison with Memblocks

I’ve never used memblocks to access vertexdata, so can’t say. I hear they’re a bit slow.

Attachments

Login to view attachments
James H
16
Years of Service
User Offline
Joined: 21st Apr 2007
Location: St Helens
Posted: 19th Mar 2015 18:37 Edited at: 19th Mar 2015 18:41
Was just going to give this a go but I am getting a crash. First of all I had one of the older matrix1utils installed so had to remove and replace. Now I only wanted specific matrix1util dlls installed due to a conflict from another project so I went about removing the few I had installed and only installed the ones that were needed to compile the code you provided from the latest matrix1utils. Having gone through that 1 plugin at a time the code finally compiled but upon execution I get a crash!

Problem signature:
Problem Event Name: APPCRASH
Application Name: template.exe
Application Version: 1.0.0.0
Application Timestamp: 4d460aea
Fault Module Name: StackHash_0a9e
Fault Module Version: 0.0.0.0
Fault Module Timestamp: 00000000
Exception Code: c0000005
Exception Offset: 00000000
OS Version: 6.1.7601.2.1.0.256.48
Locale ID: 2057
Additional Information 1: 0a9e
Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
Additional Information 3: 0a9e
Additional Information 4: 0a9e372d3b4ad19135b953a78882e789

I am using u7.7rc7 currently and tested the code under rc6 as I have win7 64bit sp1 and rc6 has a fix required for dbp exe's to work with this setup. Are you using an earlier update? If not, any clue as to why I can't run the exe without the crash produced with your code? My first thought was IanM might not have updated it for u7.7 rc7 but looking at the dates between the 2, IanM's latest matrix1utils is much newer than rc7 of u7.7. Am at a bit of a loss here as I really wanted to check out what you have done here.

Edit:
I almost forgot I did a quick search for the stackhash module reference and I get a lot of results about DEP - have tried turning it off also - same result as before :/
MonoCoder
18
Years of Service
User Offline
Joined: 4th Dec 2005
Location: england
Posted: 20th Mar 2015 00:47 Edited at: 20th Mar 2015 00:48
Hi! You're right regarding me using an earlier update, and given this is one of those error-prone sensitive-to-change hacks I should probably have made a note of it earlier.

I'm on dbp u7.1 (or, v1.071), which I believe was (still is?) considered one of the most safe/stable of the late dbp updates.

Using M1U May 2012, latest as per its thread (and indeed, as you say, after dbp u7.7rc7 which was April 2011 as per this thread).

The dbp source linked to in the first post gives it last revision as December 2011 - I'd assume that if it can be referred to when working with 7.1 without problem, the same must hold for all later updates. In short, I don't think the code is looking somewhere for something that's since moved.

I'm also using win vista, 32-bit sp2. My (very limited) understanding of dbp working on 64-bit systems is that it is 'boxed off' in a 32-bit... place, and for all it knows and cares runs as though it were on a 32-bit system.

I've no particular suggestion to make right now (the problem signature, stackhash, dep stuff and so on goes over my head), but I guess the standard approach is as good a start as any: strip the code down to something that won't crash, then add stuff back little-by-little until it breaks. Let me know how it goes
James H
16
Years of Service
User Offline
Joined: 21st Apr 2007
Location: St Helens
Posted: 20th Mar 2015 06:42
I have tried both 7.1 and 7.2 - both failed to compile, I could not find the get vertexdata ptr() function in the 3d debug dll but spotted it in 7.3 so gave that a go and sure enough it compiled - but got the same crash as before! After some messing around I can get it to run without the same crash error as before, as long as I don't use find free object or make object plane, which inevitably makes it exit with the obvious error of invalid object ID plus the fact more errors will follow without actually creating the first 3 objects even if a good ID was fed in. So I can write my own find free object function(or just borrow evolveds hehehe) but it will take some messing about to get the 3 plane objects from blender and then clean up the exported files so as to ensure any further fails are not down to them or me, so I won't bother until tomorrow as its almost 530am here. On the other hand how would you feel about simply uploading the 3 saved meshes of them labelled case 0, 1 and 2 accordingly, not only will it save me some time(and patience) along with a certainty that any further fails is not down to media, but it would also serve those who find themselves in a similar position - I suspect that there is something different in IanM's 18 & 19 plugins than the rest used in your demo that may well be specific to win7. I will ask in Ian's thread when the time comes if he would consider a fix/looking into this, as I am fairly sure that I had a similar issue with m1u's 18 or 19(cant recall which) with another project which I came across the other week by chance - its the same one I mentioned earlier(I say by chance because I thought I lost all my projects some time ago). That said I need to think more before posting there because I am quite sure - that same project - I had running on vista 32 bit when I came across the issue. Of course being quite sure isn't being sure. Any way its late(well early morning) and I need to sleep so will continue tomorrow. Cheers
James H
16
Years of Service
User Offline
Joined: 21st Apr 2007
Location: St Helens
Posted: 21st Mar 2015 18:48
Hello again, I am having issues recreating the plane objects. The first one is easy enough, the second a little more difficult but should be doable, however I do not understand what the parameters LimbsX and LimbsZ mean for the third object, neither can I find any explanation in the m1u help files or this forum using google search. Any chance of an explanation?
Also does the fvf matter for those plane objects? I ask because according to m1u help files the plane objects should have fvf 274 when an fvf is not stated whereas the other dbp native objects should be fvf 338.
MonoCoder
18
Years of Service
User Offline
Joined: 4th Dec 2005
Location: england
Posted: 22nd Mar 2015 13:30
The second demo is just an assortment of objects - what those objects are doesn't really matter. That said, the M1U make object plane limbsx/z param means it will tile your one plane (the single plane when limbsx/z isn't specified), each tile being another limb of the object.

This should show two identical-looking plane objects, but the left object has 1 limb that is a 10x10 plane; and the right object has 10x10 limbs that are each a 1x1 plane.



The FVF should not matter: as mentioned in the first post, the fvf size is known and so any irrelevant (ie. not position or normal) data is skipped over.

Also, in the second demo, the multi-limb plane objects (in the third column (x=2) and its clone in the 11th column (x=10) of the scene) should only exhibit changing vertices for a single limb - that is to say, the demo is working correctly if it looks like this:



its working fine.

Additionally, I've attached a .rar with the compiled demo executable which might work.

Attachments

Login to view attachments
James H
16
Years of Service
User Offline
Joined: 21st Apr 2007
Location: St Helens
Posted: 23rd Mar 2015 05:36
The compiled exe works just fine thanks, I get 20 to 21 ms. I think my system is having major issues with m1u dlls. I have to check but only have time for this at some point this week. Very dumb of me not to guess the purpose of limbsx/z parameters especially given I have written terrain meshes in memblocks in the past! My only defence is I am an idiot who was tired, same goes for my fvf question having looked at the code again!
James H
16
Years of Service
User Offline
Joined: 21st Apr 2007
Location: St Helens
Posted: 24th Mar 2015 23:31 Edited at: 25th Mar 2015 06:28
I have installed all upgrades in separate install paths:
7.1,7.2(will not compile as get vertexdata ptr() function does not exist)
7.3 through to 7.5(get vertextdata ptr introduced in u7.3 onwards as detailed by Lee)
7.6, 7.61, 7.62
u7.7rc1 through to u7.7rc7
I have not installed any of the u7.1 release candidates as 7.1 and 7.2 did not contain the function get vertexdata ptr()

From 7.3 up I have determined that peek/poke won't accept UDT, array or standard variable as a parameter(on my system), works fine to reference a variable for make memory().

Also have noticed that unless I create an object before calling the m1u function find free object() I will experience the crash.

I have carried out the tests using the standard editor, synergy editor and the Indigo editor just to make sure its not one of them(if your using a different editor please say).

Have never tackled ptr before, have used UDT's before but thats the nearest I've got(I say this because I assume that the "." is something to do with a pointer when referencing a UDT component). Will now attempt to alter your code and change to using make memory() instead - of course assuming this does not defeat the point. But first of all I will read all of the m1u thread to see if there's anything becomes apparent that is related and isn't covered in his very first post. It may be a while before I post back!

It would be nice if someone not using win7 can confirm the code works for them using any upgrade from and including 7.3 as well as from someone who also has win7 32 bit and also from someone with win7 64 bit, other than yourself and me of course. If after a few days this does not happen and you don't mind I will open a thread on the dbp board to see if I can generate some interest in both your code and my problem. Of course this may be subject to change once I have been through m1u thread! Any other advice you have will be very much appreciated

Edit:
The problem I had with make object plane command from m1u was that it needed auto cam to be off before the command was used!

Edit 2:
Well this is just strange!! I now have it working - all I had to do was add make object cube 999,1 near the beginning and compile. I was surprised to say the least, but here is the strange part, I then removed that very same line I added, deleted the previously compiled exe and recompiled - it worked first time. So to make sure I wasn't imagining this I then deleted the entire code and copy pasted from your snippet here back into the project(the benchmark I neglected to tell you I was using as I can see you guessed correctly which one I was referring to earlier). Again it worked!! I do not understand what on earth has gone on - at all. Anyway, knowing I had a separate project set up with simple code that definitely gave me the crashes I experienced earlier and ran that also - it worked first time!!! I no longer have to create a new object before calling the find free object function or call autocam off before creating the plane with m1u command. I havent even altered anything like switching between renaming install paths so that I can check each update with the code. That said - I have now with just u7.3 as a test and the code works fine for this as well! In fact I cannot reproduce the crash no matter what I try whereas before I couldn't escape the crash at all!

So here are the results for benchmark 2:
Ranges between top end of 19 ms and mid to low end of 20 ms for direct access
Bottom end of 55 ms for standard access

Edit 3:
Benchmark 1 image attached

Attachments

Login to view attachments

Login to post a reply

Server time is: 2024-04-18 22:35:46
Your offset time is: 2024-04-18 22:35:46