예제 #1
0
        protected StoredValue <ValueT> GetValue(int x, int y, int z, long identifier)
        {
            if (valueDictionary.ContainsKey(identifier))
            {
                var prevValue = valueDictionary[identifier];
                if (prevValue.NumTimesCalled < 7)
                {
                    prevValue.NumTimesCalled++;
                }
                else
                {
                    valueDictionary.Remove(identifier);
                }
                return(prevValue);
            }
            var newValue = new StoredValue <ValueT>
            {
                Value          = GetValueFromSolid(x, y, z),
                X              = x,
                Y              = y,
                Z              = z,
                NumTimesCalled = 1,
                ID             = identifier
            };

            valueDictionary.Add(identifier, newValue);
            return(newValue);
        }
예제 #2
0
 protected override double GetOffset(StoredValue <double> from, StoredValue <double> to,
                                     int direction, int sign)
 {
     if (from.Value.IsPracticallySame(surfaceLevel))
     {
         return(0.0);
     }
     if (to.Value.IsPracticallySame(surfaceLevel))
     {
         return(gridToCoordinateFactor);
     }
     if (to.Value.IsPracticallySame(from.Value))
     {
         return(gridToCoordinateFactor / 2);
     }
     return(gridToCoordinateFactor * (surfaceLevel - from.Value) / (to.Value - from.Value));
 }
 protected override double GetOffset(StoredValue <double> from, StoredValue <double> to,
                                     int direction, int sign)
 {
     if (from.Value.IsNegligible())
     {
         return(0.0);
     }
     if (to.Value.IsNegligible())
     {
         return(gridToCoordinateFactor);
     }
     if (direction == 2 && (double.IsInfinity(from.Value) || double.IsInfinity(to.Value)))
     {
         return(0.5 * gridToCoordinateFactor);
     }
     return(-gridToCoordinateFactor * from.Value / (to.Value - from.Value));
 }
예제 #4
0
        protected override double GetOffset(StoredValue <bool> from, StoredValue <bool> to,
                                            int direction, int sign)
        {
            switch (direction)
            {
            case 0:
                var maxX = to.X - from.X;
                for (int i = 1; i < maxX; i++)
                {
                    if (GetValueFromSolid((from.X + sign * i), from.Y, from.Z) != GetValueFromSolid((from.X + sign * (i - 1)), from.Y, from.Z))
                    {
                        return(gridToCoordinateFactor * (i + 0.5) / maxX);
                    }
                }
                break;

            case 1:
                var maxY = to.Y - from.Y;
                for (int i = 1; i < maxY; i++)
                {
                    if (GetValueFromSolid(from.X, (from.Y + sign * i), from.Z) != GetValueFromSolid(from.X, (from.Y + sign * (i - 1)), from.Z))
                    {
                        return(gridToCoordinateFactor * (i + 0.5) / maxY);
                    }
                }
                break;

            case 2:
                var maxZ = to.X - from.X;
                for (int i = 1; i < maxZ; i++)
                {
                    if (GetValueFromSolid(from.X, from.Y, (from.Z + sign * i)) != GetValueFromSolid(from.X, from.Y, (from.Z + sign * (i - 1))))
                    {
                        return(gridToCoordinateFactor * (i + 0.5) / maxZ);
                    }
                }
                break;
            }
            return(gridToCoordinateFactor);
        }
예제 #5
0
        protected override double GetOffset(StoredValue <bool> from, StoredValue <bool> to,
                                            int direction, int sign)
        {
            switch (direction)
            {
            case 0:
                var maxX = (int)(to.X - from.X);
                for (int i = 1; i < maxX; i++)
                {
                    if (solid[(int)(from.X + sign * i), (int)from.Y, (int)from.Z] != solid[(int)(from.X + sign * (i - 1)), (int)from.Y, (int)from.Z])
                    {
                        return(gridToCoordinateFactor * (i + 0.5) / maxX);
                    }
                }
                break;

            case 1:
                var maxY = (int)(to.Y - from.Y);
                for (int i = 1; i < maxY; i++)
                {
                    if (solid[(int)from.X, (int)(from.Y + sign * i), (int)from.Z] != solid[(int)from.X, (int)(from.Y + sign * (i - 1)), (int)from.Z])
                    {
                        return(gridToCoordinateFactor * (i + 0.5) / maxY);
                    }
                }
                break;

            case 2:
                var maxZ = (int)(to.X - from.X);
                for (int i = 1; i < maxZ; i++)
                {
                    if (solid[(int)from.X, (int)from.Y, (int)(from.Z + sign * i)] != solid[(int)from.X, (int)from.Y, (int)(from.Z + sign * (i - 1))])
                    {
                        return(gridToCoordinateFactor * (i + 0.5) / maxZ);
                    }
                }
                break;
            }
            return(gridToCoordinateFactor);
        }
