Exemplo n.º 1
0
        private static WPLightmapData PrepareLightmapData(string[] lightmapPaths, GameObject[] affectedObjects, float waterLevel, float wetnessHeight, float wetnessAmount)
        {
            //Debug.Log("waterLevel: " + waterLevel);
            WPLightmapData wpLightmapData = new WPLightmapData();

            wpLightmapData.waterLevel    = waterLevel;
            wpLightmapData.wetnessHeight = wetnessHeight;
            wpLightmapData.wetnessAmount = wetnessAmount;


            wpLightmapData.lightmapFiles = new string[lightmapPaths.Length];
            for (int i = 0; i < lightmapPaths.Length; i++)
            {
                wpLightmapData.lightmapFiles[i] = lightmapPaths[i];
                //Debug.Log("Adding lightmap: " + lightmapPaths[i]);
            }

            //
            //Normal meshes
            List <WPMesh> wpMeshes = new List <WPMesh>();

            foreach (GameObject obj in affectedObjects)
            {
                Renderer rend = obj.GetComponent <Renderer>();

                if (rend == null)
                {
                    continue;
                }

                //Skip terrains for now
                Terrain terrain = obj.GetComponent <Terrain>();
                if (terrain != null)
                {
                    Debug.LogWarning("skipping terrain");
                    continue;
                }

                if (rend.lightmapIndex < 0 || rend.lightmapIndex >= LightmapSettings.lightmaps.Length)
                {
                    continue;
                }

                MeshFilter meshFilter = rend.gameObject.GetComponent <MeshFilter>();

                if (meshFilter == null)
                {
                    continue;
                }

                Mesh mesh = meshFilter.sharedMesh;

                WPMesh wpMesh = new WPMesh();

                string objName = rend.name;
                if (objName == "default")
                {
                    objName = obj.gameObject.name;
                }

                if (objName == "default")
                {
                    objName = obj.gameObject.transform.parent.gameObject.name;
                }

                if (null == mesh)
                {
                    Debug.LogError("mesh of " + objName + " is null. Skipping.");
                    continue;
                }

                wpMesh.name = objName;

                wpMesh.lightmapIndex = rend.lightmapIndex;
                wpMesh.tilingOffset  = rend.lightmapScaleOffset;

                wpMesh.localToWorldMatrix    = new Vector4[4];
                wpMesh.localToWorldMatrix[0] = obj.transform.localToWorldMatrix.GetRow(0);
                wpMesh.localToWorldMatrix[1] = obj.transform.localToWorldMatrix.GetRow(1);
                wpMesh.localToWorldMatrix[2] = obj.transform.localToWorldMatrix.GetRow(2);
                wpMesh.localToWorldMatrix[3] = obj.transform.localToWorldMatrix.GetRow(3);

                //Debug.LogWarning("1 * matrix: " + obj.transform.localToWorldMatrix.MultiplyVector(Vector3.one) );

                wpMesh.vertexCount = mesh.vertexCount;
                wpMesh.vertices    = mesh.vertices;

                if (mesh.uv2 == null)
                {
                    wpMesh.uvs = mesh.uv;
                }
                else
                {
                    if (mesh.uv2.Length <= 0)
                    {
                        wpMesh.uvs = mesh.uv;
                    }
                    else
                    {
                        wpMesh.uvs = mesh.uv2;
                    }
                }

                wpMesh.triangles = mesh.triangles;

                if (wpMesh.vertices == null)
                {
                    Debug.LogWarning("No vertices found for " + objName + ". Skipping.");
                    continue;
                }
                else
                {
                    if (wpMesh.vertices.Length <= 0)
                    {
                        Debug.LogWarning("No vertices found for " + objName + ". Skipping.");
                        continue;
                    }
                }

                if (wpMesh.uvs == null)
                {
                    Debug.LogWarning("No UVs found for " + objName + ". Skipping.");
                    continue;
                }
                else
                {
                    if (wpMesh.uvs.Length <= 0)
                    {
                        Debug.LogWarning("No UVs found for " + objName + ". Skipping.");
                        continue;
                    }
                }

                wpMeshes.Add(wpMesh);
            }

            wpLightmapData.meshes = wpMeshes.ToArray();

            //
            //Terrains meshes
            List <WPTerrainData> wpTerrains = new List <WPTerrainData>();

            foreach (GameObject obj in affectedObjects)
            {
                //break;

                Terrain terrain = obj.GetComponent <Terrain>();

                if (terrain == null)
                {
                    continue;
                }

                //Debug.LogWarning("Adding terrain");

                /*Renderer rend = obj.renderer;
                 *
                 * if (rend == null) {
                 *      Debug.LogWarning("No renderer found for the terrain.");
                 *      continue;
                 * }*/

                TerrainData terrainData = terrain.terrainData;

                //Debug.Log("terrainData.size.y: " + terrainData.size.y);

                //Debug.Log("terrain resolution: " + terrainData.heightmapResolution);

                if (terrain.lightmapIndex < 0 || terrain.lightmapIndex >= LightmapSettings.lightmaps.Length)
                {
                    continue;
                }

                string objName = obj.gameObject.name;
                if (objName == "default")
                {
                    objName = obj.gameObject.name;
                }

                if (objName == "default")
                {
                    objName = obj.gameObject.transform.parent.gameObject.name;
                }

                WPTerrainData wpTerrainData = new WPTerrainData();
                wpTerrainData.name          = objName;
                wpTerrainData.width         = terrainData.heightmapWidth;
                wpTerrainData.height        = terrainData.heightmapHeight;
                wpTerrainData.lightmapIndex = terrain.lightmapIndex;
                //wpTerrainData.tilingOffset = rend.lightmapTilingOffset;
                wpTerrainData.position = obj.transform.position;

                float[,] tempHeightmap2d = terrainData.GetHeights(0, 0, terrainData.heightmapWidth, terrainData.heightmapHeight);

                if (tempHeightmap2d == null)
                {
                    Debug.LogWarning("No heightmap found for " + objName + ". Skipping.");
                    continue;
                }
                else
                {
                    if (tempHeightmap2d.Length <= 0)
                    {
                        Debug.LogWarning("No heightmap found for " + objName + ". Skipping.");
                        continue;
                    }
                }

                //Convert the heightmap
                float[] tempHeightmap1d = new float[wpTerrainData.width * wpTerrainData.height];

                for (int x = 0; x < wpTerrainData.width; x++)
                {
                    for (int y = 0; y < wpTerrainData.height; y++)
                    {
                        tempHeightmap1d[y * wpTerrainData.width + x] = tempHeightmap2d[x, y] * terrainData.size.y;
                    }
                }

                wpTerrainData.heightmap = tempHeightmap1d;

                wpTerrains.Add(wpTerrainData);
            }

            wpLightmapData.terrains = wpTerrains.ToArray();

            return(wpLightmapData);
        }
