예제 #1
0
    protected override void OnUpdate()
    {
        if (flag)
        {
            return;
        }

        flag = true;

        ComponentGroup planetGroup = GetComponentGroup(typeof(Planet), typeof(PlanetNoise));
        ComponentGroup dataGroup   = GetComponentGroup(typeof(PlanetSharedData));

        ComponentDataArray <Planet>                 planetArray = planetGroup.GetComponentDataArray <Planet>();
        ComponentDataArray <PlanetNoise>            noiseArray  = planetGroup.GetComponentDataArray <PlanetNoise>();
        SharedComponentDataArray <PlanetSharedData> dataArray   = dataGroup.GetSharedComponentDataArray <PlanetSharedData>();

        GameObject prefab = dataArray[0].nodePrefab;

        for (int i = 0; i < planetArray.Length; ++i)
        {
            Planet        planet = planetArray[i];
            PlanetNoise   noise  = noiseArray[i];
            HyperDistance r      = planet.radius;

            for (int n = 0; n < 20; ++n)
            {
                Entity      nodeEntity = EntityManager.Instantiate(prefab);
                TerrainNode node       = EntityManager.GetComponentData <TerrainNode>(nodeEntity);
                node.level        = 0;
                node.planetData   = planet;
                node.noiseData    = noise;
                node.built        = 0;
                node.divided      = 0;
                node.hyperDistant = 1;

                int idx = n * 3;
                node.corner1 = icoVerts[idx];
                node.corner2 = icoVerts[idx + 1];
                node.corner3 = icoVerts[idx + 2];
                EntityManager.SetComponentData(nodeEntity, node);

                HyperPosition pos = math.normalize(node.corner1 + node.corner2 + node.corner3) * r;

                PrecisePosition prspos = new PrecisePosition {
                    pos = pos.prs
                };
                EntityManager.SetComponentData(nodeEntity, prspos);

                OctantPosition octpos = new OctantPosition {
                    pos = pos.oct
                };
                EntityManager.SetComponentData(nodeEntity, octpos);
            }
        }
    }
    public static HyperDistance operator*(HyperDistance lhs, HyperDistance rhs)
    {
        float octantSize = HyperposStaticReferences.OctantSize;

        HyperDistance rhsprs = new HyperDistance {
            prs = rhs.prs, oct = 0
        };
        HyperDistance rhsoct = new HyperDistance {
            prs = 0, oct = rhs.oct
        };
        HyperDistance lhsprs = new HyperDistance {
            prs = lhs.prs, oct = 0
        };
        HyperDistance lhsoct = new HyperDistance {
            prs = 0, oct = lhs.oct
        };

        HyperDistance a        = rhsprs.prs * lhsprs;
        HyperDistance b        = rhsprs.prs * lhsoct;
        float         oct      = (rhsoct.oct * lhsprs.prs) + (rhsoct.oct * lhsoct.oct * octantSize);
        float         overflow = oct % 1f;

        oct      -= overflow;
        overflow *= octantSize;
        a.prs    += overflow;
        a.oct    += (int)oct;

        return(a + b);
        //HyperDistance a = lhs * rhs.prs;
        //int oct = a.oct + (rhs.oct * lhs.oct * (int)octantSize);
        //
        //float octF = lhs.prs * rhs.oct;
        //float overflow = octF % 1f;
        //octF -= overflow;
        //a.prs += overflow * octantSize;
        //overflow = math.floor(a.prs / octantSize);
        //a.prs -= overflow * octantSize;
        //octF += overflow;
        //
        //return new HyperDistance { prs = a.prs, oct = oct + (int)octF };
    }
예제 #3
0
    private bool InSubdivideDist(int3 camOct, float3 camPrc, int3 nodeOct, float3 nodePrc, int octDivDist, float prcDivDist)
    {
        HyperDistance dist = MathUtils.Distance(camOct, camPrc, nodeOct, nodePrc);

        return(dist.oct < octDivDist || (dist.oct == octDivDist && dist.prs < prcDivDist));
    }
