Jump to content

  • Log In with Google      Sign In   
  • Create Account

Need some experience input on 3D model structure


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 Danicco   Members   -  Reputation: 449

Like
0Likes
Like

Posted 11 September 2013 - 02:36 PM

I'm finally starting to code the 3D structure of my engine, and after watching some videos (physX particularly), it made me rethink on how I was going to design it.

 

At first, I was going to have the following:

 _______________      ____________      _________
| ModelInScreen |--->| ModelClass |--->| VBO/IBO |
|_______________|    |____________|    |_________|
(has position/etc)    / (template)     (has the float arrays for data)
 _______________     / 
| AnotherModel  |---´
|_______________|
(has another position/etc)

But then, I started to think about animations and how it needs to change the actual mesh data, so I can't really have the same modelClass for a bunch of different game entities, even if they do use the same model.

 

So I'm thinking that each game entity (a 3D model in screen) must have it's own vertexData so it's skeleton/deformation effects can change it's data without affecting the other ones.

 

Or I could try to find some solution to divide the mesh somehow, and in the shader I sent the skeleton/deformation matrix and only the affected vertexes (still haven't figured if this is possible or not with extra atrib pointers and some uniforms for bones), so I don't get the same resource loaded twice in the memory.

 

Not sure if this is a big hit on performance as well (I'm assuming it is, and I have no idea how those games with armies of models do).

 

Also, I'm beginning to think on the physics and what I will try to implement, though it's not urgent, but I still want to leave room for improvements and work with some (what I believe it is) mesh deformations like what physX does.

I'm guessing it makes deformations directly on the vertexes and use a 3D texture to show what's inside and either just push back vertexes creating a deformation, or completely destroys an area and automatically builds a new mesh to "close" the hole to simulate model destruction.

 

Anyway, I'd like to ask for some experience help here, how is this handled, what's the best way?

 

The options I thought so far:

 

1. Each entity has it's own vertex data (duplicates data in memory, but each has it's own)

2. Entities shares the vertex data pointer, and every entity "resets" the pointer data and then apply it's own transformation to it (don't duplicate, but needs more computations per object)

3. Try to figure a shader solution such as creating a new AttribPointer and sending weights/matrices to multiply each vertex.

 

Other suggestions on how this could be handled are also appreciated!

 

Edit: Just figured how I'd do it with the shader, I'd do something like:

//Vertex Shader (GLSL)
layout(location = 0) in vec3 vertexPosition;
//etc
layout(location = 4) in float vertexWeight; //maybe unnecessary
layout(location = 5) uniform mat4 vertexBoneTransformation; //vertexWeight could be computed here already

And in the game Update(), for every vertex in the model, I'd calculate (still not sure how) it's bone transformation/vertex deformation * weight, then I'd get a matrix for this, and I'd only need to upload/mapSubBuffer this value.

That'd avoid duplicate vertex data in the memory and VBOs, but this calculation looks quite expensive for each vertex, and uploading mat4s for every vertex seems also a bit heavy...

 

Edit2: I think I got this right, but it seems like:

 

(bones being mat4, vertex being vec3)

#1 has CPU: (bones^bones) * vertex, RAM: models * Count, GPU: float upload

#2 has CPU: ((bones^bones) * vertex)^2, RAM: models * 1, GPU: float upload

#3 has CPU: (bones^bones) * vertex, RAM: models * 1, GPU: float[4][4] upload

 

I... don't really like any of these options, they all seem bad, but #1 seems to be the least terrible of them all...


Edited by Danicco, 11 September 2013 - 03:17 PM.


Sponsor:

#2 DekuTree64   Members   -  Reputation: 986

Like
0Likes
Like

Posted 12 September 2013 - 03:22 AM

Here's how I structure it:

 

ModelResource: Read-only data, can be shared. Contains all the model data except textures (it just has filenames for them)

AnimResource: Read only data, can be shared. Has an array of keyframes for each joint of the model it goes with.

 

AnimState: Dynamic, not shared. Has a pointer to ModelResource and AnimResource, and current translation/rotation/scale for each joint of the model. Tell it a frame number, and it calculates the joint values with interpolation between keyframes.

 

Model: Dynamic, not shared. Combines the previous 3, and handles the memory allocation/file loading/textures/rendering. Also handles texture swapping.

 

Above that is actual game entities, which have a Model, and their world position and rotation and such. Multiply those into the modelview matrix before calling the model render.


Edited by DekuTree64, 12 September 2013 - 03:31 AM.


#3 Danicco   Members   -  Reputation: 449

Like
0Likes
Like

Posted 12 September 2013 - 05:47 AM

After thinking a bit about it, I'm thinking that's the best way to deal with it (it's the option #2 in the first post).

 

I was thinking I had to "save" the actual state of the model for some reason, and so each model needed to have it's own instance of the mesh resource.

Hmm, actually, I was thinking I had to save the actual state so I don't upload any vertex info to the GPU if the model class hasn't changed since the last frame.

 

By keeping a single mesh resource (VBO), I'm going to have to upload new data for every model and every frame, regardless if they changed or not from their previous state.

 

Still looks better than having 30+ of the same VBO, but this seems like something that could be improved on if I know the type of the object (if there'll be multiples of it or not).


Edited by Danicco, 12 September 2013 - 05:47 AM.


#4 DekuTree64   Members   -  Reputation: 986

Like
0Likes
Like

Posted 12 September 2013 - 09:45 AM

After thinking a bit about it, I'm thinking that's the best way to deal with it (it's the option #2 in the first post).

 

I was thinking I had to "save" the actual state of the model for some reason, and so each model needed to have it's own instance of the mesh resource.

Hmm, actually, I was thinking I had to save the actual state so I don't upload any vertex info to the GPU if the model class hasn't changed since the last frame.

 

By keeping a single mesh resource (VBO), I'm going to have to upload new data for every model and every frame, regardless if they changed or not from their previous state.

 

Still looks better than having 30+ of the same VBO, but this seems like something that could be improved on if I know the type of the object (if there'll be multiples of it or not).

Yeah, my thought on the matter is that animated things will most likely be needing to update every frame regardless, so there's not much point optimizing for unchanging things. And static objects will generally have no animation at all. Or if they do have a single-frame animation, then all instances will be using the same one, so you can add a check to skip the update if the VBO is already in the correct state.

 

That said, I don't think you should need to update the VBO every frame at all, unless you're doing skinning calculations in software. But I haven't learned shaders well enough yet to say for sure. I've done software skinning in the past, and hard-weighted skinning on Nintendo DS using display lists and the matrix stack, but my current engine doesn't have skinning at all yet. I think all the transformations for it should be done in the vertex shader during rendering. I'm just not sure exactly how that's done yet mellow.png






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS