Why should I use the node structure for a non-rigged model? - data-structures

I'm working with Vulkan since a few weeks. I have a question about the data structure of a model:
I'm using Assimp for loading fbx and dae files. The loaded model then usually contains several nodes (RootNode and their ChildNodes).
Should I keep this structure on non-rigged models? Or could I transform all the meshes (or rather their vertices) into world space at the first loading by multiplying with the offset matrix of the node (and then delete the node structure in my program)? Because I've never seen that someone transform a node (and their meshes) after loading, if the model isn't rigged.
Or is there any other reason why I should keep this structure?

Assimp also offers the flag aiProcess_PreTransformVertices to flatten the transformation hierarchy. You can also do it manually, of course, by using the aiNode::mTransformation matrices and multiplying them in the right order.
A potential problem with these approaches (especially with the flag) can be that the material properties of sub-meshes can get lost. Assimp doesn't care if sub-meshes have different material properties and just merges them, s.t. the material properties can get lost for a certain sub-mesh. This also applies to other properties like sub-mesh names. If sub-meshes get merged, only one (arbitrarily chosen?) sub-mesh name remains.
I.e. you'll want to prevent flattening the node hierarchy if you would like to use specific properties (names, material properties) of sub-meshes.
If your concern is only w.r.t. transforming them to world space: If you are never going to do something with the nodes in object space (like, e.g., transforming a sub-node in relation to a parent node), then I don't see a reason to not transform them into world space.

Related

CGAL - Preserve attributes on vertex using corefine boolean operations

I'm relatively new to CGAL, so please pardon me if there is an obvious fix to this that I'm missing.
I was following this example on preserving attributes on facets of a polyhedral mesh after a corefine+boolean operation:
https://github.com/CGAL/cgal/blob/master/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_mesh_union_with_attributes.cpp
I wanted to know if it was possible to construct a Visitor struct which similarly operates on vertices of a polyhedral mesh. Ideally, I'd like to interpolate property values (a vector of doubles) from the original mesh onto the new boolean output vertices, but I can settle for imputing nearest neighbor values.
The difficulty I was running into was that the after_subface_created and after_face_copy functions overloaded within Visitor operate before the halfedge structure is set for the target face and hence, I'm not sure how to access the vertices of the target face. Is there a way to use the Visitor structure within corefinement to do this ?
In an older version of the code I used to have a visitor handling vertex creation/copy but it has not been backported (due to lack of time). What you are trying to do is a good workaround but you should use the visitor to collect the information (say fill a map [input face] -> std::vector<output face>) and process that map once the algorithm is done.

Spritekit: Efficiently create many SpriteNodes

I am using SpriteKit to write a bullet-hell style shoot-em-up, and the SK framework seems to be able to handle hundreds of nodes at 60fps without any problems at all. My problem however is that sometimes I need to spawn 50+ nodes in a single frame, and that does seem to cause the odd hitch in framerate. Are there any tricks I should be using to make sure that creation of many nodes is as performant as possible?
I am re-using SKTextures, should I also have a persistent collection of SKSpriteNodes and SKActions that get 'recycled' instead of creating them new?
You can pre-create all nodes before game scene loads(using completion handler) and when needed, just show them i.e. setHidden = NO. This way you don't have to recreate nodes again and again. When nodes are not needed, just set them hidden. You can read more here. Just find part about lasers. I think that would be one way to resolve framerate drop caused by spawning many nodes at same time. And I hope you use atlases...To be sure that everything works correctly enable your draws and nodes count info in view controller and check stats. If you don't use atlases, or use them incorrectly it may happen that draws count is high (comparing to nodes count).
About atlases from the docs:
When you create a texture atlas, you want to strike a balance between
collecting too many textures or too few. If you use too few images,
Sprite Kit may still need many drawing passes to render a frame. If
you include too many images, then large amounts of texture data may
need to be loaded into memory at once. Because Xcode builds the
atlases for you, you can switch between different atlas configurations
with relative ease. So experiment with different configurations of
your texture atlases and choose the combination that gives you the
best performance.
A couple points to keep in mind:
Remove any nodes no longer needed from parent.
Do not use usesPreciseCollisionDetection unless you absolutely have to.
Use a texture atlas.
Do not go overboard with the number of nodes. Stay realistic and only use the minimum needed.

Grab objects near camera

I was looking at the http://threejs.org/examples/webgl_nearestneighbour.html and had a few questions come up. I see that they use the kdtree to stick all the particles positions and then have a function to determine the nearest particle and color it. Let's say that you have a canvas with around 100 buffered geometries with around 72000 vertices / geometry. The only way I know to do this is that you get the positions of the buffered geometries and then put them into the kdtree to determine the nearest vertice and go from there. This sounds very expensive.
What other way is there to return the objects that are near the camera. Something like how THREE.LOD does it? http://threejs.org/examples/#webgl_lod It has the ability to see how far an object is and render the different levels depending on the setting you inputted.
Define "expensive". The point of the kdtree is to find nearest neighbour elements quickly, its primary focus is not on saving memory (Although it does everything inplace on a typed array, it's quit cheap in terms of memory already). If you need to save memory you maybe have to find another way.
Yet a typed array with length 21'600'000 is indeed a bit long. I highly doubt you have to have every single vertex in there. Why not have a position reference point for every geometry part? And, if you need to get the vertices associated to that point, a dictionary. Then you can call myGeometryVertices[ geometryReferencePoint ].
Three.LOD works with raycasts. If you have a (few) hundred objects that might work well. If you have hundred thousands or even millions of positions you'll get some troubles. Also if you're not using meshes; you can't raytrace e.g. a particle.
Really just build your own logic with them. None of those two provide a prebuilt perfect-for-all-cases solution.

How to implement batches using webgl?

I am working on a small game using webgl. Within this game I have some kind of forest which consists out of many (100+) tree objects. Because I only have a few different tree models, I rotate and scale these models in a different way before I display them.
At the moment I loop over all trees to display them:
for (var tree in trees) {
tree.display();
}
While the display() method of tree looks like:
display : function() { // tree
this.treeModel.setRotation(this.rotation);
this.treeModel.setScale(this.scale);
this.treeModel.setPosition(this.position);
this.treeModel.display();
}
Many tree objects share the same treeModel object, so I have to set rotation/scale/position of the model everytime before I display it. The rotation/scale/position values are different for every tree.
The display method of treeModel does all the gl stuff:
display : function() { // treeModel
// bind texture
// set uniforms for projection/modelview matrix based on rotation/scale/position
// bind buffers
// drawArrays
}
All tree models use the same shader but can use different textures.
Because a single tree model consists only out of a few triangles I want to combine all trees into one VBO and display the whole forest with one drawArrays() call.
Some assumptions to make talking about numbers easier:
There are 250 trees to display
There are 5 different tree models
Every tree model has 50 triangles
Questions I have:
At the moment I have 5 buffers that are 50 * 3 * 8 (position + normal + texCoord) * floatSize bytes large. When i want to display all trees with one vbo i would have a buffer with 250 * 50 * 3 * 8 * floatSize byte size. I think I can't use an index buffer because I have different position values for every tree (computed out of the position value of the tree model and the tree position/scale/rotation). Is this correct or is there still a way I can use index buffers to reduce the buffer size at least a bit? Maybe there are other ways to optimize this?
How to handle different textures of the tree models? I can bind all textures to different texture units but how can I decide within the shader which texture should be used for the fragment that is currently displayed?
When I want to add a new tree (or any other kind of object) to this buffer at runtime: Do I have to create a new buffer and copy the content? I think new values can't be added by using glMapBuffer. Is this correct?
Index element buffers can only reach over attributes that are equal to or below 65535 in length, so you need to use drawArrays instead. It's usually not a big loss.
You can add trees to the end of the buffers using GL.bufferSubData.
If your textures are in reasonable sized (like 128x128 or 256x256), you can probably merge them into one big texture and handle the whole thing with the UV-coords. If not, you can add another attribute saying what texture the vertex belongs to and have a condition in the vertex shader, alternatively an array of sampler2Ds (not sure it works, never tried it). Remember that conditions in shaders are pretty slow.
If you decide to stick to your current solution, make sure to sort the trees so the once using the same textures are rendered after each other - keeping state switching down is essential, always.
A few thoughts:
Once you plant a tree in your world, do you ever modify it? Will it animate at all? Or is it just static geometry? If it's truly static, you could always build a single buffer with several copies of each tree. As you append trees, first apply (in Javascript) that instance's world transform to the vertices. If using triangle strips, you can link trees together using degenerate polygons.
You could roll your own pseudo-instanced drawing:
Encode an instance ID in the array buffer. Just set this to the same value for all vertices that are part of the same tree instance. I seem to recall that you can't have non-floaty vertex attributes in ES GLSL (maybe that's a Chrome limitation), so you will need to bring it in as a float but use it as an int. Since it's coming in as a float, you will have to deal with the fact that it's interpolated across your triangle, and so the value will have minor fluctuations - but simply rounding to the nearest integer fixes that right up.
Use a separate texture (which I will call the data texture) to encode all the per-instance information. In your vertex shader, look at the instance ID of the current vertex and use that to compute a texture coordinate in the data texture. Pull out whatever you need to transform the current vertex, and apply it. I think this is called a "dependent texture read", which is generally frowned upon because it can cause performance issues, but it might help you batch your geometry, which can help solve performance issues. If you're interested, you'll have to try it and see what happens.
Hope for an extension to support real instanced drawing.
Your current approach isn't so bad. I'd say: Stick with it until you hit some wall.
50 triangles is already a reasonable batch size for a single drawElements/drawArrays call. It's not optimal, but also not so bad. So for every tree change the paramters like location, texture and maybe shape through uniforms. Then do a draw call for each tree. Also a total of 250 drawElements calls isn't so bad either.
So I'd use one single VBO that contains all the used tree geometry variants. I'd actually split up the trees into building blocks, so that I could recombine them for added variety. And for each tree set appropriate offsets into the VBO before calling drawArrays or drawElements.
Also don't forget that you can do a very cheap field of view culling of each tree.