예제 #4
0
        public void Execute()
        {
            Vector3[] vertices = new Vector3[nVerts];
            int[]     indices  = new int[nTris * 3];

            float dist01 = Vector3.Distance(corner0, corner1);
            float dist12 = Vector3.Distance(corner1, corner2);

            float lenAxis01 = dist01 / (rez - 1);
            float lenAxis12 = dist12 / (rez - 1);

            float3 add1 = math.normalize(corner1 - corner0) * lenAxis01;
            float3 add2 = math.normalize(corner2 - corner1) * lenAxis12;

            int vIdx = 0;

            float octantSize = HyperposStaticReferences.OctantSize;

            HyperDistance radius = node.planetData.radius;

            //if (node.hyperDistant == 1)
            //    radius = radius / new HyperDistance { prs = 0f, oct = 1 };

            for (int i = 0; i < rez; ++i)
            {
                for (int n = 0; n <= i; ++n)
                {
                    vertices[vIdx] = corner0 + add1 * i + add2 * n;
                    float3        normal   = (vertices[vIdx]).normalized;
                    float         noiseVal = GetValue(normal, node.noiseData, node.level);
                    HyperPosition vertPos  = normal * (radius + (noiseVal * node.noiseData.finalValueMultiplier));
                    //if (n == 0)
                    //    Debug.Log(MathUtils.ToString(node.planetData.radius) + "\n" +
                    //        MathUtils.ToString(noiseVal * node.noiseData.finalValueMultiplier) + "\n" +
                    //        MathUtils.ToString(node.planetData.radius + (noiseVal * node.noiseData.finalValueMultiplier)));
                    HyperPosition nodeCenter  = GetNodeCenter(node);
                    HyperPosition relativePos = vertPos - nodeCenter;
                    vertices[vIdx] = relativePos.prs + (float3)relativePos.oct * octantSize;
                    //vertices[vIdx] = normal * (node.planetData.radius + noiseVal * node.noiseData.finalValueMultiplier);
                    //vertices[vIdx] = normal * sphereRadius; //Use this line instead of above to gen a perfect sphere

                    ++vIdx;
                }
            }

            int indIdx          = 0;
            int rowStartIdx     = 1;
            int prevRowStartIdx = 0;

            for (int row = 0; row < rez - 1; ++row)
            {
                bool upright          = true;
                int  trisInRow        = 1 + row * 2;
                int  vertsInRowBottom = row + 2;

                int upTri   = 0;
                int downTri = 0;

                for (int tri = 0; tri < trisInRow; ++tri)
                {
                    if (upright)
                    {
                        indices[indIdx]     = rowStartIdx + upTri + 1;
                        indices[indIdx + 1] = rowStartIdx + upTri;
                        indices[indIdx + 2] = prevRowStartIdx + upTri;
                        ++upTri;
                    }
                    else
                    {
                        indices[indIdx]     = prevRowStartIdx + downTri + 1;
                        indices[indIdx + 1] = rowStartIdx + downTri + 1;
                        indices[indIdx + 2] = prevRowStartIdx + downTri;
                        ++downTri;
                    }

                    indIdx += 3;
                    upright = !upright;
                }

                prevRowStartIdx = rowStartIdx;
                rowStartIdx    += vertsInRowBottom;
            }

            verts.CopyFrom(vertices);
            tris.CopyFrom(indices);
        }
