I am trying to load and render some rigged models using Assimp 3.1.1
So I have the aiBone's identified in the hierarchy of aiNode's.
For each aiBone, I have its transformation (TRS) w.r.t. to the parent.
My question is, how can I determine the length of each bone?
Assuming a connected skeleton, this is not a problem for most of the bones, except for the leaf bones.
Assuming I have the following skeleton structure:
b0 --> b1 --> b2
with b0 being the root bone and b2 being the leaf bone. How can I know the length of b2 (since I only have its transformation w.r.t. b1)?
Thanks!
So, after a little further digging..
ISTM that there isn't any implicit way of knowing where leaf bones should terminate.
The following code comments are referenced from the Ogre3D wiki (it's not assimp, but we're talking about the same problem here).
if(numChildren == 0)
{
// There are no children, but we should still represent the bone
// Creates a bone of length 1 for leaf bones (bones without children)
// ...
}
I suppose you could consider trying to calculate the length of a leaf bone, by calculating the distance from the bone to the edge of the mesh that you're rendering.. though that might be more trouble than its worth.
Even though most SDKs and game engines define a skeleton as having bones, that's incorrect. It actually has joints. The bones are the implied connections between joints. When you look at it this way, you realize that all bones have a length and there is no bone extending past leaf joints.
Replacing your example with joints:
J0 ---B0---> J1 ---B1---> J2
B0 is the bone between J0 and J1, and B1 is the bone between J1 and J2.
Related
I am making an engine for the game of Hive (https://www.gen42.com/games/hive) in C++ and I need it to be highly efficient as I will have an AI searching through many thousands of positions. Note that it is not essential to be familiar with Hive to answer this, as this question is more related to graph theory. There is an example at the end.
Representation
In the game of Hive, pieces can be placed and moved around on an infinite hexagonal grid. There is a crucial rule, the One Hive Rule, that states: The pieces in play must be linked at all times (i.e., the Hive may never be broken)
In other words, the hive can be represented as a connected undirected planar graph, where:
The vertices are the pieces
The edges are the connections between adjacent pieces
The articulation points of this graph represent pieces restricted by the One Hive Rule. Also, no vertex can have more than six edges. (pieces on top of the hive are not included in the graph)
Problem
The problem I have is recalculating these articulation points efficiently after the graph is changed and I am wondering if there is some efficient data structure that could handle this.
Specifically, the data structure would need to accommodate the following updates:
Add a vertex to the graph along with its connecting edges (i.e., placing a piece/moving a piece to its new location)
Remove a vertex from the graph along with its connected edges (i.e., removing a piece when it is being moved to a new location)
When queried, the data structure would return which vertices are articulation points.
Also note that the graph begins empty, and the number of vertices can never decrease. (pieces cannot be removed from the hive)
Ideas
I am aware of algorithms like Tarjan’s which calculate the articulation points of a graph in a single DFS traversal. However, most of the time in Hive when a piece is moved, only a few pieces become restricted/unrestricted by this rule (usally no more than 2), and therefore only a few vertices in the graph should have to be updated. (rather than re-traversing the entire graph every time)
Can anyone provide me with an efficient data structure and/or algorithm for this?
Example
(You don’t need to know how the pieces move)
In the current position, the white ant (blue) is about to move to the location south-east of the black bee (yellow). In the graph, I have shown in dark blue the updates that would be required.
The vertices in the graph circled in red are articulation points (immobile pieces). Also note that after the ant has moved to its new location, the vertex corresponding to the black bee will also become an articulation point.
Example Image
A block-cut tree may be useful in solving the problem, but more to the point of this answer, it may help you understand that there is no easy solution to the problem.
Consider the graph shown below (source:wikipedia with modifications in color)):
The graph with 18 vertices (black) is shown on the left. The corresponding block-cut tree is shown to the right. Notice that the cut points (aka articulation points) are considered to be part of the blocks that they connect. So for example, cut point 1 (C1) in the tree, which is vertex 2 (V2) in the graph is a member of blocks B1, B2, and B3.
I propose to add vertex 19 (magenta), and then consider the consequences. I've circled the cut points in the graph. Those circled in red (V2, V8, and V10) remain as cut points when V19 is added. But V7 (aka C2) ceases to be a cut point when V19 is added. That's because C2 in the block-cut tree is part of a cycle that is created by adding V19. And unlike C1, C3, and C4, it doesn't connect to any blocks that aren't part of the cycle. It only connects B3 and B4, which are both part of the cycle.
So after adding V19, there are only 4 blocks and 3 cut points. B2, B5, and B7 continue to exist as separate blocks, connected by C1, C3, and C4 respectively. B1, C1, B3, C2, B4, C3, C4, and B6 are now all part of a single large block. The resulting block-cut tree is shown below (source:ibid with modifications in color):
Finally getting to the point, notice that V7 is about as far away from V19 as it can possibly be. So the effects of adding a vertex aren't localized to the neighbors of the added vertex. The effects can propagate throughout the graph.
And then it gets worse.
We've seen the effects of adding a vertex. Now consider the reverse. After adding V19, the player decides to move the piece that V19 represents, thereby removing V19 from the graph. Suddenly, block B19 explodes into four blocks (B1, B3, B4, and B6), and C2 appears as a cut point. Basically restructuring the entire block-cut tree. So by the time the code finds the newly formed cut point, and rearranges the block-cut tree, it may have been possible (or even faster) to run Tarjan's again.
Skeletal Movement
Hi I have been trying to create a skeleton made of Joints and Bones. The skeleton is done in JavaFX using circles and lines. I have manage to connect the lines (bones) at pivot points (joints). Given two pivot points it is possible to rotate a bone around its parent joint. What I am trying to achieve is for Example:
Given that there are 3 bones connected to each other at pivot points Bone A, B and C if lets say bone A is rotated around its pivot point bone B and C should move relative to bone A while maintaining their respective positions. If bone B is rotated bone C should follow.
Here are some images showing the desired effect
Shows how the bones are originally position before rotating bone B
Shows how the bones should be position after rotating bone B
The problem I am having is that I am not sure how to calculate the values in order to make this possible. I have been looking around for similar problems for a while with no luck. I was hesitant to ask the question. I hope my question was clear enough. All comments and help is deeply appreciated Thank you for your time.
I am currently learning about computer graphics but the topic of cyclic ordering is something that I can't seem to grasp. I was told that software like blender export the indices of triangles making up a model in a cyclic order. This way, the normals are ensured to point outward from the model.
I am not so sure what cyclic order means and how does this kind of ordering applies to triangles indices? Also, if I want to procedurally generate a mesh, what would be the algorithm I should use to apply cyclic ordering so that my mesh has correct indices for calculating normals?
Cyclic ordering means that cyclic permutations of vertex indices in a certain direction give a outward pointing normal. To illustrate this, here is a diagram:
The cylindrical arrows show the outward pointing normal. On the left is the anti-clockwise ordering convention, and on the right clockwise. The circular arrows show the directions that you can shift ("permute") the indices in, for the normal to stay the same.
For the anti-clockwise convention you would calculate the normal by (p2 - p1) x (p3 - p1), and for clockwise, (p3 - p1) x (p2 - p1). Note that the use of particular indices in these formulas is arbitrary as cyclic permutation would cover all possible ways of calculating the normal.
I don't know if one convention is more commonly used than the other (in OpenGL, for example, you are free to set either); but if it is then I would guess the anti-clockwise (2 before 3). Again - it only matters that different programs using the same data also share the same convention.
As an example, OpenGL uses the convention to determine how to calculate the outward normal, which it uses to do backface culling. It takes the dot product of the normal with a displacement vector from the camera to any point in the triangle's plane. If the result is negative then the triangle is facing the camera, and vice versa. (This is only useful for closed meshes though - you would see holes as transparent from certain angles. Again, OpenGL provides the option to disable backface culling entirely for this purpose.)
If you procedurally generate a mesh, and want to compute the correct index ordering for all triangles, do the following:
Set the per-triangle indices in any order (as long as they belong to the correct triangle)
Calculate the normal using either convention that you choose (remember to be consistent)
Use the method in my previous answer to determine whether the computed normal is facing inwards
If it is, then swap any two indices for the triangle. This will switch to the correct ordering.
I am currently working on a node-based house-builder for Unity. The system is pretty simple in its workflow: users can create nodes, which are simply cubes, and connect them with each other to create walls. The mesh processing is already done and it works nice and smooth.
What I am trying to do now is to detect how many closed rooms have been created and what vertices are involved in each one of them. The possible inputs can be seen in the following images:
In the first picture, the loops would be
(1,5,3,4), (1,2,6,8,7,5), (6,9,12,11,10,8), (8,10,14,13) and (10,11,17,16,15,14).
In the second one they'd be
(1,2,5,6,8,7), (2,3,4,14,13,6,5), (6,13,12,11,10) and (8,6,10,9).
Each node can be connected to up to four other nodes, one per cardinal side, and every link is stored on both sides. I do not need the nodes to come in any particular order.
I thought I could use a generic loop-detection algorithm and recursively search for sub-loops until the loop I find has has no internal connections, but this would be extremely resource-consuming. There must be some properties I can use to detect loops with no internal connections without iterating over the graph so many times, but I haven't been able to find it.
Do you have any suggestion?
For the following algorithm to work, you need the following:
A unique direction of the edge (which you probably already have)
Two flags for every edge that specify if the edge has been used in the forward and the backward direction
A list of vertices with unused edges
Then the idea is the following. Take any node with unused edges and go along any of the unused edges to the neighbor (keep the direction in mind). Doing so, immediately mark the edge in the according direction as used. At this neighbor, you know the direction from which you came. Look in counter-clockwise order until you find the first unused edge (again watch out for the edge direction). You can also search in clockwise order, this will define the order of all your output faces. E.g. if you came from the left edge, then check the bottom, right, top edges, respectively. Go across this edge (mark as used) and repeat until you arrive at the start vertex. All visited vertices form your room.
Doing so, you should update the list of vertices with unused edges accordingly.
Eventually, you will also create a face for the border. You can detect this e.g. by calculating its orientation:
v1 x v2 + v2 x v3 + v3 x v4 + ... + vn x v1
, where v are the positions of the vertices and x represents the z-component of the cross product (which represents the face orientation):
(x1, y1) x (x2, y2) = (x1 * y2) - (x2 * y1)
The boundary face will have a different sign for this orientation than all other faces. The actual sign depends on whether you used counter-clockwise or clockwise order during the edge traversal.
This is an answer only to the first question, but it might help you with the second one. The number of closed rooms actually has a closed formula:
1 - V + E where V is the number of vertices and E is the number of edges. In your second example, there are 14 vertices, 17 edges and 4 rooms.
The mathematics are a bit complicated, but the key word is Euler characteristic.
I'm working on implementing various subdivision algorithms (such as catmull-clark); to do this efficiently requires a good way to store information about a grid of tesselated polygons. I implemented the half-edge data structure as outlined by flipcode, but now I'm not sure how to populate the data structure from vertices!
My initial attempt was to
create vertices
group vertices into faces
sort vertices within faces (using their angle relative to the centroid)
for each face, grab the first vertex and then walk through the sorted vertex list to create a half-edge list.
However, this creates a list of faces (with half-edges) that don't have any information about adjacent faces! This also feels a bit wrong, because it seems as if the faces are really the first-class object and the edges provide auxiliary information; I really feel like I should be creating edges from the vertices and then sorting out the faces from there. But again, I'm not really sure how to go about it that way -- I can't think of a way to create a list of half-edges without creating the faces first.
Any suggestions for what the best way to go turning data about vertices (and faces) into half-edges?
First, I'd like to point you to an excellent C++ implementation of the half-edge data structure: OpenMesh. If you want to use it, make sure you work you way through the tutorial. If (and only if) you do that, working with OpenMesh is quite straightforward. It also contains some nice methods on top of which you can implement subdivision or reduction algorithms.
Now to your question:
However, this creates a list of faces (with half-edges) that don't have any information about adjacent faces! This also feels a bit wrong, because it seems as if the faces are really the first-class object and the edges provide auxiliary information
I think this somewhat misses the point of the half-edge data structure. In a half-edge structure, it is the half-edges that carry the most information!
Quoting shamelessly from the OpenMesh documentation (see also the figure there):
Each vertex references one outgoing halfedge, i.e. a halfedge that starts at this vertex.
Each face references one of the halfedges bounding it.
Each halfedge provides a handle to
the vertex it points to ,
the face it belongs to
the next halfedge inside the face (ordered counter-clockwise) ,
the opposite halfedge ,
(optionally: the previous halfedge in the face ).
As you see, most information is stored in the half-edges - these are the primary objects. Iterating over meshes in this data-structure is all about cleverly following pointers.
However, this creates a list of faces (with half-edges) that don't have any information about adjacent faces!
This is perfectly ok! As you see above, a face references only one bounding half edge. Assuming a triangle mesh, the chain of pointers you follow to get the 3 adjacent triangles to a given face F is the following:
F -> halfEdge -> oppositeHalfEdge -> face
F -> halfEdge -> nextHalfEdge -> oppositeHalfEdge -> face
F -> halfEdge -> previousHalfEdge -> oppositeHalfEdge -> face
Optionally, you can use nextHalfEdge -> nextHalfEdge if you don't use the 'previous' pointers. This, of course, generalizes easily to quads or higher order polygons.
If you set the pointers listed above correctly when building your mesh, then you can iterate over all kinds of adjacencies in your mesh like this. If you use OpenMesh, you can use a bunch of special iterators that to the pointer chasing for you.
Setting the "opposite half edge" pointers is of course the tricky part when building a half-edge structure from a "triangle soup". I suggest to use a map data-structure of some kind to keep track of half-edges already created.
To be more specific, here is some very conceptual pseudo-code for creating a half-edge mesh from faces. I omitted the vertex part, which is simpler, and can be implemented in the same spirit. I assume that iteration over a face edges is ordered (e.g. clock-wise).
I assume half edges are implemented as structs of type HalfEdge, which contain the pointers listed above as members.
struct HalfEdge
{
HalfEdge * oppositeHalfEdge;
HalfEdge * nextHalfEdge;
Vertex * vertex;
Face * face;
}
Let Edges be a map from pairs of vertex identifiers to pointers to the actual half-edge instances, e.g.
map< pair<unsigned int, unsigned int>, HalfEdge* > Edges;
in C++. Here is the construction pseudo-code (without the vertex and face part):
map< pair<unsigned int, unsigned int>, HalfEdge* > Edges;
for each face F
{
for each edge (u,v) of F
{
Edges[ pair(u,v) ] = new HalfEdge();
Edges[ pair(u,v) ]->face = F;
}
for each edge (u,v) of F
{
set Edges[ pair(u,v) ]->nextHalfEdge to next half-edge in F
if ( Edges.find( pair(v,u) ) != Edges.end() )
{
Edges[ pair(u,v) ]->oppositeHalfEdge = Edges[ pair(v,u) ];
Edges[ pair(v,u) ]->oppositeHalfEdge = Edges[ pair(u,v) ];
}
}
}
EDIT: Made the code a bit less pseudo, to be more clear about the Edges map and the pointers.
Consider we have a list of triangles, each of which is specified by 3 vertex IDs in counterclockwise order, and the task is to construct the half-edge data structure representing this triangulation. If the vertices are given as 3d-vectors (as in STL file format) then the works starts from giving unique identifiers to each distinct vertex, which is accomplish via a hash map from 3d-vector to vertex ID.
After that we progressively consider every triangle from the list. And the first thing is to find or create its three edges (each of which consists of a pair of half-edges). If some edge is shared by two triangles and the other triangle was already added in the data structure then we find that edge, otherwise new edge must be created.
To find whether an edge between vertices v1 and v2 already exists, we use a flat map from a vertex to one of half-edges with the origin in it. All other half-edges with the same origin can be enumerated using already constructed half-edge data structure. So the algorithm for this step is to look at every half-edge originating in v1 and test whether its destination is v2. If no such edge is found, then two half-edges must be created. In the terms of flipcode: pair of one created half-edge points on the other, vert on v1 and v2 respectively, and next on existing half-edges in v1 and v2, or if it was the first half-edge in a vertex then on itself.
When all 3 edges of the current triangle are found or created, face field of half-edges having that triangle at the left points to new HE_face record representing the triangle.
After all triangles are passed, the data structure is ready. There are certain optimizations and improvements that can be implemented, but the basic idea is as presented above.
All mesh libraries based on half-edge data structure construct it during mesh opening from a standard file format, such as STL/PLY/OBJ/OFF/… So it is a good idea at least to look at their code, and probably even integrate them in your software instead of creating your own implementation:
OpenMesh is a good C++ library already presented in the other answer.
MeshLib is a younger library also written in C++, which opens standard file formats considerably faster (based on my observations especially STLs); this suggests better optimizations in the conversion (see MRMeshBuilder.cpp) in half-edge data structure (MRMeshTopology.h).