public void Populate(Surface s, Transform objectTemplate) { surface = s; if(surfaceObjects != null) DestroyExistingObjects(); surfaceObjects = new List<Transform>(); GameObject objectsParent = new GameObject("Objects"); objectsParent.transform.parent = this.transform; Vector3[] vertices = surface.mesh.vertices; Vector3[] normals = surface.mesh.normals; Color[] colors = surface.mesh.colors; // colors contain planet data // r = height // g = polarity for(int i = 0; i < vertices.Length; i++) { if(colors[i].r >= minHeight && colors[i].r <= maxHeight && colors[i].g >= minPolarity && colors[i].g <= maxPolarity) { if(Random.Range(0f, 1f) < objectChance) { Transform newObject = PlacementHelper.PlaceObject(objectTemplate, objectsParent.transform, vertices[i], normals[i], scale, rotation, scaleVariation, rotationVariation); surfaceObjects.Add(newObject); } } } }
public void ApplyToSurface(Surface surface) { if(surface == null) return; //material = new Material(Shader.Find("Diffuse")); //surface.renderer.sharedMaterial = material; //surface.renderer.sharedMaterial.SetTexture("_MainTex", surface.textures[0]); if(material == null) material = new Material(shader); surface.renderer.sharedMaterial = material; /*surface.renderer.sharedMaterial.SetFloat("_Value1", value1); surface.renderer.sharedMaterial.SetFloat("_Value2", value2); surface.renderer.sharedMaterial.SetFloat("_Value3", value3); surface.renderer.sharedMaterial.SetFloat("_Brightness", brightness); surface.renderer.sharedMaterial.SetColor("_Color1", color1); surface.renderer.sharedMaterial.SetColor("_Color2", color2); surface.renderer.sharedMaterial.SetColor("_Color3", color3); surface.renderer.sharedMaterial.SetColor("_Color4", color4); if(useTextures) { surface.renderer.sharedMaterial.SetTexture("_Texture1", texture1); surface.renderer.sharedMaterial.SetTexture("_Texture2", texture2); surface.renderer.sharedMaterial.SetTexture("_Texture3", texture3); surface.renderer.sharedMaterial.SetTexture("_Texture4", texture4); surface.renderer.sharedMaterial.SetVector("_UvScale", textureScales); } if(useBumpMaps) { surface.renderer.sharedMaterial.SetTexture("_Normal1", normal1); surface.renderer.sharedMaterial.SetTexture("_Normal2", normal2); surface.renderer.sharedMaterial.SetTexture("_Normal3", normal3); surface.renderer.sharedMaterial.SetTexture("_Normal4", normal4); surface.renderer.sharedMaterial.SetVector("_NormalUvScale", normalScales); } // poles surface.renderer.sharedMaterial.SetColor("_PolarColor", polarColor); surface.renderer.sharedMaterial.SetFloat("_Polarity", polarity); surface.renderer.sharedMaterial.SetFloat("_PolarStrenght", polarStrenght); // equator surface.renderer.sharedMaterial.SetColor("_EquatorColor", equatorColor); surface.renderer.sharedMaterial.SetVector("_Equator", new Vector4(equatorWidth, equatorStrenght, equatorHeight));*/ }
/// <summary> /// Initializes the surface, called by the genetor to pass parameters /// </summary> public void Initialize(int level, Vector3 start, Vector3 end, Vector3 topRight, Vector3 bottomLeft, Planet planet, Planet.SurfacePosition sp, Surface parent, int sx, int sy) { // save reference this.planet = planet; this.surfacePosition = sp; this.parent = parent; this.subX = sx; this.subY = sy; // surface start and end points this.topleft = start; this.bottomright = end; this.topright = topRight; this.bottomleft = bottomLeft; // lod subdivision level lodLevel = level; // modifier starting point modifierStartX = 0; modifierStartY = 0; if(lodLevel == 0) { modifierResolution = planet.modifierResolution / (float)planet.subdivisions; } else { modifierResolution = parent.modifierResolution / 2f; modifierStartX += parent.modifierStartX; modifierStartY += parent.modifierStartY; } modifierStartX += subX * modifierResolution; modifierStartY += subY * modifierResolution; modifierMultiplier = modifierResolution / planet.meshResolution; // uv uvStartX = 0f; uvStartY = 0f; if(lodLevel == 0) { uvResolution = 1f / planet.subdivisions; } else { uvResolution = parent.uvResolution / 2f; uvStartX += parent.uvStartX; uvStartY += parent.uvStartY; } uvStartX += subX * uvResolution; uvStartY += subY * uvResolution; // corners subSurfaces = new List<Surface>(); if(planet.useLod) { /*topLeftCorner = SperifyPoint(topleft) * planet.radius; bottomRightCorner = SperifyPoint(bottomright) * planet.radius; middlePoint = SperifyPoint((start + end) / 2f) * planet.radius; topRightCorner = SperifyPoint(topright) * planet.radius; bottomLeftCorner = SperifyPoint(bottomleft) * planet.radius;*/ // TOP LEFT topLeftCorner = SperifyPoint(topleft); float displacement = planet.Terrain.module.GetValue(topLeftCorner); float rx = modifierStartX + 0 * modifierMultiplier; float cy = modifierStartY + 0 * modifierMultiplier; if(planet.useBicubicInterpolation) displacement += planet.GetBicubicInterpolatedModifierAt(rx, cy, surfacePosition); else displacement += planet.GetBilinearInterpolatedModifierAt(rx, cy, surfacePosition); topLeftCorner += topLeftCorner * displacement * planet.heightVariation; topLeftCorner *= planet.radius; // BOTTOM RIGHT bottomRightCorner = SperifyPoint(bottomright); displacement = planet.Terrain.module.GetValue(bottomRightCorner); rx = modifierStartX + planet.meshResolution * modifierMultiplier; cy = modifierStartY + planet.meshResolution * modifierMultiplier; if(planet.useBicubicInterpolation) displacement += planet.GetBicubicInterpolatedModifierAt(rx, cy, surfacePosition); else displacement += planet.GetBilinearInterpolatedModifierAt(rx, cy, surfacePosition); bottomRightCorner += bottomRightCorner * displacement * planet.heightVariation; bottomRightCorner *= planet.radius; // MIDDLE POINT middlePoint = SperifyPoint((start + end) / 2f); displacement = planet.Terrain.module.GetValue(middlePoint); rx = modifierStartX + (planet.meshResolution/2) * modifierMultiplier; cy = modifierStartY + (planet.meshResolution/2) * modifierMultiplier; if(planet.useBicubicInterpolation) displacement += planet.GetBicubicInterpolatedModifierAt(rx, cy, surfacePosition); else displacement += planet.GetBilinearInterpolatedModifierAt(rx, cy, surfacePosition); middlePoint += middlePoint * displacement * planet.heightVariation; middlePoint *= planet.radius; // TOP RIGHT topRightCorner = SperifyPoint(topright); displacement = planet.Terrain.module.GetValue(topRightCorner); rx = modifierStartX + planet.meshResolution * modifierMultiplier; cy = modifierStartY + 0 * modifierMultiplier; if(planet.useBicubicInterpolation) displacement += planet.GetBicubicInterpolatedModifierAt(rx, cy, surfacePosition); else displacement += planet.GetBilinearInterpolatedModifierAt(rx, cy, surfacePosition); topRightCorner += topRightCorner * displacement * planet.heightVariation; topRightCorner *= planet.radius; // BOTTOM LEFT bottomLeftCorner = SperifyPoint(bottomleft); displacement = planet.Terrain.module.GetValue(bottomLeftCorner); rx = modifierStartX + planet.meshResolution * modifierMultiplier; cy = modifierStartY + 0 * modifierMultiplier; if(planet.useBicubicInterpolation) displacement += planet.GetBicubicInterpolatedModifierAt(rx, cy, surfacePosition); else displacement += planet.GetBilinearInterpolatedModifierAt(rx, cy, surfacePosition); bottomLeftCorner += bottomLeftCorner * displacement * planet.heightVariation; bottomLeftCorner *= planet.radius; /*Transform sphere = (Transform)Resources.Load("Sphere", typeof(Transform)); Transform newSphere = (Transform)Instantiate(sphere, planet.transform.TransformPoint(topLeftCorner), Quaternion.identity); newSphere.parent = transform; newSphere = (Transform)Instantiate(sphere, bottomRightCorner, Quaternion.identity); newSphere.parent = transform; newSphere = (Transform)Instantiate(sphere, middlePoint, Quaternion.identity); newSphere.parent = transform; newSphere = (Transform)Instantiate(sphere, topRightCorner, Quaternion.identity); newSphere.parent = transform; newSphere = (Transform)Instantiate(sphere, bottomLeftCorner, Quaternion.identity); newSphere.parent = transform;*/ } // mesh if(mesh == null) { // create mesh filter MeshFilter meshFilter = (MeshFilter)gameObject.AddComponent(typeof(MeshFilter)); mesh = meshFilter.sharedMesh = new Mesh(); // create mesh renderer gameObject.AddComponent(typeof(MeshRenderer)); renderer.castShadows = true; renderer.receiveShadows = true; renderer.enabled = true; } }
/// <summary> /// Event handler called by each subsurface when completed /// </summary> private void SubsurfaceGenerationComplete(Surface s) { if(this == null) return; generatedCount++; if(generatedCount == subSurfaces.Count) { renderer.enabled = false; if(SubdivisionComplete != null) SubdivisionComplete(this); queuedForSubdivision = false; } }
/// <summary> /// Event raised by the planet when a new surface is generated. /// If enabled, adds SurfaceObjects component to the Surface and populates it with objects /// </summary> public void OnSurfaceGenerated(Surface surface) { for(int f = 0; f < foliageTypes.Length; f++) { if(surface.lodLevel == foliageTypes[f].lodLevel) { // create new list MeshInstanceList mil = new MeshInstanceList(); mil.meshInstances = new List<MeshInstance>(); // save surface reference and listen for its destruction mil.surface = surface; surface.SurfaceDestroyed += SurfaceDestroyed; // get mesh Vector3[] vertices = surface.mesh.vertices; Vector3[] normals = surface.mesh.normals; Color[] colors = surface.mesh.colors; Vector3 right = Vector3.zero; //, perpendicular = Vector3.one, normalized = Vector3.zero; //float vertexDistance = 0f; for(int i = 0; i < vertices.Length; i++) { if(i + 1 < vertices.Length) { right = vertices[i] - vertices[i+1]; //vertexDistance = right.magnitude; right.Normalize(); } if(colors[i].r >= foliageTypes[f].minHeight && colors[i].r <= foliageTypes[f].maxHeight && colors[i].g >= foliageTypes[f].minPolarity && colors[i].g <= foliageTypes[f].maxPolarity && colors[i].b >= foliageTypes[f].minSlope && colors[i].b <= foliageTypes[f].maxSlope ) { float terrainValue = terrainModule.module.GetValue(vertices[i].normalized); if(terrainValue >= foliageTypes[f].minNoiseValue && terrainValue <= foliageTypes[f].maxNoiseValue) { MeshInstance newInstance = new MeshInstance(); Vector3 vertex = planet.transform.TransformPoint(vertices[i]); Vector3 normal = planet.transform.TransformDirection(normals[i]); /*if(foliageTypes[f].positionVariation != Vector3.zero) { normalized = vertices[i].normalized; perpendicular = Vector3.Cross(right, normalized); newInstance.position += right * vertexDistance * Random.Range(-foliageTypes[f].positionVariation.x, foliageTypes[f].positionVariation.x); newInstance.position += normalized * vertexDistance * Random.Range(-foliageTypes[f].positionVariation.y, foliageTypes[f].positionVariation.y); newInstance.position += perpendicular * vertexDistance * Random.Range(-foliageTypes[f].positionVariation.z, foliageTypes[f].positionVariation.z); }*/ Quaternion adjustedRotation; if(foliageTypes[f].useGroundNormalAsUp) adjustedRotation = Quaternion.LookRotation(normal); else adjustedRotation = Quaternion.LookRotation(vertex.normalized); adjustedRotation *= Quaternion.Euler(foliageTypes[f].rotation); adjustedRotation *= Quaternion.Euler(new Vector3(Random.Range(-foliageTypes[f].rotationVariation.x, foliageTypes[f].rotationVariation.x), Random.Range(-foliageTypes[f].rotationVariation.y, foliageTypes[f].rotationVariation.y), Random.Range(-foliageTypes[f].rotationVariation.z, foliageTypes[f].rotationVariation.z))); Vector3 adjustedScale = foliageTypes[f].scale * (1f + foliageTypes[f].scaleVariation * Random.Range(0f, 1f)); newInstance.position = vertex; newInstance.scale = adjustedScale; newInstance.matrix = new Matrix4x4(); newInstance.matrix.SetTRS(newInstance.position, adjustedRotation, adjustedScale); newInstance.mesh = foliageTypes[f].mesh; newInstance.materials = foliageTypes[f].materials; newInstance.layer = foliageTypes[f].meshLayer; newInstance.castShadows = foliageTypes[f].castShadows; newInstance.receiveShadows = foliageTypes[f].receiveShadows; mil.meshInstances.Add(newInstance); } } } // add list to other lists foliageTypes[f].meshLists.Add(mil); } } }
/// <summary> /// Event raised by Surface when its being destroyed /// </summary> public void SurfaceDestroyed(Surface surface) { for(int f = 0; f < foliageTypes.Length; f++) { MeshInstanceList toBeRemoved = null; for(int i = 0; i < foliageTypes[f].meshLists.Count; i++) { if(foliageTypes[f].meshLists[i].surface == surface) { toBeRemoved = foliageTypes[f].meshLists[i]; break; } } if(toBeRemoved != null) foliageTypes[f].meshLists.Remove(toBeRemoved); } }
/// <summary> /// Event raised by the planet when a new surface is generated. /// If enabled, adds SurfaceObjects component to the Surface and populates it with objects /// </summary> public void OnSurfaceGenerated(Surface s) { if(automaticPerVertexPlacement) { if(s.lodLevel == lodLevel) { SurfaceObjects so = s.gameObject.AddComponent<SurfaceObjects>(); so.minHeight = minHeight; so.maxHeight = maxHeight; so.minPolarity = minPolarity; so.maxPolarity = maxPolarity; so.objectChance = objectChance; so.scale = scale; so.rotation = rotation; so.scaleVariation = scaleVariation; so.rotationVariation = rotationVariation; so.Populate(s, objectToPlace); surfaceObjects.Add(so); } } }