/// public void Combine() { /*if (bakeGroundLightingGrass && bakeGroundLightingFoliage) { * Debug.Log ("You can not combine meshes using 2 different materials."); * return; * }*/ if (isStaticallyCombined) { return; } Component[] filters = GetComponentsInChildren(typeof(MeshFilter)); Matrix4x4 myTransform = transform.worldToLocalMatrix; Hashtable materialToMesh = new Hashtable(); for (int i = 0; i < filters.Length; i++) { MeshFilter filter = (MeshFilter)filters[i]; Renderer curRenderer = filters[i].renderer; ///// sample ground normal Vector3 objectPos = curRenderer.transform.position; RaycastHit hit1; if (Physics.Raycast(objectPos + (Vector3.up * GroundMaxDistance * 0.5f), Vector3.down, out hit1, GroundMaxDistance)) { if (debugNormals) { Debug.DrawLine(objectPos + (Vector3.up * GroundMaxDistance * 0.5f), objectPos - (GroundMaxDistance * Vector3.up * 0.5f), Color.green, 5.0f, false); if (debugNormals) { Debug.DrawLine(objectPos, objectPos + (hit1.normal), Color.red, 5.0f, false); } // is it terrain? that makes a big difference! if (UnderlayingTerrain) { Vector3 terrainPos = (hit1.point - UnderlayingTerrain.transform.position) / UnderlayingTerrain.terrainData.size.x; //Debug.Log (hit1.point.y); //Debug.Log ( UnderlayingTerrain.SampleHeight(terrainPos) + UnderlayingTerrain.transform.position.y ); //Debug.Log (hit1.transform.gameObject.name); //if ( hit1.point.y - UnderlayingTerrain.SampleHeight(terrainPos) < 1.5f && hit1.point.y - UnderlayingTerrain.SampleHeight(terrainPos) > -1.5f ) { if (hit1.transform.gameObject.name == UnderlayingTerrain.name) { if (debugNormals) { Debug.DrawLine(objectPos, objectPos + (UnderlayingTerrain.terrainData.GetInterpolatedNormal(terrainPos.x, terrainPos.z)), Color.blue, 5.0f, false); } hit1.normal = UnderlayingTerrain.terrainData.GetInterpolatedNormal(terrainPos.x, terrainPos.z); } } } } else { hit1.normal = new Vector3(0, 1, 0); if (debugNormals) { Debug.DrawLine(objectPos, objectPos + (1.0f * hit1.normal), Color.yellow, 5.0f, false); } } MeshCombineUtilityAFS.MeshInstance instance = new MeshCombineUtilityAFS.MeshInstance(); instance.mesh = filter.sharedMesh; instance.groundNormal = hit1.normal; instance.scale = filter.transform.localScale.x; instance.pivot = filter.transform.position; // store max height in worldspace // Bounds bounds = curRenderer.bounds; // store max height in local space // Bounds bounds = filter.sharedMesh.bounds; // instance.maxHeight = bounds.size.y; if (curRenderer != null && curRenderer.enabled && instance.mesh != null) { instance.transform = myTransform * filter.transform.localToWorldMatrix; Material[] materials = curRenderer.sharedMaterials; for (int m = 0; m < materials.Length; m++) { instance.subMeshIndex = System.Math.Min(m, instance.mesh.subMeshCount - 1); ArrayList objects = (ArrayList)materialToMesh[materials[m]]; if (objects != null) { objects.Add(instance); } else { objects = new ArrayList(); objects.Add(instance); materialToMesh.Add(materials[m], objects); } } // handle dynamic combine if (Application.isPlaying) { if (destroyChildObjectsInPlaymode) { Destroy(curRenderer.gameObject); } } else { if (destroyChildObjectsInPlaymode) { DestroyImmediate(curRenderer.gameObject); isStaticallyCombined = true; } else { #if UNITY_3_5 curRenderer.gameObject.active = false; #else curRenderer.gameObject.SetActive(false); #endif isStaticallyCombined = true; } } } } foreach (DictionaryEntry de in materialToMesh) { ArrayList elements = (ArrayList)de.Value; MeshCombineUtilityAFS.MeshInstance[] instances = (MeshCombineUtilityAFS.MeshInstance[])elements.ToArray(typeof(MeshCombineUtilityAFS.MeshInstance)); // We have a maximum of one material, so just attach the mesh to our own game object if (materialToMesh.Count == 1) { // Make sure we have a mesh filter & renderer if (GetComponent(typeof(MeshFilter)) == null) { gameObject.AddComponent(typeof(MeshFilter)); } if (!GetComponent("MeshRenderer")) { gameObject.AddComponent("MeshRenderer"); } MeshFilter filter = (MeshFilter)GetComponent(typeof(MeshFilter)); // /////// renderer.material = (Material)de.Key; //renderer.enabled = true; // check material and set up the combine script automatically bakeGroundLightingGrass = false; bakeGroundLightingFoliage = false; simplyCombine = false; string result; if (Application.isPlaying) { result = renderer.material.GetTag("RenderType", true, ""); // RenderTags are: AfsGrassModelSingleSided / AfsGrassModel / AtsFoliage if (result == "AfsGrassModel" || result == "AfsGrassModelSingleSided") { bakeGroundLightingGrass = true; } else if (result == "AtsFoliage") { // just foliage of groundlighting? if (renderer.material.HasProperty("_GroundLightingAttunation")) { bakeGroundLightingFoliage = true; } else { simplyCombine = true; } } filter.mesh = MeshCombineUtilityAFS.Combine(instances, bakeGroundLightingGrass, bakeGroundLightingFoliage, randomBrightness, randomPulse, randomBending, randomFluttering, HealthyColor, DryColor, NoiseSpread, bakeScale, simplyCombine, NoiseSpreadFoliage); } else { result = renderer.sharedMaterial.GetTag("RenderType", true, ""); // RenderTags are: AfsGrassModelSingleSided / AfsGrassModel / AtsFoliage if (result == "AfsGrassModel" || result == "AfsGrassModelSingleSided") { bakeGroundLightingGrass = true; } else if (result == "AtsFoliage") { // just foliage of groundlighting? if (renderer.sharedMaterial.HasProperty("_GroundLightingAttunation")) { bakeGroundLightingFoliage = true; } else { simplyCombine = true; } } filter.sharedMesh = MeshCombineUtilityAFS.Combine(instances, bakeGroundLightingGrass, bakeGroundLightingFoliage, randomBrightness, randomPulse, randomBending, randomFluttering, HealthyColor, DryColor, NoiseSpread, bakeScale, simplyCombine, NoiseSpreadFoliage); } //renderer.material = (Material)de.Key; renderer.enabled = true; if (CastShadows) { renderer.castShadows = true; } else { renderer.castShadows = false; } } // We have multiple materials to take care of, build one mesh / gameobject for each material // and parent it to this object else { GameObject go = new GameObject("Combined mesh"); go.transform.parent = transform; go.transform.localScale = Vector3.one; go.transform.localRotation = Quaternion.identity; go.transform.localPosition = Vector3.zero; go.AddComponent(typeof(MeshFilter)); go.AddComponent("MeshRenderer"); go.renderer.material = (Material)de.Key; go.layer = go.transform.parent.gameObject.layer; // /////// // check material and set up the combine script automatically bakeGroundLightingGrass = false; bakeGroundLightingFoliage = false; simplyCombine = false; string result; if (Application.isPlaying) { result = go.renderer.material.GetTag("RenderType", true, ""); } else { result = go.renderer.sharedMaterial.GetTag("RenderType", true, ""); } // RenderTags are: AfsGrassModelSingleSided / AfsGrassModel / AtsFoliage if (result == "AfsGrassModel" || result == "AfsGrassModelSingleSided") { bakeGroundLightingGrass = true; } else if (result == "AtsFoliage") { // just foliage of groundlighting? if (Application.isPlaying) { if (go.renderer.material.HasProperty("_GroundLightingAttunation")) { bakeGroundLightingFoliage = true; } else { simplyCombine = true; } } else { if (go.renderer.sharedMaterial.HasProperty("_GroundLightingAttunation")) { bakeGroundLightingFoliage = true; } else { simplyCombine = true; } } } // /////// MeshFilter filter = (MeshFilter)go.GetComponent(typeof(MeshFilter)); if (Application.isPlaying) { filter.mesh = MeshCombineUtilityAFS.Combine(instances, bakeGroundLightingGrass, bakeGroundLightingFoliage, randomBrightness, randomPulse, randomBending, randomFluttering, HealthyColor, DryColor, NoiseSpread, bakeScale, simplyCombine, NoiseSpreadFoliage); } else { filter.sharedMesh = MeshCombineUtilityAFS.Combine(instances, bakeGroundLightingGrass, bakeGroundLightingFoliage, randomBrightness, randomPulse, randomBending, randomFluttering, HealthyColor, DryColor, NoiseSpread, bakeScale, simplyCombine, NoiseSpreadFoliage); } } } }
public void Combine () { if (isStaticallyCombined) { return; } Component[] filters = GetComponentsInChildren(typeof(MeshFilter)); Matrix4x4 myTransform = transform.worldToLocalMatrix; Hashtable materialToMesh= new Hashtable(); for (int i=0;i<filters.Length;i++) { MeshFilter filter = (MeshFilter)filters[i]; Renderer curRenderer = filters[i].GetComponent<Renderer>(); // Sample ground normal Vector3 objectPos = curRenderer.transform.position; RaycastHit hit1; if (Physics.Raycast(objectPos + (Vector3.up * GroundMaxDistance * 0.5f), Vector3.down, out hit1, GroundMaxDistance)) { if(debugNormals) { Debug.DrawLine(objectPos + (Vector3.up * GroundMaxDistance * 0.5f), objectPos - (GroundMaxDistance * Vector3.up * 0.5f), Color.green, 5.0f, false); if(debugNormals) { Debug.DrawLine(objectPos, objectPos + (hit1.normal), Color.red, 5.0f, false); } // Is it terrain? That makes a big difference! if (UnderlayingTerrain) { Vector3 terrainPos = (hit1.point - UnderlayingTerrain.transform.position) / UnderlayingTerrain.terrainData.size.x; if (hit1.transform.gameObject.name == UnderlayingTerrain.name ){ if(debugNormals) { Debug.DrawLine(objectPos, objectPos + (UnderlayingTerrain.terrainData.GetInterpolatedNormal(terrainPos.x, terrainPos.z)), Color.blue, 5.0f, false); } hit1.normal = UnderlayingTerrain.terrainData.GetInterpolatedNormal(terrainPos.x, terrainPos.z); } } } } else { hit1.normal = new Vector3 (0,1,0); if(debugNormals) { Debug.DrawLine(objectPos, objectPos + (1.0f * hit1.normal), Color.yellow, 5.0f, false); } } MeshCombineUtilityAFS.MeshInstance instance = new MeshCombineUtilityAFS.MeshInstance (); instance.mesh = filter.sharedMesh; instance.groundNormal = hit1.normal; instance.scale = filter.transform.localScale.x; instance.pivot = filter.transform.position; // Store max height in worldspace // Bounds bounds = curRenderer.bounds; // store max height in local space // Bounds bounds = filter.sharedMesh.bounds; // instance.maxHeight = bounds.size.y; if (curRenderer != null && curRenderer.enabled && instance.mesh != null) { instance.transform = myTransform * filter.transform.localToWorldMatrix; Material[] materials = curRenderer.sharedMaterials; for (int m=0;m<materials.Length;m++) { instance.subMeshIndex = System.Math.Min(m, instance.mesh.subMeshCount - 1); ArrayList objects = (ArrayList)materialToMesh[materials[m]]; if (objects != null) { objects.Add(instance); } else { objects = new ArrayList (); objects.Add(instance); materialToMesh.Add(materials[m], objects); } } // Handle dynamic combine if (Application.isPlaying) { if (destroyChildObjectsInPlaymode) { Destroy(curRenderer.gameObject); } } else { if (destroyChildObjectsInPlaymode) { DestroyImmediate(curRenderer.gameObject); isStaticallyCombined = true; } else { #if UNITY_3_5 curRenderer.gameObject.active = false; #else curRenderer.gameObject.SetActive(false); #endif isStaticallyCombined = true; } } } } foreach (DictionaryEntry de in materialToMesh) { ArrayList elements = (ArrayList)de.Value; MeshCombineUtilityAFS.MeshInstance[] instances = (MeshCombineUtilityAFS.MeshInstance[])elements.ToArray(typeof(MeshCombineUtilityAFS.MeshInstance)); // We have a maximum of one material, so just attach the mesh to our own game object if (materialToMesh.Count == 1) { // Make sure we have a mesh filter & renderer if (GetComponent(typeof(MeshFilter)) == null) gameObject.AddComponent(typeof(MeshFilter)); if (!GetComponent("MeshRenderer")) gameObject.AddComponent<MeshRenderer>(); MeshFilter filter = (MeshFilter)GetComponent(typeof(MeshFilter)); GetComponent<Renderer>().material = (Material)de.Key; // Check material and set up the combine script automatically bakeGroundLightingGrass = false; bakeGroundLightingFoliage = false; simplyCombine = false; string result; if (Application.isPlaying) { result = GetComponent<Renderer>().material.GetTag("AfsMode", true, ""); // RenderTags are: AfsGrassModelSingleSided / AfsGrassModel / AtsFoliage if (result == "Grass" || result == "AfsGrassModelSingleSided" ) { bakeGroundLightingGrass = true; } else if (result == "Foliage") { // Just foliage of groundlighting? if (GetComponent<Renderer>().material.HasProperty("_GroundLightingAttunation")) { bakeGroundLightingFoliage = true; } else { simplyCombine = true; } if (GetComponent<Renderer>().material.GetFloat("_BendingControls") == 1.0f) { useUV4 = true; } } filter.mesh = MeshCombineUtilityAFS.Combine(instances, bakeGroundLightingGrass, bakeGroundLightingFoliage, randomBrightness, randomPulse, randomBending, randomFluttering, HealthyColor, DryColor, NoiseSpread, bakeScale, simplyCombine, NoiseSpreadFoliage, createUniqueUV2playmode, useUV4); } else { result = GetComponent<Renderer>().sharedMaterial.GetTag("AfsMode", true, ""); // RenderTags are: AfsGrassModelSingleSided / AfsGrassModel / AtsFoliage if (result == "Grass" || result == "AfsGrassModelSingleSided" ) { bakeGroundLightingGrass = true; } else if (result == "Foliage") { // just foliage of groundlighting? if (GetComponent<Renderer>().sharedMaterial.HasProperty("_GroundLightingAttunation")) { bakeGroundLightingFoliage = true; } else { simplyCombine = true; } if (GetComponent<Renderer>().material.GetFloat("_BendingControls") == 1.0f) { useUV4 = true; } } filter.sharedMesh = MeshCombineUtilityAFS.Combine(instances, bakeGroundLightingGrass, bakeGroundLightingFoliage, randomBrightness, randomPulse, randomBending, randomFluttering, HealthyColor, DryColor, NoiseSpread, bakeScale, simplyCombine, NoiseSpreadFoliage, createUniqueUV2, useUV4); } GetComponent<Renderer>().enabled = true; if (CastShadows) { GetComponent<Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; } else { GetComponent<Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; } if(UseLightprobes) { GetComponent<Renderer>().useLightProbes = true; } else { GetComponent<Renderer>().useLightProbes = false; } } // We have multiple materials to take care of, build one mesh / gameobject for each material // and parent it to this object else { GameObject go = new GameObject("Combined mesh"); go.transform.parent = transform; go.transform.localScale = Vector3.one; go.transform.localRotation = Quaternion.identity; go.transform.localPosition = Vector3.zero; go.AddComponent(typeof(MeshFilter)); go.AddComponent<MeshRenderer>(); go.GetComponent<Renderer>().material = (Material)de.Key; go.layer = go.transform.parent.gameObject.layer; // Check material and set up the combine script automatically bakeGroundLightingGrass = false; bakeGroundLightingFoliage = false; simplyCombine = false; string result; if (Application.isPlaying) { result = go.GetComponent<Renderer>().material.GetTag("AfsMode", true, ""); } else { result = go.GetComponent<Renderer>().sharedMaterial.GetTag("AfsMode", true, ""); } // RenderTags are: AfsGrassModelSingleSided / AfsGrassModel / AtsFoliage if (result == "Grass" || result == "AfsGrassModelSingleSided" ) { bakeGroundLightingGrass = true; } else if (result == "Foliage") { // Just foliage of groundlighting? if (Application.isPlaying) { if (go.GetComponent<Renderer>().material.HasProperty("_GroundLightingAttunation")) { bakeGroundLightingFoliage = true; } else { simplyCombine = true; } if (go.GetComponent<Renderer>().material.GetFloat("_BendingControls") == 1.0f) { useUV4 = true; } } else { if (go.GetComponent<Renderer>().sharedMaterial.HasProperty("_GroundLightingAttunation")) { bakeGroundLightingFoliage = true; } else { simplyCombine = true; } if (go.GetComponent<Renderer>().sharedMaterial.GetFloat("_BendingControls") == 1.0f) { useUV4 = true; } } } MeshFilter filter = (MeshFilter)go.GetComponent(typeof(MeshFilter)); if (Application.isPlaying) { filter.mesh = MeshCombineUtilityAFS.Combine(instances, bakeGroundLightingGrass, bakeGroundLightingFoliage, randomBrightness, randomPulse, randomBending, randomFluttering, HealthyColor, DryColor, NoiseSpread, bakeScale, simplyCombine, NoiseSpreadFoliage, createUniqueUV2playmode, useUV4); } else { filter.sharedMesh = MeshCombineUtilityAFS.Combine(instances, bakeGroundLightingGrass, bakeGroundLightingFoliage, randomBrightness, randomPulse, randomBending, randomFluttering, HealthyColor, DryColor, NoiseSpread, bakeScale, simplyCombine, NoiseSpreadFoliage, createUniqueUV2, useUV4); } // Copy settings if (CastShadows) { go.GetComponent<Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; } else { go.GetComponent<Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; } if(UseLightprobes) { go.GetComponent<Renderer>().useLightProbes = true; } else { go.GetComponent<Renderer>().useLightProbes = false; } } } }