示例#1
0
            /// <summary>
            /// Converts a DynamicOctree into this BFSOctree.
            /// </summary>
            /// <param name="node">The DynamicOctree to convert into this BFSOctree.</param>
            private void convert(DynamicOctreeNode node)
            {
                Queue<DynamicOctreeNode> queue = new Queue<DynamicOctreeNode>();

                queue.Enqueue(node);
                node = null;
                uint offset = 1;
                int index = 0;

                while (queue.Count > 0)
                {
                    DynamicOctreeNode currentNode = queue.Dequeue();

                    uint mask = 0;
                    if (currentNode.hasChildren())
                    {
                        DynamicOctreeNode child = currentNode.getFirstChild();
                        for (byte i = 0; i < currentNode.getChildCount(); ++i)
                        {
                            queue.Enqueue(child);

                            mask |= (byte)(1u << child.position);
                            child = child.getNextNode();
                        }
                    }

                    if (index < _innerNodes.Length)
                        _innerNodes[index++] = new BFSInnerNode(mask, offset, currentNode.vd);
                    else
                        _leaves[index++ - _innerNodes.Length] = new BFSLeaf(currentNode.vd);

                    offset += currentNode.getChildCount();
                }
                queue.Clear();
            }
示例#2
0
 /// <summary>
 /// Creates a new empty node with no child nodes.
 /// </summary>
 /// <param name="position">The position of this node relative to
 /// its parent. <seealso cref="DynamicOctree"/></param>
 public DynamicOctreeNode(byte position)
 {
     childCount = 0;
     this.position = position;
     firstChild = null;
     nextNode = null;
     dist = float.MaxValue;
 }
示例#3
0
            /// <summary>
            /// Helper function used to assign bone weights to voxels.
            /// Since a voxel is approximated by a triangle, in the worst case,
            /// 12 bone weights could affect it. This function determines the 4 most
            /// influential bones for a voxel and assigns them to it.
            /// </summary>
            /// <param name="node">The node to assign bone weights to.</param>
            /// <param name="vertices">Vertex buffer of the triangle mesh.</param>
            /// <param name="indices">Index buffer of the triangle mesh.</param>
            /// <param name="index">Index of the first vertex of the triangle.</param>
            /// <param name="u">Barycentric coordinate of the triangle's first vertex.</param>
            /// <param name="v">Barycentric coordinate of the triangle's second vertex.</param>
            /// <param name="w">Barycentric coordinate of the triangle's third vertex.</param>
            private static void weight(DynamicOctreeNode node,
                                       FBXVertexFormat[] vertices,
                                       int[] indices, int index,
                                       float u, float v, float w)
            {
                for (int i = 0; i < 256; ++i)
                {
                    boneWeights[i] = 0.0f;
                    boneIndices[i] = (byte) i;
                }

                boneWeights[vertices[indices[index]].boneIndex0] += vertices[indices[index]].boneWeights.X * u;
                boneWeights[vertices[indices[index]].boneIndex1] += vertices[indices[index]].boneWeights.Y * u;
                boneWeights[vertices[indices[index]].boneIndex2] += vertices[indices[index]].boneWeights.Z * u;
                boneWeights[vertices[indices[index]].boneIndex3] += vertices[indices[index]].boneWeights.W * u;

                boneWeights[vertices[indices[index + 1]].boneIndex0] += vertices[indices[index + 1]].boneWeights.X * v;
                boneWeights[vertices[indices[index + 1]].boneIndex1] += vertices[indices[index + 1]].boneWeights.Y * v;
                boneWeights[vertices[indices[index + 1]].boneIndex2] += vertices[indices[index + 1]].boneWeights.Z * v;
                boneWeights[vertices[indices[index + 1]].boneIndex3] += vertices[indices[index + 1]].boneWeights.W * v;

                boneWeights[vertices[indices[index + 2]].boneIndex0] += vertices[indices[index + 2]].boneWeights.X * w;
                boneWeights[vertices[indices[index + 2]].boneIndex1] += vertices[indices[index + 2]].boneWeights.Y * w;
                boneWeights[vertices[indices[index + 2]].boneIndex2] += vertices[indices[index + 2]].boneWeights.Z * w;
                boneWeights[vertices[indices[index + 2]].boneIndex3] += vertices[indices[index + 2]].boneWeights.W * w;

                Array.Sort(boneWeights, boneIndices);
                float sum = 1.0f / (boneWeights[255] + boneWeights[254] + boneWeights[253] + boneWeights[252]);

                node.vd.boneIndex0 = boneIndices[255];
                node.vd.boneIndex1 = boneIndices[254];
                node.vd.boneIndex2 = boneIndices[253];
                node.vd.boneIndex3 = boneIndices[252];

                node.vd.boneWeights.X = boneWeights[255] * sum;
                node.vd.boneWeights.Y = boneWeights[254] * sum;
                node.vd.boneWeights.Z = boneWeights[253] * sum;
                node.vd.boneWeights.W = boneWeights[252] * sum;
            }
