示例#1
0
 public void AddShard(int x, int z, TETerrainShardData data)
 {
     Debug.Assert(!m_shardMapping.ContainsKey(MakeKey(x, z)));
     m_shardMapping[MakeKey(x, z)] = shards.Count;
     shards.Add(data);
     data.owner  = this;
     data.shardX = x;
     data.shardZ = z;
     RecalculateMinMax();
 }
示例#2
0
    static MeshInfo CreateMeshInfo(TETerrainShardData shardData, int edgeLength, int edgeQuadCount, bool quadMesh, Vector4 uvScaleOffset, string label)
    {
        var mi = new MeshInfo();

        mi.mesh          = CreateMesh(shardData, edgeLength, edgeQuadCount, quadMesh, uvScaleOffset, label);
        mi.edgeLen       = edgeLength;
        mi.edgeQuads     = edgeQuadCount;
        mi.uvScaleOffset = uvScaleOffset;
        return(mi);
    }
示例#3
0
    static void UpdateMesh(Mesh mesh, TETerrainShardData shard, int edgeLength, int edgeQuadCount, bool quadMesh, Vector4 uvScaleOffset, bool updateHeight, bool updateNormal)
    {
        var quadEdgeLength = edgeLength / edgeQuadCount;
        var vertexCount    = edgeQuadCount + 1;
        var rcpUVScale     = 1f / (float)edgeQuadCount;

        uvScaleOffset.x *= rcpUVScale;
        uvScaleOffset.y *= rcpUVScale;

        var heightMap         = shard.heightData;
        var heightScaleOffset = new Vector2(1f, 0f);

        Vector3[] pos = updateHeight ? mesh.vertices : null;
        Vector3[] nrm = updateNormal ? mesh.normals : null;

        for (int z = 0; z < vertexCount; ++z)
        {
            for (int x = 0; x < vertexCount; ++x)
            {
                var uv = new Vector2(x * uvScaleOffset.x + uvScaleOffset.z, z * uvScaleOffset.y + uvScaleOffset.w);
                var h  = heightMap.GetPixelBilinear(uv.x, uv.y).r *heightScaleOffset.x + heightScaleOffset.y;

                if (updateNormal)
                {
                    // TODO: Optimize normal extraction
                    var hp1p0  = heightMap.GetPixelBilinear(uv.x + uvScaleOffset.x, uv.y).r *heightScaleOffset.x + heightScaleOffset.y;
                    var hm1p0  = heightMap.GetPixelBilinear(uv.x - uvScaleOffset.x, uv.y).r *heightScaleOffset.x + heightScaleOffset.y;
                    var hp0p1  = heightMap.GetPixelBilinear(uv.x, uv.y + uvScaleOffset.y).r *heightScaleOffset.x + heightScaleOffset.y;
                    var hp0m1  = heightMap.GetPixelBilinear(uv.x, uv.y - uvScaleOffset.y).r *heightScaleOffset.x + heightScaleOffset.y;
                    var normal = Vector3.Cross(
                        new Vector3(quadEdgeLength * 2f, hp1p0 - hm1p0, 0f),
                        new Vector3(0f, hp0p1 - hp0m1, -quadEdgeLength * 2f)
                        ).normalized;

                    nrm[z * vertexCount + x] = normal;
                }

                if (updateHeight)
                {
                    pos[z * vertexCount + x].y = h;
                }
            }
        }

        if (updateNormal)
        {
            mesh.normals = nrm;
        }

        if (updateHeight)
        {
            mesh.vertices = pos;
            mesh.RecalculateBounds();
        }
    }
示例#4
0
    void GenerateInstances(Vector3 focusPos, Vector3 detailCornerPos, Vector3 shardCornerPos, TETerrainShardData shardData, RenderTexture matId, ComputeBuffer meshBuffer, ComputeBuffer argBuffer)
    {
        meshBuffer.SetCounterValue(0);

        detailSpawnShader.SetBuffer(0, "meshOutput", meshBuffer);
        detailSpawnShader.SetTexture(0, "materialID", matId);
        detailSpawnShader.SetTexture(0, "noiseRG", detailNoiseRG);

        detailSpawnShader.SetVector("focusPos", focusPos);

        detailSpawnShader.SetVector("detailCornerPos", detailCornerPos);
        detailSpawnShader.SetVector("detailCellSize", Vector4.one * detailCellSize);
        detailSpawnShader.SetVector("shardCornerPos", shardCornerPos);
        detailSpawnShader.SetVector("shardSize", Vector4.one * farMeshEdgeLength);

        detailSpawnShader.SetTexture(0, "heightmap", shardData.HeightTexture);
        detailSpawnShader.SetTexture(0, "controlmap", shardData.ControlTexture);
        detailSpawnShader.SetTexture(0, "colormap", shardData.ColorTexture);

        detailSpawnShader.SetBuffer(0, "spriteTemplates", m_detailSpriteTemplatesBuffer);
        detailSpawnShader.SetBuffer(0, "detailLayers", m_detailDetailLayersBuffer);
        detailSpawnShader.SetBuffer(0, "materialOffsetCount", m_detailMaterialStartOffsetBuffer);
        detailSpawnShader.SetInt("weakTemplatesOffset", 0);

        detailSpawnShader.SetFloat("vegetationDensityScale", vegetationDensityScale);

        detailSpawnShader.Dispatch(0, detailCellSize, detailCellSize, 1);

        //argBuffer.SetData(m_args0100);
        ComputeBuffer.CopyCount(meshBuffer, argBuffer, 0);

        // Separate dispatch just to setup indirect factors :(
        detailSpawnShader.SetBuffer(1, "argBuffer", argBuffer);
        detailSpawnShader.Dispatch(1, 1, 1, 1);
    }