Exemplo n.º 2
0
        public static void UpdateLightmaps(Transform _waterSurfaceTransform, string _lightmapWetnessHeightString, string _lightmapWetnessAmountString)
        {
            waterSurfaceTransform       = _waterSurfaceTransform;
            lightmapWetnessHeightString = _lightmapWetnessHeightString;
            lightmapWetnessAmountString = _lightmapWetnessAmountString;

            if (waterSurfaceTransform == null)
            {
                Debug.LogError("Please assign a water surface first.");
                return;
            }

            float wetnessHeight;
            float wetnessAmount;


            if (!float.TryParse(lightmapWetnessHeightString, out wetnessHeight))
            {
                Debug.LogError("Please enter a correct value into the 'Lightmap wetness height' field.");
                return;
            }

            if (!float.TryParse(lightmapWetnessAmountString, out wetnessAmount))
            {
                Debug.LogError("Please enter a correct value into the 'Lightmap wetness amount' field.");
                return;
            }

            if (LightmapSettings.lightmaps.Length <= 0)
            {
                Debug.LogError("No lightmaps found. Please bake lightmaps first before updating them in Water+.");
                return;
            }

            //WriteBakeSettings();
            wetnessAmount = Mathf.Clamp(wetnessAmount, 0.0f, 0.7f);


            //Debug.Log("waterHeight: " + wetnessHeight + " maxWetness: " + wetnessAmount);

            float wetnessLineY = waterSurfaceTransform.GetComponent <Renderer>().bounds.max.y + wetnessHeight;

            GameObject[] affectedObjects = BuildListOfAffectedObjects(wetnessLineY);

            string[] lightmapPaths = PrepareLightmaps(affectedObjects);

            if (null == lightmapPaths)
            {
                return;
            }

            WPLightmapData wpLightmapData = PrepareLightmapData(lightmapPaths, affectedObjects, waterSurfaceTransform.GetComponent <Renderer>().bounds.max.y, wetnessHeight, wetnessAmount);

            BakeLightmaps(wpLightmapData);


            //Debug.Log("lightmapPaths.Length: " + lightmapPaths.Length);
//			ExportLightmapsDataToXML(xmlPath, lightmapPaths, affectedObjects.ToArray(), waterSurfaceTransform.renderer.bounds.max.y, wetnessHeight, wetnessAmount);
//
//			Debug.Log("Sending lightmaps data to the external baker. xmlPath:" + xmlPath);
//

            waterSurfaceTransform.GetComponent <Renderer>().sharedMaterial.SetFloat("_refractionsWetness", 1.0f - wetnessAmount * .5f);
        }
