private void AddQuad(MeshData meshData, MassiveGrassProfile profile, Element element, float density, int index) { var vOrigin = index * 4; var iOrigin = index * 6; var rand = ParkAndMiller.Get(element.index); var normalRot = Quaternion.LookRotation(element.normal); var slant = Quaternion.AngleAxis(profile.Slant * 90f * (rand - 0.5f), Vector3.right); var slantWeak = Quaternion.AngleAxis(profile.Slant * 45f * (rand - 0.5f), Vector3.right); var upRot = Quaternion.AngleAxis(360f * rand, Vector3.up); var rot = normalRot * Quaternion.AngleAxis(90f, Vector3.right) * upRot * slant; var scale = profile.Scale * (1 + 0.4f * (rand - 0.5f)); var rightVec = rot * Vector3.right; var upVec = rot * Vector3.up; var p1 = scale.x * -rightVec * 0.5f + scale.y * upVec + Vector3.up * profile.GroundOffset; var p2 = scale.x * rightVec * 0.5f + scale.y * upVec + Vector3.up * profile.GroundOffset; var p3 = scale.x * rightVec * 0.5f + Vector3.up * profile.GroundOffset; var p4 = scale.x * -rightVec * 0.5f + Vector3.up * profile.GroundOffset; var normal = element.normal; var normalBottom = element.normal; switch (profile.NormalType) { case NormalType.KeepMesh: break; case NormalType.Up: normalBottom = normal = rot * Vector3.up; break; case NormalType.Shading: normal = rot * Vector3.up; normalBottom = rot * Vector3.forward; break; default: throw new ArgumentOutOfRangeException(); } meshData.vertices[vOrigin + 0] = element.position + p1; meshData.vertices[vOrigin + 1] = element.position + p2; meshData.vertices[vOrigin + 2] = element.position + p3; meshData.vertices[vOrigin + 3] = element.position + p4; meshData.normals[vOrigin + 0] = normal; meshData.normals[vOrigin + 1] = normal; meshData.normals[vOrigin + 2] = normalBottom; meshData.normals[vOrigin + 3] = normalBottom; var attr1 = new MassiveGrassProfile.VertAttribute(density, rand, element.position, p1); var attr2 = new MassiveGrassProfile.VertAttribute(density, rand, element.position, p2); var attr3 = new MassiveGrassProfile.VertAttribute(density, rand, element.position, p3); var attr4 = new MassiveGrassProfile.VertAttribute(density, rand, element.position, p4); { var vColorR = profile.GetCustomVertexData(VertexDataType.VertexColorR, attr1); var vColorG = profile.GetCustomVertexData(VertexDataType.VertexColorG, attr1); var vColorB = profile.GetCustomVertexData(VertexDataType.VertexColorB, attr1); var vColorA = profile.GetCustomVertexData(VertexDataType.VertexColorA, attr1); meshData.colors[vOrigin + 0] = new Color(vColorR, vColorG, vColorB, vColorA); } { var vColorR = profile.GetCustomVertexData(VertexDataType.VertexColorR, attr2); var vColorG = profile.GetCustomVertexData(VertexDataType.VertexColorG, attr2); var vColorB = profile.GetCustomVertexData(VertexDataType.VertexColorB, attr2); var vColorA = profile.GetCustomVertexData(VertexDataType.VertexColorA, attr2); meshData.colors[vOrigin + 1] = new Color(vColorR, vColorG, vColorB, vColorA); } { var vColorR = profile.GetCustomVertexData(VertexDataType.VertexColorR, attr3); var vColorG = profile.GetCustomVertexData(VertexDataType.VertexColorG, attr3); var vColorB = profile.GetCustomVertexData(VertexDataType.VertexColorB, attr3); var vColorA = profile.GetCustomVertexData(VertexDataType.VertexColorA, attr3); meshData.colors[vOrigin + 2] = new Color(vColorR, vColorG, vColorB, vColorA); } { var vColorR = profile.GetCustomVertexData(VertexDataType.VertexColorR, attr4); var vColorG = profile.GetCustomVertexData(VertexDataType.VertexColorG, attr4); var vColorB = profile.GetCustomVertexData(VertexDataType.VertexColorB, attr4); var vColorA = profile.GetCustomVertexData(VertexDataType.VertexColorA, attr4); meshData.colors[vOrigin + 3] = new Color(vColorR, vColorG, vColorB, vColorA); } { var uv1Z = profile.GetCustomVertexData(VertexDataType.UV1Z, attr1); var uv1W = profile.GetCustomVertexData(VertexDataType.UV1W, attr1); meshData.uvs[vOrigin + 0] = new Vector4(0f, 1f, uv1Z, uv1W); } { var uv1Z = profile.GetCustomVertexData(VertexDataType.UV1Z, attr2); var uv1W = profile.GetCustomVertexData(VertexDataType.UV1W, attr2); meshData.uvs[vOrigin + 1] = new Vector4(1f, 1f, uv1Z, uv1W); } { var uv1Z = profile.GetCustomVertexData(VertexDataType.UV1Z, attr3); var uv1W = profile.GetCustomVertexData(VertexDataType.UV1W, attr3); meshData.uvs[vOrigin + 2] = new Vector4(1f, 0f, uv1Z, uv1W); } { var uv1Z = profile.GetCustomVertexData(VertexDataType.UV1Z, attr4); var uv1W = profile.GetCustomVertexData(VertexDataType.UV1W, attr4); meshData.uvs[vOrigin + 3] = new Vector4(0f, 0f, uv1Z, uv1W); } meshData.triangles[iOrigin + 0] = vOrigin + 0; meshData.triangles[iOrigin + 1] = vOrigin + 1; meshData.triangles[iOrigin + 2] = vOrigin + 2; meshData.triangles[iOrigin + 3] = vOrigin + 2; meshData.triangles[iOrigin + 4] = vOrigin + 3; meshData.triangles[iOrigin + 5] = vOrigin + 0; }
private void Add(MeshData meshData, MassiveGrassProfile profile, Element element, float density, int index) { var vOrigin = index * templateData.vertexCount; var iOrigin = index * templateData.indecesCount; var rand = ParkAndMiller.Get(element.index + 1000); var normalRot = Quaternion.LookRotation(element.normal); var slant = Quaternion.AngleAxis(profile.Slant * 90f * (rand - 0.5f), Vector3.right); var slantWeak = Quaternion.AngleAxis(profile.Slant * 45f * (rand - 0.5f), Vector3.right); var upRot = Quaternion.AngleAxis(360f * rand, Vector3.up); var idealRot = normalRot * Quaternion.AngleAxis(90f, Vector3.right) * upRot; var rot = idealRot * slant; // var scale = profile.Scale * (1 + 0.4f * (rand - 0.5f)); var scale = Vector3.one * (1 + 0.4f * (rand - 0.5f)); var rightVec = element.index % 2 == 0 ? rot * Vector3.right : rot * -Vector3.right; var upVec = rot * Vector3.up; for (var i = 0; i < templateData.vertexCount; i++) { var vertPos = element.position + Vector3.up * profile.GroundOffset + rot * Vector3.Scale(templateData.scaledVertices[i], scale); meshData.vertices[vOrigin + i] = vertPos; switch (profile.NormalType) { case NormalType.Up: meshData.normals[vOrigin + i] = idealRot * Vector3.up; break; default: meshData.normals[vOrigin + i] = templateData.normals[i]; break; } var uv = templateData.uvs[i]; var attr = new MassiveGrassProfile.VertAttribute(density, rand, element.position, templateData.vertices[i]); var vColorR = profile.GetCustomVertexData(VertexDataType.VertexColorR, attr); var vColorG = profile.GetCustomVertexData(VertexDataType.VertexColorG, attr); var vColorB = profile.GetCustomVertexData(VertexDataType.VertexColorB, attr); var vColorA = profile.GetCustomVertexData(VertexDataType.VertexColorA, attr); var uv1Z = profile.GetCustomVertexData(VertexDataType.UV1Z, attr); var uv1W = profile.GetCustomVertexData(VertexDataType.UV1W, attr); var color = new Color(vColorR, vColorG, vColorB, vColorA); meshData.colors[vOrigin + i] = color; meshData.uvs[vOrigin + i] = new Vector4(uv.x, uv.y, uv1Z, uv1W); } for (var i = 0; i < templateData.indecesCount; i++) { var vi = vOrigin + templateData.triangles[i]; if (vi >= vOrigin + templateData.vertexCount) { var a = 100; } meshData.triangles[iOrigin + i] = vOrigin + templateData.triangles[i]; } }
public async Task <Mesh> Build(Terrain terrain, List <Texture2D> alphaMaps, MassiveGrassProfile profile, List <Element> elements) { var terrainData = terrain.terrainData; var w = terrainData.alphamapWidth; var h = terrainData.alphamapHeight; var alphas = new float[elements.Count]; for (var i = 0; i < elements.Count; i++) { var element = elements[i]; var layers = profile.PaintTextureIndex; var alpha = 0f; foreach (var layer in layers) { var v = alphaMaps[layer].GetPixel( Mathf.RoundToInt((float)w * element.normalizedPosition.x), Mathf.RoundToInt((float)h * element.normalizedPosition.y)).a; alpha = Mathf.Max(alpha, v); } alphas[i] = alpha; } var mesh = new Mesh(); var combine = new List <CombineInstance>(); if (cache == null) { cache = Mesh.Instantiate(profile.Mesh); switch (profile.NormalType) { case NormalType.KeepMesh: break; case NormalType.Up: cache.normals = cache.normals.Select(_ => Vector3.up).ToArray(); break; case NormalType.Shading: cache.normals = cache.normals.Select((_, i) => Vector3.Slerp(cache.normals[i], Vector3.up, cache.vertices[i].y)).ToArray(); break; default: throw new ArgumentOutOfRangeException(); } } var scale = new Vector3(profile.Scale.x, profile.Scale.y, profile.Scale.x); for (var i = 0; i < elements.Count; i++) { var element = elements[i]; if (alphas[i] >= profile.AlphaMapThreshold) { var density = alphas[i]; var rand = ParkAndMiller.Get(element.index); var vColorR = profile.GetCustomVertexData(VertexDataType.VertexColorR, density, rand); var vColorG = profile.GetCustomVertexData(VertexDataType.VertexColorG, density, rand); var vColorB = profile.GetCustomVertexData(VertexDataType.VertexColorB, density, rand); var vColorA = profile.GetCustomVertexData(VertexDataType.VertexColorA, density, rand); var uv1Z = profile.GetCustomVertexData(VertexDataType.UV1Z, density, rand); var uv1W = profile.GetCustomVertexData(VertexDataType.UV1W, density, rand); var color = new Color(vColorR, vColorG, vColorB, vColorA); Quaternion normalRot = Quaternion.LookRotation(element.normal); Quaternion slant = Quaternion.AngleAxis(profile.Slant * 90f * (rand - 0.5f), Vector3.right); Quaternion upRot = Quaternion.AngleAxis(360f * rand, Vector3.up); Quaternion rot = normalRot * Quaternion.AngleAxis(90f, Vector3.right) * upRot * slant; var instance = new CombineInstance(); instance.mesh = Mesh.Instantiate(cache); instance.mesh.colors = instance.mesh.colors.Select(_ => color).ToArray(); var uvs = new List <Vector4>(); instance.mesh.GetUVs(0, uvs); instance.mesh.SetUVs(0, uvs.Select(v => new Vector4(v.x, v.y, uv1Z, uv1W)).ToList()); instance.transform = Matrix4x4.TRS( element.position + Vector3.up * profile.GroundOffset, rot, scale); combine.Add(instance); } } mesh.CombineMeshes(combine.ToArray()); return(mesh); }
private void AddQuad(MeshData meshData, MassiveGrassProfile profile, Element element, float density, int index) { var vOrigin = index * 4; var iOrigin = index * 6; var rand = ParkAndMiller.Get(element.index); Quaternion normalRot = Quaternion.LookRotation(element.normal); Quaternion slant = Quaternion.AngleAxis(profile.Slant * 90f * (rand - 0.5f), Vector3.right); Quaternion slantWeak = Quaternion.AngleAxis(profile.Slant * 45f * (rand - 0.5f), Vector3.right); Quaternion upRot = Quaternion.AngleAxis(360f * rand, Vector3.up); Quaternion rot = normalRot * Quaternion.AngleAxis(90f, Vector3.right) * upRot * slant; var scale = profile.Scale; var p1 = rot * new Vector3(-0.5f * scale.x, 1f * scale.y, 0f) + Vector3.up * profile.GroundOffset; var p2 = rot * new Vector3(0.5f * scale.x, 1f * scale.y, 0f) + Vector3.up * profile.GroundOffset; var p3 = rot * new Vector3(0.5f * scale.x, 0f, 0f) + Vector3.up * profile.GroundOffset; var p4 = rot * new Vector3(-0.5f * scale.x, 0f, 0f) + Vector3.up * profile.GroundOffset; var normal = element.normal; var normalBottom = element.normal; switch (profile.NormalType) { case NormalType.KeepMesh: break; case NormalType.Up: normalBottom = normal = rot * Vector3.up; break; case NormalType.Shading: normal = rot * Vector3.up; normalBottom = rot * Vector3.forward; break; default: throw new ArgumentOutOfRangeException(); } var vColorR = profile.GetCustomVertexData(VertexDataType.VertexColorR, density, rand); var vColorG = profile.GetCustomVertexData(VertexDataType.VertexColorG, density, rand); var vColorB = profile.GetCustomVertexData(VertexDataType.VertexColorB, density, rand); var vColorA = profile.GetCustomVertexData(VertexDataType.VertexColorA, density, rand); var uv1Z = profile.GetCustomVertexData(VertexDataType.UV1Z, density, rand); var uv1W = profile.GetCustomVertexData(VertexDataType.UV1W, density, rand); var color = new Color(vColorR, vColorG, vColorB, vColorA); meshData.vertices[vOrigin + 0] = element.position + p1; meshData.vertices[vOrigin + 1] = element.position + p2; meshData.vertices[vOrigin + 2] = element.position + p3; meshData.vertices[vOrigin + 3] = element.position + p4; meshData.normals[vOrigin + 0] = normal; meshData.normals[vOrigin + 1] = normal; meshData.normals[vOrigin + 2] = normalBottom; meshData.normals[vOrigin + 3] = normalBottom; meshData.uvs[vOrigin + 0] = new Vector4(0f, 1f, uv1Z, uv1W); meshData.uvs[vOrigin + 1] = new Vector4(1f, 1f, uv1Z, uv1W); meshData.uvs[vOrigin + 2] = new Vector4(1f, 0f, uv1Z, uv1W); meshData.uvs[vOrigin + 3] = new Vector4(0f, 0f, uv1Z, uv1W); meshData.colors[vOrigin + 0] = color; meshData.colors[vOrigin + 1] = color; meshData.colors[vOrigin + 2] = color; meshData.colors[vOrigin + 3] = color; meshData.triangles[iOrigin + 0] = vOrigin + 0; meshData.triangles[iOrigin + 1] = vOrigin + 1; meshData.triangles[iOrigin + 2] = vOrigin + 2; meshData.triangles[iOrigin + 3] = vOrigin + 2; meshData.triangles[iOrigin + 4] = vOrigin + 3; meshData.triangles[iOrigin + 5] = vOrigin + 0; }