Beispiel #1
0
        /// <summary>
        /// 2つのVertexを内分するVertexを求める
        /// </summary>
        /// <param name="v1">1つ目のVertex</param>
        /// <param name="v2">2つ目のVertex</param>
        /// <param name="isoValue">等値曲面の値</param>
        /// <returns>内分されたVertex</returns>
        public static Vertex Interpolate(Vertex v1, Vertex v2, float isoValue)
        {
            if (Math.Abs(isoValue - v1.Value) < 0.00001f) {
                return v1;
            }
            if (Math.Abs(isoValue - v2.Value) < 0.00001f) {
                return v2;
            }
            if (Math.Abs(v1.Value - v2.Value) < 0.00001f) {
                return v1;
            }

            var diff = (isoValue -  v1.Value) / (v2.Value - v1.Value);

            Vertex v;
            v.Point = new Vec3(
                v1.Point.X  + (v2.Point.X - v1.Point.X) * diff,
                v1.Point.Y + (v2.Point.Y - v1.Point.Y) * diff,
                v1.Point.Z + (v2.Point.Z - v1.Point.Z) * diff
            );
            v.Value = (v1.Value + v2.Value) * 0.5f;
            v.IsInside = false;

            return v;
        }
        /// <summary>
        /// 等値曲面を計算する
        /// </summary>
        /// <returns>等値曲面を構成する三角形の配列</returns>
        public unsafe List<Triangle> CalculateIsosurface()
        {
            // 等値曲面を構成するポリゴンの動的配列
            var triangles = new List<Triangle>();
            // ポリゴンを構成する座標の配列
            var vertexList = new Vertex[12];
            var vertices = (Vertex*)_verticesBuffer.ToPointer();

            for (var z = 0; z < _sizeZ - 1; z++) {
                for (var y = 0; y < _sizeY - 1; y++) {
                    for (var x = 0; x < _sizeX - 1; x++) {
                        var lookup = 0;
                        var index = x + y * _sizeX + z * _sizeX * _sizeY;

                        // 等値曲面の内側に存在する頂点を検索する
                        if (vertices[index + _sizeX + _sizeXY].IsInside) lookup |= 1;
                        if (vertices[index + 1 + _sizeX + _sizeXY].IsInside) lookup |= 2;
                        if (vertices[index + 1 + _sizeX].IsInside) lookup |= 4;
                        if (vertices[index + _sizeX].IsInside) lookup |= 8;
                        if (vertices[index + _sizeXY].IsInside) lookup |= 16;
                        if (vertices[index + 1 + _sizeXY].IsInside) lookup |= 32;
                        if (vertices[index + 1].IsInside) lookup |= 64;
                        if (vertices[index].IsInside) lookup |= 128;

                        // 全ての頂点が等値曲面の内側・外側に存在しないときのみ
                        if ((lookup != 0) && (lookup != 255)) {
                            if ((EDGE_TABLE[lookup] & 1) != 0)
                                vertexList[0]= Vertex.Interpolate(vertices[index + _sizeX + _sizeXY],
                                                                        vertices[index + 1 + _sizeY + _sizeXY], _isoValue);
                            if ((EDGE_TABLE[lookup] & 2) != 0)
                                vertexList[1] = Vertex.Interpolate(vertices[index + 1 + _sizeX + _sizeXY],
                                                                       vertices[index + 1 + _sizeX], _isoValue);
                            if ((EDGE_TABLE[lookup] & 4) != 0)
                                vertexList[2] = Vertex.Interpolate(vertices[index + 1 + _sizeX],
                                                                  vertices[index + _sizeX], _isoValue);
                            if ((EDGE_TABLE[lookup] & 8) != 0)
                                vertexList[3] = Vertex.Interpolate(vertices[index + _sizeX],
                                                                  vertices[index + _sizeX + _sizeXY], _isoValue);
                            if ((EDGE_TABLE[lookup] & 16) != 0)
                                vertexList[4] = Vertex.Interpolate(vertices[index + _sizeXY],
                                                                  vertices[index + 1 + _sizeXY], _isoValue);
                            if ((EDGE_TABLE[lookup] & 32) != 0)
                                vertexList[5] = Vertex.Interpolate(vertices[index + 1 + _sizeXY],
                                                                  vertices[index + 1], _isoValue);
                            if ((EDGE_TABLE[lookup] & 64) != 0)
                                vertexList[6] = Vertex.Interpolate(vertices[index + 1],
                                                                  vertices[index], _isoValue);
                            if ((EDGE_TABLE[lookup] & 128) != 0)
                                vertexList[7] = Vertex.Interpolate(vertices[index],
                                                                  vertices[index + _sizeXY], _isoValue);
                            if ((EDGE_TABLE[lookup] & 256) != 0)
                                vertexList[8] = Vertex.Interpolate(vertices[index + _sizeX + _sizeXY],
                                                                  vertices[index + _sizeXY], _isoValue);
                            if ((EDGE_TABLE[lookup] & 512) != 0)
                                vertexList[9] = Vertex.Interpolate(vertices[index + 1 + _sizeX + _sizeXY],
                                                                  vertices[index + 1 + _sizeXY], _isoValue);
                            if ((EDGE_TABLE[lookup] & 1024) != 0)
                                vertexList[10] = Vertex.Interpolate(vertices[index + 1 + _sizeX],
                                                                   vertices[index + 1], _isoValue);
                            if ((EDGE_TABLE[lookup] & 2048) != 0)
                                vertexList[11] = Vertex.Interpolate(vertices[index + _sizeX],
                                                                   vertices[index], _isoValue);

                            // 三角形ポリゴンを生成していく
                            for (var i = 0; i < TRI_TABLE[lookup].Length; i += 3) {
                                triangles.Add(new Triangle(
                                    vertexList[TRI_TABLE[lookup][i]].Point,
                                    vertexList[TRI_TABLE[lookup][i + 1]].Point,
                                    vertexList[TRI_TABLE[lookup][i + 2]].Point
                                ));
                            }
                        }
                    }
                }
            }

            return triangles;
        }