示例#4
0
            /// <summary>
            /// Helper method used by <see cref="TriangleMesh.toDynamicOctree"/>.
            /// It constructs the DynamicOctree recursively. It is supplied a
            /// triangle and adds all nodes to the octree that intersect the triangle.
            /// </summary>
            /// <param name="pos">Position of the current node relative to its parent.
            /// See <see cref="DynamicOctree"/></param>
            /// <param name="x">x-coordinate within the virtual uniform grid spanned by the octree.</param>
            /// <param name="y">y-coordinate within the virtual uniform grid spanned by the octree.</param>
            /// <param name="z">z-coordinate within the virtual uniform grid spanned by the octree.</param>
            /// <param name="octreeMin">Minimum vector of the octree.</param>
            /// <param name="gridDimension">Dimension of the octree (a cube).</param>
            /// <param name="index">Index of the first triangle vertex.</param>
            /// <param name="triBBmin">Minimum vector of the triangle bounding box.</param>
            /// <param name="triBBmax">Maximum vector of the triangle bounding box.</param>
            /// <param name="level">Current tree level/depth.</param>
            /// <param name="maxLevel">The maximum node level/depth of any node in
            /// the created DynamicOctree.</param>
            /// <param name="parent">Parent node of the current node.</param>
            private void traverse(byte pos,
                                  ushort x, ushort y, ushort z,
                                  Vector3 octreeMin, double gridDimension,                            
                                  int index,
                                  Vector3 triBBmin, Vector3 triBBmax,                  
                                  byte level, byte maxLevel,
                                  DynamicOctreeNode parent)
            {
                if (level == 0)
                {
                    for (byte i = 0; i < 8; ++i)
                    {
                        traverse(i,
                                 (ushort)(x * 2 + (i & 1)),
                                 (ushort)(y * 2 + ((i & 2) >> 1)),
                                 (ushort)(z * 2 + ((i & 4) >> 2)),
                                 octreeMin, gridDimension,
                                 index,
                                 triBBmin, triBBmax,
                                 (byte)(level + 1), maxLevel,
                                 parent);
                    }
                }
                else
                {
                    if (Math3DHelper.intersects(x, y, z, level, gridDimension,
                                                octreeMin,
                                                _vertices[_indices[index]].position,
                                                _vertices[_indices[index + 1]].position,
                                                _vertices[_indices[index + 2]].position,
                                                triBBmin, triBBmax))
                    {
                        DynamicOctreeNode newParent = parent.addChild(pos);

                        float gridCellDim = (float)(gridDimension / (1u << level));
                        float gridCellHalfDim = gridCellDim * .5f;
                        Vector3 center = new Vector3(x * gridCellDim + gridCellHalfDim,
                                                     y * gridCellDim + gridCellHalfDim,
                                                     z * gridCellDim + gridCellHalfDim) +
                                                     octreeMin;

                        float triArea = Vector3.Cross(_vertices[_indices[index + 1]].position -
                                                      _vertices[_indices[index]].position,
                                                      _vertices[_indices[index + 2]].position -
                                                      _vertices[_indices[index]].position).Length() * 0.5f;

                        float u = Vector3.Cross(_vertices[_indices[index + 1]].position -
                                                center,
                                                _vertices[_indices[index + 2]].position -
                                                center).Length() * 0.5f;

                        float v = Vector3.Cross(_vertices[_indices[index]].position -
                                                center,
                                                _vertices[_indices[index + 2]].position -
                                                center).Length() * 0.5f;

                        float w = Vector3.Cross(_vertices[_indices[index]].position -
                                                center,
                                                _vertices[_indices[index + 1]].position -
                                                center).Length() * 0.5f;

                        float sum;
                        if ((sum = u + v + w) < newParent.dist)
                        {
                            newParent.dist = sum;
                            triArea = 1.0f / triArea;
                            u *= triArea;
                            v *= triArea;
                            w *= triArea;
                            sum = 1.0f / (u + v + w);
                            u *= sum;
                            v *= sum;
                            w *= sum;
                            newParent.vd.normal = u * _vertices[_indices[index]].normal +
                                                  v * _vertices[_indices[index + 1]].normal +
                                                  w * _vertices[_indices[index + 2]].normal;
                            newParent.vd.normal.Normalize();

                            newParent.vd.texCoords = u * _vertices[_indices[index]].texCoord +
                                                     v * _vertices[_indices[index + 1]].texCoord +
                                                     w * _vertices[_indices[index + 2]].texCoord;

                            weight(newParent, _vertices, _indices, index, u, v, w);

                            Vector3 e1 = _vertices[_indices[index + 1]].position - _vertices[_indices[index]].position;
                            Vector3 e2 = _vertices[_indices[index + 2]].position - _vertices[_indices[index]].position;
                            Vector2 euv1 = _vertices[_indices[index + 1]].texCoord - _vertices[_indices[index]].texCoord;
                            Vector2 euv2 = _vertices[_indices[index + 2]].texCoord - _vertices[_indices[index]].texCoord;

                            float cp = euv1.Y * euv2.X - euv1.X * euv2.Y;
                            if (cp != 0.0f)
                            {
                                newParent.vd.tangent = (e1 * (-euv2.Y) + e2 * euv1.Y) / cp;
                                newParent.vd.tangent.Normalize();
                            }
                        }

                        if (level < maxLevel)
                        {
                            for (byte i = 0; i < 8; ++i)
                            {
                                traverse(i,
                                         (ushort)(x * 2 + (i & 1)),
                                         (ushort)(y * 2 + ((i & 2) >> 1)),
                                         (ushort)(z * 2 + ((i & 4) >> 2)),
                                         octreeMin, gridDimension,
                                         index,
                                         triBBmin, triBBmax,
                                         (byte)(level + 1), maxLevel,
                                         newParent);
                            }
                        }
                    }
                }
            }
