示例#1
0
        // Perform signed sphere marching
        // Returns hitType 0, 1, 2, or 3 and update hit position/normal
        int RayMarching(Vector origin, Vector direction, float accuracy, out Vector hitPos, out Vector hitNorm)
        {
            float[,,] data = chacheData.GetDataDist(direction);

            hitPos  = origin;
            hitNorm = direction;
            int   hitType    = (int)HitType.HIT_NONE;
            int   noHitCount = 0;
            float d          = chacheData.FastFastQueryDatabase(hitPos, data); // distance from closest object in world.
            float prev_d;

            //bool outside = false;
            // Signed distance marching
            for (float total_d = d; total_d < 100; total_d += d)
            {
                //Vec prev = hitPos;
                hitPos = origin + direction * total_d;
                prev_d = d;
                d      = chacheData.FastFastQueryDatabase(hitPos, data);
                //if (prev_d >= accuracy + 0.01 && d < accuracy//тут было 0.01
                if (d < accuracy ||//тут было 0.01
                    ++noHitCount > 99 || d < 0)
                {
                    hitType = chacheData.FastFastQueryDatabaseHitType(hitPos);

                    if (noHitCount < 99)
                    {
                        if (hitType == (int)HitType.HIT_LETTER)
                        {
                            d       = scene.QueryDatabase(hitPos, out _);
                            hitNorm = new Vector(scene.QueryDatabase(hitPos + new Vector(.01f, 0), out _) - d,
                                                 scene.QueryDatabase(hitPos + new Vector(0, .01f), out _) - d,
                                                 scene.QueryDatabase(hitPos + new Vector(0, 0, .01f), out _) - d).Normal();

                            //hitNorm = chacheData.FastFastQueryDatabaseNorm(hitPos);
                        }
                        else
                        {
                            hitNorm = chacheData.FastFastQueryDatabaseNorm(hitPos);
                            //hitNorm = new Vec(chacheData.FastFastQueryDatabase(hitPos + new Vec(.01f, 0)) - d,
                            //  chacheData.FastFastQueryDatabase(hitPos + new Vec(0, .01f)) - d,
                            //  chacheData.FastFastQueryDatabase(hitPos + new Vec(0, 0, .01f)) - d).Normal();
                        }
                    }

                    if (float.IsNaN(hitNorm.x))
                    {
                        //hitNorm = hitNorm;
                        hitNorm = direction;
                    }

                    //hitPos = prev;
                    //hitPos = (direction%hitNorm)
                    return(hitType); // Weird return statement where a variable is also updated.
                }
            }
            return(0);
        }