예제 #5
0
    protected override void OnUpdate()
    {
        for (int i = meshCreationSets.Count - 1; i >= 0; --i)
        {
            if (meshCreationSets[i].jobHandle.IsCompleted)
            {
                meshCreationSets[i].jobHandle.Complete();

                if (EntityManager.Exists(meshCreationSets[i].entity))
                {
                    Mesh mesh = new Mesh();

                    mesh.vertices  = meshCreationSets[i].verts.ToArray();
                    mesh.triangles = meshCreationSets[i].tris.ToArray();
                    mesh.RecalculateNormals();

                    HPMeshInstanceRenderer r = EntityManager.GetSharedComponentData <HPMeshInstanceRenderer>(meshCreationSets[i].entity);

                    r.mesh = mesh;

                    EntityManager.SetSharedComponentData(meshCreationSets[i].entity, r);

                    TerrainNode node = EntityManager.GetComponentData <TerrainNode>(meshCreationSets[i].entity);

                    if (node.level != 0 && EntityManager.Exists(node.parentEntity))
                    {
                        TerrainNode parentNode = EntityManager.GetComponentData <TerrainNode>(node.parentEntity);

                        if (parentNode.divided == 1)
                        {
                            ++parentNode.childrenBuilt;
                            if (parentNode.childrenBuilt == 4)
                            {
                                HPMeshInstanceRenderer parentR = EntityManager.GetSharedComponentData <HPMeshInstanceRenderer>(node.parentEntity);
                                parentR.mesh = null;
                                EntityManager.SetSharedComponentData(node.parentEntity, parentR);
                            }

                            EntityManager.SetComponentData(node.parentEntity, parentNode);
                        }
                    }
                }

                meshCreationSets[i].verts.Dispose();
                meshCreationSets[i].tris.Dispose();

                meshCreationSets.RemoveAt(i);
            }
        }



        ComponentGroup nodeGroup = GetComponentGroup(typeof(TerrainNode), typeof(HPMeshInstanceRenderer), typeof(PrecisePosition), typeof(OctantPosition));
        ComponentGroup camGroup  = GetComponentGroup(typeof(Flycam), typeof(PrecisePosition), typeof(Rotation), typeof(OctantPosition));
        ComponentGroup dataGroup = GetComponentGroup(typeof(PlanetSharedData));

        SharedComponentDataArray <PlanetSharedData> planetDataArray = dataGroup.GetSharedComponentDataArray <PlanetSharedData>();

        PlanetSharedData[] dataArray = new PlanetSharedData[planetDataArray.Length];
        for (int i = 0; i < dataArray.Length; ++i)
        {
            dataArray[i] = planetDataArray[i];
        }

        EntityArray entityTempArray = nodeGroup.GetEntityArray();

        Entity[] entityArray = new Entity[entityTempArray.Length];
        for (int i = 0; i < entityArray.Length; ++i)
        {
            entityArray[i] = entityTempArray[i];
        }

        SharedComponentDataArray <HPMeshInstanceRenderer> meshCDArray = nodeGroup.GetSharedComponentDataArray <HPMeshInstanceRenderer>();

        HPMeshInstanceRenderer[] meshArray = new HPMeshInstanceRenderer[meshCDArray.Length];
        for (int i = 0; i < meshArray.Length; ++i)
        {
            meshArray[i] = meshCDArray[i];
        }

        ComponentDataArray <TerrainNode> nodeCDArray = nodeGroup.GetComponentDataArray <TerrainNode>();

        TerrainNode[] nodeArray = new TerrainNode[nodeCDArray.Length];
        for (int i = 0; i < nodeCDArray.Length; ++i)
        {
            nodeArray[i] = nodeCDArray[i];
        }

        ComponentDataArray <PrecisePosition> nodePosArray = nodeGroup.GetComponentDataArray <PrecisePosition>();

        PrecisePosition[] posArray = new PrecisePosition[nodePosArray.Length];
        for (int i = 0; i < nodePosArray.Length; ++i)
        {
            posArray[i] = nodePosArray[i];
        }

        ComponentDataArray <OctantPosition> nodeOctArray = nodeGroup.GetComponentDataArray <OctantPosition>();

        OctantPosition[] octArray = new OctantPosition[nodePosArray.Length];
        for (int i = 0; i < nodeOctArray.Length; ++i)
        {
            octArray[i] = nodeOctArray[i];
        }

        ComponentDataArray <PrecisePosition> camPosArray = camGroup.GetComponentDataArray <PrecisePosition>();
        float3 camPos = camPosArray[0].pos;
        ComponentDataArray <OctantPosition> camOctArray = camGroup.GetComponentDataArray <OctantPosition>();
        int3 camOct = camOctArray[0].pos;

        float octantSize = HyperposStaticReferences.OctantSize;


        for (int i = 0; i < meshArray.Length; ++i)
        {
            if (nodeArray[i].built == 1 && nodeArray[i].divided == 0)
            {
                if (nodeArray[i].level < nodeArray[i].planetData.maxNodeLevels)
                {
                    float3        corner0      = nodeArray[i].corner1;
                    float3        corner1      = nodeArray[i].corner2;
                    float3        corner2      = nodeArray[i].corner3;
                    HyperDistance sphereRadius = nodeArray[i].planetData.radius;

                    HyperPosition corner0Pos = corner0 * sphereRadius;
                    HyperPosition corner1Pos = corner1 * sphereRadius;

                    HyperDistance distToSubdivide = MathUtils.Distance(corner0Pos, corner1Pos)
                                                    * (PERCENT_DIST_TO_SUBDIVIDE_AT / 100f);

                    HyperPosition centerPos = GetNodeCenter(nodeArray[i]);

                    //if (UnityEngine.Random.Range(0, 20) == 2)
                    //    Debug.Log(MathUtils.ToString(distToSubdivide) + "\n" + MathUtils.ToString(centerPos));
                    if (InSubdivideDist(camOct, camPos, centerPos.oct, centerPos.prs, distToSubdivide.oct, distToSubdivide.prs))
                    {
                        //Debug.Log(MathUtils.ToString(distToSubdivide) + "\n" + MathUtils.ToString(centerPos)
                        //    + "\n" + camOct + " " + camPos);
                        Subdivide(entityArray[i], nodeArray[i], meshArray[i], dataArray[0],
                                  distToSubdivide.prs, distToSubdivide.oct, centerPos.prs, centerPos.oct);
                    }
                }
                if (nodeArray[i].level > 0 && EntityManager.Exists(nodeArray[i].parentEntity))
                {
                    HPMeshInstanceRenderer parentR
                        = EntityManager.GetSharedComponentData <HPMeshInstanceRenderer>(nodeArray[i].parentEntity);
                    //float dist = math.distance(camPos, nodeArray[i].parentCenter);
                    //HyperDistance dist = MathUtils.Distance(camOct, camPos,
                    //    nodeArray[i].parentOctantCenter, nodeArray[i].parentPreciseCenter);

                    //if (parentR.mesh != null
                    //    && (dist.octantDist < nodeArray[i].parentOctantSubdivideDist
                    //        || (dist.octantDist == nodeArray[i].parentOctantSubdivideDist && dist.preciseDist < nodeArray[i].parentPreciseSubdivideDist)))
                    if (!InSubdivideDist(camOct, camPos, nodeArray[i].parentOctantCenter, nodeArray[i].parentPreciseCenter,
                                         nodeArray[i].parentOctantSubdivideDist, nodeArray[i].parentPreciseSubdivideDist))
                    {
                        EntityManager.DestroyEntity(entityArray[i]);
                    }
                }
            }
            else if (nodeArray[i].built == 0 && nodeArray[i].divided == 1)
            {
                float3        corner0      = nodeArray[i].corner1;
                float3        corner1      = nodeArray[i].corner2;
                float3        corner2      = nodeArray[i].corner3;
                HyperDistance sphereRadius = nodeArray[i].planetData.radius;

                HyperPosition corner0Pos = corner0 * sphereRadius;
                HyperPosition corner1Pos = corner1 * sphereRadius;

                HyperDistance distToSubdivide = MathUtils.Distance(corner0Pos, corner1Pos) * (PERCENT_DIST_TO_SUBDIVIDE_AT / 100f);
                HyperPosition centerPos       = GetNodeCenter(nodeArray[i]);

                if (!InSubdivideDist(camOct, camPos, centerPos.oct, centerPos.prs, distToSubdivide.oct, distToSubdivide.prs))
                {
                    nodeArray[i].divided       = 0;
                    nodeArray[i].childrenBuilt = 0;
                    EntityManager.SetComponentData(entityArray[i], nodeArray[i]);
                }
            }
            else if (nodeArray[i].built == 0 && nodeArray[i].divided == 0)
            {
                nodeArray[i].built = 1;

                Planet planetData = nodeArray[i].planetData;

                // rez is the number of vertices on one side of the mesh/triangle
                // the part in parentheses is called the "Mersenne Number"
                int rez = 2 + ((int)Mathf.Pow(2, planetData.meshSubdivisions) - 1);
                // nTris is the number of tris in the mesh
                int t     = rez - 2;
                int nTris = (t * (t + 1)) + (rez - 1);
                // nVerts is the number of vertices in the mesh
                // it is the formula for the "Triangle Sequence" of numbers
                int nVerts = (rez * (rez + 1)) / 2;

                NativeArray <Vector3> verts = new NativeArray <Vector3>(nVerts, Allocator.Persistent);
                NativeArray <int>     tris  = new NativeArray <int>(nTris * 3, Allocator.Persistent);

                HyperPosition centerPos = GetNodeCenter(nodeArray[i]);
                HyperPosition camHyp    = new HyperPosition {
                    prs = camPos, oct = camOct
                };
                HyperDistance dist = MathUtils.Distance(centerPos, camHyp);

                //if (dist > planetData.hyperdistanceThreshold)
                //{
                //    nodeArray[i].hyperDistant = 1;
                //    if(!EntityManager.HasComponent<HyperdistantMarker>(entityArray[i]))
                //        EntityManager.AddComponent(entityArray[i], typeof(HyperdistantMarker));
                //}
                //else
                //{
                //    nodeArray[i].hyperDistant = 0;
                //    if (EntityManager.HasComponent<HyperdistantMarker>(entityArray[i]))
                //        EntityManager.RemoveComponent(entityArray[i], typeof(HyperdistantMarker));
                //}

                MeshBuildJob job = new MeshBuildJob();
                job.node    = nodeArray[i];
                job.corner0 = nodeArray[i].corner3;
                job.corner1 = nodeArray[i].corner2;
                job.corner2 = nodeArray[i].corner1;
                job.rez     = rez;
                job.nTris   = nTris;
                job.nVerts  = nVerts;
                job.verts   = verts;
                job.tris    = tris;

                JobHandle handle = job.Schedule();
                JobHandle.ScheduleBatchedJobs();

                MeshCreationSet mcs = new MeshCreationSet();
                mcs.entity    = entityArray[i];
                mcs.jobHandle = handle;
                mcs.verts     = verts;
                mcs.tris      = tris;
                meshCreationSets.Add(mcs);

                EntityManager.SetComponentData(entityArray[i], nodeArray[i]);
            }
        }
    }
 public static string ToString(HyperDistance hyd)
 {
     return(hyd.oct + " : " + hyd.prs);
 }