Exemplo n.º 3
0
        private static void BakeLightmaps(WPLightmapData lightmapData)
        {
//			Debug.Log ("waterLevel: " + lightmapData.waterLevel);
//			Debug.Log ("wetnessHeight: " + lightmapData.wetnessHeight);
//			Debug.Log ("wetnessAmount: " + lightmapData.wetnessAmount);
            //
            //Load all of the lightmaps
            ImageData[] imagesData = new ImageData[lightmapData.lightmapFiles.Length];

            for (int lightmapIndex = 0; lightmapIndex < lightmapData.lightmapFiles.Length; lightmapIndex++)
            {
                bool shouldSkipFile = false;
                //Don't load non-used lightmaps
                if (lightmapData.lightmapFiles [lightmapIndex] == null)
                {
                    shouldSkipFile = true;
                }
                else if (lightmapData.lightmapFiles.Length <= 0)
                {
                    shouldSkipFile = true;
                }

                if (shouldSkipFile)
                {
                    Debug.Log("Skipping lightmap " + lightmapIndex + " because the lightmap is non-used");
                    continue;
                }

                string filePath = lightmapData.lightmapFiles [lightmapIndex];
                //string filePath = "C:/Users/Me/Desktop/Water+/iPhone4_hq_1.png";
                //string filePath = "1/LightmapFar-0.exr";
                //string filePath = "C:/Users/Me/waterplus/Assets/WaterPlus/Water_Island/LightmapFar-0.exr";
                //Debug.Log("lightmap path: " + filePath);
                imagesData [lightmapIndex] = new ImageData(filePath);

                /*for (int i = 0; i < imagesData[lightmapIndex].width * imagesData[lightmapIndex].height; i++) {
                 *      imagesData[lightmapIndex].pixels[i].r = imagesData[lightmapIndex].pixels[i].r * imagesData[lightmapIndex].pixels[i].r * .5f;
                 *      imagesData[lightmapIndex].pixels[i].g = imagesData[lightmapIndex].pixels[i].g * imagesData[lightmapIndex].pixels[i].g * 2.0f;
                 *      imagesData[lightmapIndex].pixels[i].b = imagesData[lightmapIndex].pixels[i].b * imagesData[lightmapIndex].pixels[i].b;
                 * }*/

                //Debug.Log("Successfully loaded lightmap at path " + filePath);
                //break;
            }

            //Debug.Log ("Successfully loaded lightmaps.");

            //return;

            System.DateTime bakeStartTime = System.DateTime.Now;

            //int count = 0;

            //1. Go over all pixels of the mesh
            //2. Convert UV to vertex
            //3. If the vertex is within water line, update the lightmap.
            //Debug.Log ("Updating lightmaps.");
            int bakeCount          = 0;
            int totalObjectsToBake = lightmapData.meshes.Length + lightmapData.terrains.Length;

            //
            //Regular meshes
            foreach (WPMesh obj in lightmapData.meshes)
            {
                if (obj.lightmapIndex < 0 || obj.lightmapIndex >= imagesData.Length)
                {
                    Debug.Log("skipping " + obj + " because of a wrong lightmapIndex: " + obj.lightmapIndex);
                    continue;
                }

                //Calculate object's texel size
                ImageData lightmapUsed       = imagesData [obj.lightmapIndex];
                int       lightmapResolution = lightmapUsed.width;
                Vector4   tilingOffset       = obj.tilingOffset;

                if (lightmapResolution == 0)
                {
                    Debug.Log("error: lightmapResolution == 0");
                    continue;
                }

                if (tilingOffset.x == 0)
                {
                    Debug.LogError("error: tilingOffset.x == 0");
                    continue;
                }

                float pixelSize = 1.0f / (tilingOffset.x * (float)lightmapResolution);

                //Debug.Log("tilingOffset: " + tilingOffset.ToString() + " " + lightmapResolution);

                //Console

                //Debug.Log("2");

                Vector2[] meshUVs = obj.uvs;
                if (meshUVs == null)
                {
                    Debug.Log("No UVs found for " + obj.name);
                    continue;
                }

                bakeCount++;

                //long searchIterations = ((long)(1.0f / (pixelSize * pixelSize)) * (long)obj.vertexCount);


                //Debug.Log ("baking " + obj.name + " with " + searchIterations +
                //                  " search iterations; progress: " + (100.0f * bakeCount / lightmapData.meshes.Length).ToString("0") + "%" );
                //Debug.Log ("baking " + obj.name + ". total progress: " + (100.0f * bakeCount / totalObjectsToBake).ToString("0") + "%" );

                //Debug.Log(obj.name + " at position " + obj.);
                //Debug.Log ("pixelSize: " + pixelSize + " iterations: " + (1.0f / (pixelSize * pixelSize)));


                //int verticesFound = 0;
                //int verticesNotFound = 0;
                //Iterate over all UVs in the mesh
                //float previousProgress = 0.0f;
                //int totalPixels = 0;
                //int pixelsProcessed = 0;

                int updatedPixels = 0;

                //Debug.Log("pixelSize: " + pixelSize);
                Matrix4x4 tempMatrix = new Matrix4x4();
                tempMatrix.SetRow(0, obj.localToWorldMatrix[0]);
                tempMatrix.SetRow(1, obj.localToWorldMatrix[1]);
                tempMatrix.SetRow(2, obj.localToWorldMatrix[2]);
                tempMatrix.SetRow(3, obj.localToWorldMatrix[3]);
                //Debug.Log( tempMatrix.GetRow(3) );
                //Debug.Log("1 * matrix: " + tempMatrix.MultiplyPoint(Vector3.one) );


                for (float u = 0.0f; u < 1.0f; u += pixelSize)
                {
                    //Progress for large objects
                    //if (1.0f / (pixelSize * pixelSize) >= 10000.0f) {
                    //Make sure to log only every percent, not less
//					if (u - previousProgress >= .01f) {
//						Console.Write("\r\t" + obj.name + " progress: " + (u * 100.0f).ToString("0") + "%");
//						previousProgress = u;
//					}
                    //}

                    for (float v = 0.0f; v < 1.0f; v += pixelSize)
                    {
                        //totalPixels++;

                        //Convert UV to vertex position
                        Vector2 currentUV   = new Vector2(u, v);
                        bool    vertexFound = false;
                        Vector3 vertexPos;
                        WPHelper.UVToVertex(currentUV, obj, meshUVs, out vertexFound, out vertexPos);

                        //Update the lightmap
                        //vertexFound = true;
                        if (vertexFound)
                        {
                            vertexPos = tempMatrix.MultiplyPoint(vertexPos);

                            //if (u >= .45f && u <= .55f)
                            //if (1.0f / (pixelSize * pixelSize) >= 10000.0f)
                            //	Console.Write(vertexPos.y + "\t");

                            //Debug.Log("vertexPos.y: " + vertexPos.y);
                            if (vertexPos.y <= lightmapData.waterLevel + lightmapData.wetnessHeight)
                            {
                                //Convert object's UV to lightmap's UV
                                Vector2 lightmapUV = currentUV;
                                lightmapUV.x *= tilingOffset.x;
                                lightmapUV.y *= tilingOffset.y;

                                lightmapUV.x += tilingOffset.z;
                                lightmapUV.y += tilingOffset.w;

                                int lightmapX = (int)(lightmapUV.x * (float)lightmapResolution);
                                int lightmapY = (int)(lightmapUV.y * (float)lightmapResolution);


                                if (lightmapX < 0 || lightmapX >= lightmapResolution || lightmapY < 0 || lightmapY >= lightmapResolution)
                                {
                                    //Debug.LogWarning("lightmapX: " + lightmapX + " lightmapY: " + lightmapY);
                                }
                                else
                                {
                                    //lightmapPixels[lightmapY * lightmapResolution + lightmapX] = Color.yellow;
                                    float gradientAmount = 0.0f;

                                    if (vertexPos.y <= lightmapData.waterLevel)
                                    {
                                        gradientAmount = 1.0f;
                                    }
                                    else if (vertexPos.y > lightmapData.waterLevel + lightmapData.wetnessHeight)
                                    {
                                        gradientAmount = 0.0f;
                                    }
                                    else
                                    {
                                        gradientAmount = 1.0f - (vertexPos.y - lightmapData.waterLevel) / lightmapData.wetnessHeight;
                                    }

                                    gradientAmount = 1.0f - gradientAmount * lightmapData.wetnessAmount;

                                    gradientAmount = Mathf.Clamp01(gradientAmount);                                             //Just in case

                                    lightmapUsed.dstPixels [lightmapY * lightmapResolution + lightmapX].r = lightmapUsed.srcPixels[lightmapY * lightmapResolution + lightmapX].r * gradientAmount;
                                    lightmapUsed.dstPixels [lightmapY * lightmapResolution + lightmapX].g = lightmapUsed.srcPixels[lightmapY * lightmapResolution + lightmapX].g * gradientAmount;
                                    lightmapUsed.dstPixels [lightmapY * lightmapResolution + lightmapX].b = lightmapUsed.srcPixels[lightmapY * lightmapResolution + lightmapX].b * gradientAmount;
                                    //pixelsProcessed++;

                                    updatedPixels++;

                                    //lightmapPixels [lightmapY * lightmapResolution + lightmapX].r = 1.0f;
                                    //lightmapPixels [lightmapY * lightmapResolution + lightmapX].g = 1.0f;
                                    //lightmapPixels [lightmapY * lightmapResolution + lightmapX].b = 0.0f;
                                }
                            }

                            //verticesFound++;
                        }
                    }
                }

//				Console.Write("\r\t" + obj.name + " progress:  100%");
//				Console.Write("\n");
//				Debug.Log("lowestVertexLocal: " + lowestVertexLocal + "; heighestVertexLocal: " + heighestVertexLocal +
//				                  "; lowestVertexWorld: " + lowestVertexWorld + "; heighestVertexWorld: " + heighestVertexWorld);
            }

            //
            //Terrains
            foreach (WPTerrainData obj in lightmapData.terrains)
            {
                if (obj.lightmapIndex < 0 || obj.lightmapIndex >= imagesData.Length)
                {
                    Debug.Log("skipping " + obj + " because of a wrong lightmapIndex: " + obj.lightmapIndex);
                    continue;
                }

                //Calculate object's texel size
                ImageData lightmapUsed       = imagesData [obj.lightmapIndex];
                int       lightmapResolution = lightmapUsed.width;

                if (lightmapResolution == 0)
                {
                    Debug.Log("error: lightmapResolution == 0");
                    continue;
                }

                float pixelSize = 1.0f / (float)lightmapResolution;

                bakeCount++;

//				Debug.Log ("baking " + obj.name + ". total progress: " + (100.0f * bakeCount / totalObjectsToBake).ToString("0") + "%" );

//				float previousProgress = 0.0f;

                for (float u = 0.0f; u < 1.0f; u += pixelSize)
                {
                    //Progress for large objects
                    //if (1.0f / (pixelSize * pixelSize) >= 10000.0f) {
                    //Make sure to log only every percent, not less
//					if (u - previousProgress >= .01f) {
//						Console.Write("\r\t" + obj.name + " progress: " + (u * 100.0f).ToString("0") + "%");
//						previousProgress = u;
//					}

                    for (float v = 0.0f; v < 1.0f; v += pixelSize)
                    {
                        //Update the lightmap
                        //int heightmapX = obj.width - (int)(u * (float)obj.width);
                        //int heightmapY = obj.height - (int)(v * (float)obj.height);
                        int heightmapX = (int)(v * (float)obj.height);
                        int heightmapY = (int)(u * (float)obj.width);

                        if (heightmapX < 0 || heightmapX >= obj.width || heightmapY < 0 || heightmapY >= obj.height)
                        {
                            continue;
                        }

                        int lightmapX = (int)(u * (float)lightmapResolution);
                        int lightmapY = (int)(v * (float)lightmapResolution);

                        if (lightmapX < 0 || lightmapX >= lightmapResolution || lightmapY < 0 || lightmapY >= lightmapResolution)
                        {
                            continue;
                        }

                        float yPos = obj.position.y + obj.heightmap[heightmapY * obj.height + heightmapX];

                        if (yPos <= lightmapData.waterLevel + lightmapData.wetnessHeight)
                        {
                            //if (yPos > 0)
                            //	Debug.Log("yPos: " + yPos + " waterLevel: " + lightmapData.waterLevel);

                            float gradientAmount = 0.0f;

                            if (yPos <= lightmapData.waterLevel)
                            {
                                gradientAmount = 1.0f;
                            }
                            else if (yPos > lightmapData.waterLevel + lightmapData.wetnessHeight)
                            {
                                gradientAmount = 0.0f;
                            }
                            else
                            {
                                gradientAmount = 1.0f - (yPos - lightmapData.waterLevel) / lightmapData.wetnessHeight;
                            }

                            gradientAmount = 1.0f - gradientAmount * lightmapData.wetnessAmount;

                            gradientAmount = Mathf.Clamp01(gradientAmount);                                     //Just in case

                            lightmapUsed.dstPixels [lightmapY * lightmapResolution + lightmapX].r = lightmapUsed.srcPixels[lightmapY * lightmapResolution + lightmapX].r * gradientAmount;
                            lightmapUsed.dstPixels [lightmapY * lightmapResolution + lightmapX].g = lightmapUsed.srcPixels[lightmapY * lightmapResolution + lightmapX].r * gradientAmount;
                            lightmapUsed.dstPixels [lightmapY * lightmapResolution + lightmapX].b = lightmapUsed.srcPixels[lightmapY * lightmapResolution + lightmapX].r * gradientAmount;
                        }

                        //verticesFound++;
                    }
                }
//				Console.Write("\r\t" + obj.name + " progress:  100%");
//				Console.Write("\n");
            }


            //
            //Save all the lightmaps
            for (int i = 0; i < imagesData.Length; i++)
            {
                //string newPath = AppDomain.CurrentDomain.BaseDirectory + "Lightmap_" + i + ".exr";
                //imagesData[i].Save( newPath );
                if (null == imagesData[i])
                {
                    continue;
                }

                imagesData[i].Save();
            }

            Debug.Log("Successfully updated the lightmaps in " + (System.DateTime.Now - bakeStartTime).TotalSeconds + " seconds.");
        }