예제 #6
0
 protected abstract double GetOffset(StoredValue <ValueT> from, StoredValue <ValueT> to,
                                     int direction, int sign);
예제 #7
0
        /// <summary>
        /// MakeTriangles performs the Marching Cubes algorithm on a single cube
        /// </summary>
        protected void MakeFacesInCube(int xIndex, int yIndex, int zIndex)
        {
            int cubeType = 0;
            var cube     = new StoredValue <ValueT> [8];

            //Find which vertices are inside of the surface and which are outside
            for (var i = 0; i < 8; i++)
            {
                var thisX = xIndex + _unitOffsetTable[i][0];
                var thisY = yIndex + _unitOffsetTable[i][1];
                var thisZ = zIndex + _unitOffsetTable[i][2];
                var id    = getIdentifier((int)thisX, (int)thisY, (int)thisZ);
                var v     = cube[i] = GetValue((int)thisX, (int)thisY, (int)thisZ, id);
                if (IsInside(v.Value))
                {
                    cubeType |= 1 << i;
                }
            }
            //Find which edges are intersected by the surface
            int edgeFlags = CubeEdgeFlagsTable[cubeType];

            //If the cube is entirely inside or outside of the surface, then there will be no intersections
            if (edgeFlags == 0)
            {
                return;
            }
            var EdgeVertex = new Vertex[12];

            //this loop creates or retrieves the vertices that are on the edges of the
            //marching cube. These are stored in the EdgeVertexIndexTable
            for (var i = 0; i < 12; i++)
            {
                //if there is an intersection on this edge
                if ((edgeFlags & 1) != 0)
                {
                    var direction  = Math.Abs((int)directionTable[i]) - 1;
                    var sign       = directionTable[i] > 0 ? 1 : -1;
                    var fromCorner = cube[EdgeCornerIndexTable[i][0]];
                    var toCorner   = cube[EdgeCornerIndexTable[i][1]];
                    // var id = fromCorner.ID ;
                    var id = sign > 0 ? fromCorner.ID : toCorner.ID;
                    if (vertexDictionaries[direction].ContainsKey(id))
                    {
                        EdgeVertex[i] = vertexDictionaries[direction][id];
                    }
                    else
                    {
                        var coord = new Vector3(
                            _xMin + fromCorner.X * gridToCoordinateFactor,
                            _yMin + fromCorner.Y * gridToCoordinateFactor,
                            _zMin + fromCorner.Z * gridToCoordinateFactor);
                        var offSetUnitVector = (direction == 0) ? Vector3.UnitX :
                                               (direction == 1) ? Vector3.UnitY : Vector3.UnitZ;
                        double offset = GetOffset(fromCorner, toCorner, direction, sign);
                        coord         = coord + (offSetUnitVector * sign * offset);
                        EdgeVertex[i] = new Vertex(coord);
                        vertexDictionaries[direction].Add(id, EdgeVertex[i]);
                    }
                }
                edgeFlags >>= 1;
            }
            //now the triangular faces are created that connect the vertices identified above.
            //based on the les that were found. There can be up to five per cube
            var faceVertices = new Vertex[3];

            for (var i = 0; i < NumFacesTable[cubeType]; i++)
            {
                for (var j = 0; j < 3; j++)
                {
                    var vertexIndex = FaceVertexIndicesTable[cubeType][3 * i + j];
                    faceVertices[j] = EdgeVertex[vertexIndex];
                }
                faces.Add(new PolygonalFace(faceVertices));
            }
        }