示例#5
0
            /// <summary>
            /// Adds a child with the specified node to this
            /// node, iff there is no child node with position <paramref name="withPos"/> yet.
            /// In there is already such a node, it is returned.
            /// </summary>
            /// <param name="withPos">The position of the child node relative to this node.</param>
            /// <returns>The child of this node with relative position <paramref name="withPos"/>.</returns>
            public DynamicOctreeNode addChild(byte withPos)
            {
                if (childCount == 0)
                {
                    firstChild = new DynamicOctreeNode(withPos);
                    ++childCount;
                    return firstChild;
                }
                else
                {
                    if (withPos < firstChild.position)
                    {
                        DynamicOctreeNode insert = new DynamicOctreeNode(withPos);
                        insert.nextNode = firstChild;
                        firstChild = insert;
                        ++childCount;
                        return insert;
                    }
                    else if (withPos == firstChild.position)
                        return firstChild;

                    DynamicOctreeNode currentNode = firstChild.nextNode;
                    DynamicOctreeNode previousNode = firstChild;
                    for (int i = 1; i < childCount; ++i)
                    {
                        if (withPos < currentNode.position)
                        {
                            DynamicOctreeNode insert = new DynamicOctreeNode(withPos);
                            previousNode.nextNode = insert;
                            insert.nextNode = currentNode;
                            ++childCount;
                            return insert;
                        }
                        else if (withPos == currentNode.position)
                        {
                            return currentNode;
                        }
                        else
                        {
                            currentNode = currentNode.nextNode;
                            previousNode = previousNode.nextNode;
                        }
                    }

                    previousNode.nextNode = new DynamicOctreeNode(withPos);
                    ++childCount;
                    return previousNode.nextNode;
                }
            }