示例#2
0
        public void InitData()
        {
            dataDist    = new float[cx + 1, cy + 1, cz + 1];
            dataDistPPP = new float[cx + 1, cy + 1, cz + 1];
            dataDistPPM = new float[cx + 1, cy + 1, cz + 1];
            dataDistPMP = new float[cx + 1, cy + 1, cz + 1];
            dataDistPMM = new float[cx + 1, cy + 1, cz + 1];
            dataDistMPP = new float[cx + 1, cy + 1, cz + 1];
            dataDistMPM = new float[cx + 1, cy + 1, cz + 1];
            dataDistMMP = new float[cx + 1, cy + 1, cz + 1];
            dataDistMMM = new float[cx + 1, cy + 1, cz + 1];
            dataType    = new IMaterial[cx + 1, cy + 1, cz + 1];
            dataNormal  = new Vector[cx + 1, cy + 1, cz + 1];

            float cellSizeX = (maxX - minX - 1) / cx;
            float cellSizeY = (maxY - minY - 1) / cy;
            float cellSizeZ = (maxZ - minZ - 1) / cz;

            diag = (float)Math.Sqrt(cellSizeX * cellSizeX + cellSizeY * cellSizeY + cellSizeZ * cellSizeZ);

            for (int i = 0; i < cx; i++)
            {
                for (int j = 0; j < cy + 1; j++)
                {
                    for (int k = 0; k < cz + 1; k++)
                    {
                        float worldX = minX + i * (maxX - minX - 1) / cx;
                        float worldY = minY + j * (maxY - minY - 1) / cy;
                        float worldZ = minZ + k * (maxZ - minZ - 1) / cz;

                        Vector hitPos = new Vector(worldX, worldY, worldZ);
                        float  d      = scene.QueryDatabase(hitPos, out var hitObj);

                        dataDist[i, j, k]   = d;
                        dataType[i, j, k]   = hitObj.Material;
                        dataNormal[i, j, k] = scene.QueryDatabaseNorm(hitPos, d, hitObj);

                        if (float.IsNaN(dataNormal[i, j, k].x))
                        {
                            dataNormal[i, j, k] = new Vector(0, 0, 1);
                        }
                    }
                }
            }


            float diagXYZ = (float)Math.Sqrt(cellSizeX * cellSizeX + cellSizeY * cellSizeY + cellSizeZ * cellSizeZ);
            float diagXY  = (float)Math.Sqrt(cellSizeX * cellSizeX + cellSizeY * cellSizeY);
            float diagXZ  = (float)Math.Sqrt(cellSizeX * cellSizeX + cellSizeZ * cellSizeZ);
            float diagYZ  = (float)Math.Sqrt(cellSizeY * cellSizeY + cellSizeZ * cellSizeZ);

            for (int x = 1; x < cx; x++)
            {
                for (int y = 1; y < cy; y++)
                {
                    for (int z = 1; z < cz; z++)
                    {
                        float  startMin = dataDist[x, y, z];
                        Vector normal   = dataNormal[x, y, z];
                        if (startMin >= diagXYZ / 2 || (normal.x <= 0 && normal.y <= 0 && normal.z <= 0))
                        {
                            startMin = float.MaxValue;
                        }


                        dataDistMMM[x, y, z] = min(startMin,
                                                   dataDistMMM[x - 1, y, z] + cellSizeX,
                                                   dataDistMMM[x, y - 1, z] + cellSizeY,
                                                   dataDistMMM[x, y, z - 1] + cellSizeZ,
                                                   dataDistMMM[x - 1, y - 1, z] + diagXY,
                                                   dataDistMMM[x, y - 1, z - 1] + diagYZ,
                                                   dataDistMMM[x - 1, y, z - 1] + diagXZ,
                                                   dataDistMMM[x - 1, y - 1, z - 1] + diagXYZ);
                    }
                }
            }

            for (int x = 1; x < cx; x++)
            {
                for (int y = 1; y < cy; y++)
                {
                    for (int z = cz - 1; z >= 0; z--)
                    {
                        float  startMin = dataDist[x, y, z];
                        Vector normal   = dataNormal[x, y, z];
                        if (startMin >= diagXYZ / 2 || (normal.x <= 0 && normal.y <= 0 && normal.z >= 0))
                        {
                            startMin = float.MaxValue;
                        }

                        dataDistMMP[x, y, z] = min(startMin,
                                                   dataDistMMP[x - 1, y, z] + cellSizeX,
                                                   dataDistMMP[x, y - 1, z] + cellSizeY,
                                                   dataDistMMP[x, y, z + 1] + cellSizeZ,
                                                   dataDistMMP[x - 1, y - 1, z] + diagXY,
                                                   dataDistMMP[x, y - 1, z + 1] + diagYZ,
                                                   dataDistMMP[x - 1, y, z + 1] + diagXZ,
                                                   dataDistMMP[x - 1, y - 1, z + 1] + diagXYZ);
                    }
                }
            }

            for (int x = 1; x < cx; x++)
            {
                for (int y = cy - 1; y >= 0; y--)
                {
                    for (int z = 1; z < cz; z++)
                    {
                        float  startMin = dataDist[x, y, z];
                        Vector normal   = dataNormal[x, y, z];
                        if (startMin >= diagXYZ / 2 || (normal.x <= 0 && normal.y >= 0 && normal.z <= 0))
                        {
                            startMin = float.MaxValue;
                        }

                        dataDistMPM[x, y, z] = min(startMin,
                                                   dataDistMPM[x - 1, y, z] + cellSizeX,
                                                   dataDistMPM[x, y + 1, z] + cellSizeY,
                                                   dataDistMPM[x, y, z - 1] + cellSizeZ,
                                                   dataDistMPM[x - 1, y + 1, z] + diagXY,
                                                   dataDistMPM[x, y + 1, z - 1] + diagYZ,
                                                   dataDistMPM[x - 1, y, z - 1] + diagXZ,
                                                   dataDistMPM[x - 1, y + 1, z - 1] + diagXYZ);
                    }
                }
            }

            for (int x = 1; x < cx; x++)
            {
                for (int y = cy - 1; y >= 0; y--)
                {
                    for (int z = cz - 1; z >= 0; z--)
                    {
                        float  startMin = dataDist[x, y, z];
                        Vector normal   = dataNormal[x, y, z];
                        if (startMin >= diagXYZ / 2 || (normal.x <= 0 && normal.y >= 0 && normal.z >= 0))
                        {
                            startMin = float.MaxValue;
                        }

                        dataDistMPP[x, y, z] = min(startMin,
                                                   dataDistMPP[x - 1, y, z] + cellSizeX,
                                                   dataDistMPP[x, y + 1, z] + cellSizeY,
                                                   dataDistMPP[x, y, z + 1] + cellSizeZ,
                                                   dataDistMPP[x - 1, y + 1, z] + diagXY,
                                                   dataDistMPP[x, y + 1, z + 1] + diagYZ,
                                                   dataDistMPP[x - 1, y, z + 1] + diagXZ,
                                                   dataDistMPP[x - 1, y + 1, z + 1] + diagXYZ);
                    }
                }
            }

            for (int x = cx - 1; x >= 0; x--)
            {
                for (int y = 1; y < cy; y++)
                {
                    for (int z = 1; z < cz; z++)
                    {
                        float  startMin = dataDist[x, y, z];
                        Vector normal   = dataNormal[x, y, z];
                        if (startMin >= diagXYZ / 2 || (normal.x >= 0 && normal.y <= 0 && normal.z <= 0))
                        {
                            startMin = float.MaxValue;
                        }

                        dataDistPMM[x, y, z] = min(startMin,
                                                   dataDistPMM[x + 1, y, z] + cellSizeX,
                                                   dataDistPMM[x, y - 1, z] + cellSizeY,
                                                   dataDistPMM[x, y, z - 1] + cellSizeZ,
                                                   dataDistPMM[x + 1, y - 1, z] + diagXY,
                                                   dataDistPMM[x, y - 1, z - 1] + diagYZ,
                                                   dataDistPMM[x + 1, y, z - 1] + diagXZ,
                                                   dataDistPMM[x + 1, y - 1, z - 1] + diagXYZ);
                    }
                }
            }

            for (int x = cx - 1; x >= 0; x--)
            {
                for (int y = 1; y < cy; y++)
                {
                    for (int z = cz - 1; z >= 0; z--)
                    {
                        float  startMin = dataDist[x, y, z];
                        Vector normal   = dataNormal[x, y, z];
                        if (startMin >= diagXYZ / 2 || (normal.x >= 0 && normal.y <= 0 && normal.z >= 0))
                        {
                            startMin = float.MaxValue;
                        }

                        dataDistPMP[x, y, z] = min(startMin,
                                                   dataDistPMP[x + 1, y, z] + cellSizeX,
                                                   dataDistPMP[x, y - 1, z] + cellSizeY,
                                                   dataDistPMP[x, y, z + 1] + cellSizeZ,
                                                   dataDistPMP[x + 1, y - 1, z] + diagXY,
                                                   dataDistPMP[x, y - 1, z + 1] + diagYZ,
                                                   dataDistPMP[x + 1, y, z + 1] + diagXZ,
                                                   dataDistPMP[x + 1, y - 1, z + 1] + diagXYZ);
                    }
                }
            }

            for (int x = cx - 1; x >= 0; x--)
            {
                for (int y = cy - 1; y >= 0; y--)
                {
                    for (int z = 1; z < cz; z++)
                    {
                        float  startMin = dataDist[x, y, z];
                        Vector normal   = dataNormal[x, y, z];
                        if (startMin >= diagXYZ / 2 || (normal.x >= 0 && normal.y >= 0 && normal.z <= 0))
                        {
                            startMin = float.MaxValue;
                        }

                        dataDistPPM[x, y, z] = min(startMin,
                                                   dataDistPPM[x + 1, y, z] + cellSizeX,
                                                   dataDistPPM[x, y + 1, z] + cellSizeY,
                                                   dataDistPPM[x, y, z - 1] + cellSizeZ,
                                                   dataDistPPM[x + 1, y + 1, z] + diagXY,
                                                   dataDistPPM[x, y + 1, z - 1] + diagYZ,
                                                   dataDistPPM[x + 1, y, z - 1] + diagXZ,
                                                   dataDistPPM[x + 1, y + 1, z - 1] + diagXYZ);
                    }
                }
            }

            for (int x = cx - 1; x >= 0; x--)
            {
                for (int y = cy - 1; y >= 0; y--)
                {
                    for (int z = cz - 1; z >= 0; z--)
                    {
                        float  startMin = dataDist[x, y, z];
                        Vector normal   = dataNormal[x, y, z];
                        if (startMin >= diagXYZ / 2 || (normal.x >= 0 && normal.y >= 0 && normal.z >= 0))
                        {
                            startMin = float.MaxValue;
                        }

                        dataDistPPP[x, y, z] = min(startMin,
                                                   dataDistPPP[x + 1, y, z] + cellSizeX,
                                                   dataDistPPP[x, y + 1, z] + cellSizeY,
                                                   dataDistPPP[x, y, z + 1] + cellSizeZ,
                                                   dataDistPPP[x + 1, y + 1, z] + diagXY,
                                                   dataDistPPP[x, y + 1, z + 1] + diagYZ,
                                                   dataDistPPP[x + 1, y, z + 1] + diagXZ,
                                                   dataDistPPP[x + 1, y + 1, z + 1] + diagXYZ);
                    }
                }
            }
        }