Performance of using a large number of small VBOs

I wanted to know whether OpenGL VBOs are meant to be used only for large geometry arrays, or whether it makes sense to use them even for small arrays. I have code that positions a variety of geometry relative to other geometry, but some of the "leaf" geometry objects are quite small, 10x10 quad spheres and the like (200 triangles apiece). I may have a very large number of these small leaf objects. I want to be able to have a different transform matrix for each of these small leaf objects. It seems I have 2 options:
Use a separate VBO for each leaf object. I may end up with a large number of VBOs.
I could store data for multiple objects in one VBO, and apply the appropriate transforms myself when changing the data for a given leaf object. This seems strange because part of the point of OpenGL is to efficiently do large numbers of matrix ops in hardware. I would be doing in software something OpenGL is designed to do very well in hardware.
Is having a large number of VBOs inefficient, or should I just go ahead and choose option 1? Are there any better ways to deal with the situation of having lots of small objects? Should I instead be using vertex arrays or anything like that?
The most optimal solution if your data is static and consists of one object would be to use display lists and one VBO for only one mesh. Otherwise the general rule is that you want to avoid doing anything other than rendering in the main draw loop.
If you'll never need to add or remove an object after initialization (or morph any object) then it's probably more efficient to bind a single buffer permanently and change the stride/offset values to render different objects.
If you've only got a base set of geometry that will remain static, use a single VBO for that and separate VBOs for the geometry that can be added/removed/morphed.
If you can drop objects in or remove objects at will, each object should have it's own VBO to make memory management much simpler.
some good info is located at: http://www.opengl.org/wiki/Vertex_Specification_Best_Practices
I think that 200 triangles per one mesh is not so small number and maybe the performance with VBO for each of that meshes will not decrease so much. Unfortunately it is depended on hardware spec.
One huge buffer will no gain huge performance difference... I think that the best option would be to store several (but not all) objects per one VBO.
renderin using one buffer:
there is no problem with that... you simply have one buffer that is bound and then you can use glDrawArrays with different parameters. For instance if one mesh consists of 100 verts, and in th buffer you have 10 of those meshes you can use
glDrawArrays(triangles, 0, 100);
glDrawArrays(triangles, 100, 100);
glDrawArrays(triangles, ..., 100);
glDrawArrays(triangles, 900, 100);
in that way you minimize changing buffers and still you are able to render it quite efficient.
Are those "small" objects the same? do they have the same geometry but different transformations/materials? Because maybe it is worth using "instancing"?

Resources