示例#5
0
    public Mesh GetMesh(TETerrainShardData.ElementType meshType, TETerrainShardRenderElement renderElement, TETerrainShardData shardData, int edgeLength, int edgeQuadCount, Vector4 uvScaleOffset, bool forceUpdateHeight, bool forceUpdateNormal, string label, bool isTemp)
    {
        if (isTemp)
        {
            return(CreateMesh(shardData, edgeLength, edgeQuadCount, false, uvScaleOffset, label));
        }

        MeshSet meshSet = null;

        if (!m_renderElementMeshMap.TryGetValue(renderElement.elementHash, out meshSet))
        {
            meshSet        = m_renderElementMeshMap[renderElement.elementHash] = new MeshSet();
            meshSet.meshes = new MeshInfo[3];
        }

        MeshInfo meshInfo = meshSet.meshes[(int)meshType];

        if (meshInfo != null && meshInfo.mesh)
        {
            if (meshInfo.edgeLen == edgeLength && meshInfo.edgeQuads == edgeQuadCount && meshInfo.uvScaleOffset == uvScaleOffset)
            {
                if (forceUpdateHeight || forceUpdateNormal)
                {
                    UpdateMesh(meshInfo.mesh, shardData, edgeLength, edgeQuadCount, false, uvScaleOffset, forceUpdateHeight, forceUpdateNormal);

#if UNITY_EDITOR
                    UnityEditor.EditorUtility.SetDirty(this);
#endif
                }
                return(meshInfo.mesh);
            }

            Object.DestroyImmediate(meshInfo.mesh, true);
        }

        meshInfo = meshSet.meshes[(int)meshType] = CreateMeshInfo(shardData, edgeLength, edgeQuadCount, false /*meshType != TETerrainShardData.ElementType.Far*/, uvScaleOffset, label);

#if UNITY_EDITOR
        UnityEditor.AssetDatabase.AddObjectToAsset(meshInfo.mesh, this);
        UnityEditor.EditorUtility.SetDirty(this);
#endif

        return(meshInfo.mesh);
    }
示例#6
0
    static Mesh CreateMesh(TETerrainShardData shard, int edgeLength, int edgeQuadCount, bool quadMesh, Vector4 uvScaleOffset, string label)
    {
        var quadEdgeLength = edgeLength / (float)edgeQuadCount;
        var vertexCount    = edgeQuadCount + 1;
        var rcpUVScale     = 1f / (float)edgeQuadCount;

        uvScaleOffset.x *= rcpUVScale;
        uvScaleOffset.y *= rcpUVScale;

        var heightMap         = shard.heightData;
        var heightScaleOffset = new Vector2(1f, 0f);

        var pos = new Vector3[vertexCount * vertexCount];
        var nrm = new Vector3[vertexCount * vertexCount];
        var uv0 = new Vector2[vertexCount * vertexCount];

        for (int z = 0; z < vertexCount; ++z)
        {
            for (int x = 0; x < vertexCount; ++x)
            {
                var uv = new Vector2(x * uvScaleOffset.x + uvScaleOffset.z, z * uvScaleOffset.y + uvScaleOffset.w);

                // TODO: Optimize normal extraction

                var h      = heightMap.GetPixelBilinear(uv.x, uv.y).r *heightScaleOffset.x + heightScaleOffset.y;
                var hp1p0  = heightMap.GetPixelBilinear(uv.x + uvScaleOffset.x, uv.y).r *heightScaleOffset.x + heightScaleOffset.y;
                var hm1p0  = heightMap.GetPixelBilinear(uv.x - uvScaleOffset.x, uv.y).r *heightScaleOffset.x + heightScaleOffset.y;
                var hp0p1  = heightMap.GetPixelBilinear(uv.x, uv.y + uvScaleOffset.y).r *heightScaleOffset.x + heightScaleOffset.y;
                var hp0m1  = heightMap.GetPixelBilinear(uv.x, uv.y - uvScaleOffset.y).r *heightScaleOffset.x + heightScaleOffset.y;
                var normal = Vector3.Cross(
                    new Vector3(quadEdgeLength * 2f, hp1p0 - hm1p0, 0f),
                    new Vector3(0f, hp0p1 - hp0m1, -quadEdgeLength * 2f)
                    ).normalized;

                pos[z * vertexCount + x] = new Vector3(x * quadEdgeLength, h, z * quadEdgeLength);
                nrm[z * vertexCount + x] = normal;
                uv0[z * vertexCount + x] = uv;
            }
        }

        var idx = new int[edgeQuadCount * edgeQuadCount * (quadMesh ? 4 : 6)];

        for (int z = 0, i = 0; z < edgeQuadCount; ++z)
        {
            for (int x = 0; x < edgeQuadCount; ++x)
            {
                idx[i++] = (z + 0) * vertexCount + (x + 1);
                idx[i++] = (z + 0) * vertexCount + (x + 0);

                if (quadMesh)
                {
                    idx[i++] = (z + 1) * vertexCount + (x + 0);
                    idx[i++] = (z + 1) * vertexCount + (x + 1);
                }
                else
                {
                    idx[i++] = (z + 1) * vertexCount + (x + 1);

                    idx[i++] = (z + 0) * vertexCount + (x + 0);
                    idx[i++] = (z + 1) * vertexCount + (x + 0);
                    idx[i++] = (z + 1) * vertexCount + (x + 1);
                }
            }
        }

        var m = new Mesh();

        m.name     = label;
        m.vertices = pos;
        m.normals  = nrm;
        m.uv       = uv0;
        m.SetIndices(idx, quadMesh ? MeshTopology.Quads : MeshTopology.Triangles, 0);
        return(m);
    }