public LightMap(ModelInstance mi, Mesh m) { model = mi; mesh = m; width = mesh.texels.GetLength(0); height = mesh.texels.GetLength(1); texels = new Texel[width,height]; patches = new List<Patch>(); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { texels[i,j] = new Texel(); foreach (Patch p in mesh.texels[i,j].patches) { Patch temp = new Patch(p,model.transform); texels[i,j].add(temp); patches.Add(temp); } } } name = "lm" + model.layoutName + "_" + convertToBase36(model.id) + "_0" + mesh.id; }
public static Mesh CreateCube(float size = 1.0f) { float s2 = size * 0.5f; var mesh = new Mesh(); //corners mesh.positions.Add(new Vector3(s2, s2, -s2)); //0 mesh.positions.Add(new Vector3(s2, s2, s2)); //1 mesh.positions.Add(new Vector3(-s2, s2, s2)); //2 mesh.positions.Add(new Vector3(-s2, s2, -s2)); //3 mesh.positions.Add(new Vector3(s2, -s2, -s2)); //4 mesh.positions.Add(new Vector3(-s2, -s2, -s2)); //5 mesh.positions.Add(new Vector3(-s2, -s2, s2)); //6 mesh.positions.Add(new Vector3(s2, -s2, s2)); //7 //Top Face mesh.ids.Add(0); mesh.ids.Add(1); mesh.ids.Add(2); mesh.ids.Add(0); mesh.ids.Add(2); mesh.ids.Add(3); //Bottom Face mesh.ids.Add(4); mesh.ids.Add(5); mesh.ids.Add(6); mesh.ids.Add(4); mesh.ids.Add(6); mesh.ids.Add(7); //Front Face mesh.ids.Add(1); mesh.ids.Add(7); mesh.ids.Add(6); mesh.ids.Add(1); mesh.ids.Add(6); mesh.ids.Add(2); //Back Face mesh.ids.Add(0); mesh.ids.Add(3); mesh.ids.Add(5); mesh.ids.Add(0); mesh.ids.Add(5); mesh.ids.Add(4); //Left face mesh.ids.Add(2); mesh.ids.Add(6); mesh.ids.Add(5); mesh.ids.Add(2); mesh.ids.Add(5); mesh.ids.Add(3); //Right face mesh.ids.Add(1); mesh.ids.Add(0); mesh.ids.Add(4); mesh.ids.Add(1); mesh.ids.Add(4); mesh.ids.Add(7); return mesh.SwitchTriangleMeshWinding(); }
/**Initializes the tunnel initial polyline, returning the corresponding mesh and setting it as the actual one**/ protected Geometry.Mesh initializeTunnel(ref Polyline iniPol) { ((InitialPolyline)iniPol).initializeIndices(); //Create the new mesh with the hole polyline Geometry.Mesh m = new Geometry.Mesh(iniPol); proceduralMeshes.Add(m); actualMesh = m; return(m); }
//Currently mesh chunks dont store texture ids in triangles, need to do that if textures are needed public Model toModel() { Mesh[] meshes = new Mesh[chunks.Length]; for (int i = 0; i < meshes.Length; i++) { meshes[i] = new Mesh(chunks[i].name, chunks[i].tris, chunks[i].receives, chunks[i].casts, chunks[i].chunkOffset, chunks[i].chunkRotation, chunks[i].id); } return new Model(name, meshes); }
public static Mesh Clone(this Mesh m) { var mesh = new Mesh(); mesh.positions.AddRange(m.positions); mesh.normals.AddRange(m.normals); mesh.uvs.AddRange(m.uvs); mesh.ids.AddRange(m.ids); return mesh; }
private static VAO CreateMesh(Shader shader) { Mesh mesh = new Mesh(); mesh.Add(Meshes.CreateSphere(.9f)); mesh.Add(Obj2Mesh.FromObj(Resourcen.suzanne)); var vao = new VAO(); vao.SetAttribute(shader.GetAttributeLocation("position"), mesh.positions.ToArray(), VertexAttribPointerType.Float, 3); vao.SetAttribute(shader.GetAttributeLocation("normal"), mesh.normals.ToArray(), VertexAttribPointerType.Float, 3); vao.SetID(mesh.ids.ToArray(), PrimitiveType.Triangles); return vao; }
public static void Add(this Mesh a, Mesh b) { var count = (uint)a.positions.Count; a.positions.AddRange(b.positions); a.normals.AddRange(b.normals); a.uvs.AddRange(b.uvs); foreach(var id in b.ids) { a.ids.Add(id + count); } }
/**Transforms Geometry mesh into Unity mesh **/ private UnityEngine.Mesh getUnityMesh(Geometry.Mesh m, bool finished) { //Generation finished, assign the vertices and triangles created to a Unity mesh UnityEngine.Mesh mesh = new UnityEngine.Mesh(); mesh.SetVertices(m.getVertices()); mesh.SetTriangles(m.getTriangles(), 0); mesh.SetUVs(0, m.getUVs()); //TODO: http://schemingdeveloper.com/2014/10/17/better-method-recalculate-normals-unity/ mesh.RecalculateNormals(); if (finished) { mesh.RecalculateBounds(); } return(mesh); }
public Model(String name, Mesh[] mesh) { _name = name; _meshes = mesh; foreach (Mesh m in mesh) { if (m.isLightmapped) { isLightmapped = true; break; } } foreach (Mesh m in mesh) { if (m.castsShadows) { castsShadows = true; break; } } }
public override IEnumerator generate(Polyline originPoly, float holeProb) { //Hole is done, update the counter --maxHoles; //Case base is implicit, as the operation generation takes into account the maxHoles variables in order to stop generating holes if (showGeneration) { //New hole, wait a bit to see the change gameObject.GetComponent <CaveGenerator> ().updateActualPolyline(originPoly.calculateBaricenter(), originPoly.calculateNormal()); yield return(new WaitForSeconds(holeTime)); } //TODO: change maxExtrudeTimes as holes are done (eg, random number between a rank) //Generate the actual hallway/tunnel Geometry.Mesh m = initializeTunnel(ref originPoly); ExtrusionOperations actualOperation = DecisionGenerator.Instance.generateNewOperation(originPoly); //Add initial polyline to the BB IntersectionsController.Instance.addPolyline(originPoly); for (int i = 0; i < maxExtrudeTimes; ++i) { //In case the hole is finally not done, same operation will need to be applied ExtrusionOperations actualOpBackTrack = new ExtrusionOperations(actualOperation); //Generate the new polyline applying the corresponding operation Polyline newPoly = extrude(actualOperation, originPoly); if (newPoly == null) //Intersection produced //TODO: improve this //DecisionGenerator.Instance.generateNextOperation(originPoly, ref actualOperation,i,holeProb); //actualOperation = DecisionGenerator.Instance.generateNewOperation (originPoly); { continue; } //Make hole? if (actualOperation.holeOperation()) { Polyline polyHole = makeHole(originPoly, newPoly); if (polyHole != null) //Check the hole was done without problems { IntersectionsController.Instance.addPolyline(newPoly); IntersectionsController.Instance.addActualBox(); actualOperation.setCanIntersect(IntersectionsController.Instance.getLastBB()); //Avoid intersection check with own extrusion BB if (showGeneration) { yield return(StartCoroutine(generate(polyHole, holeProb - 0.001f))); //Wait a bit to let the camera return the actual tunnel gameObject.GetComponent <CaveGenerator> ().updateActualPolyline(originPoly.calculateBaricenter(), originPoly.calculateNormal()); yield return(new WaitForSeconds(holeTime)); } else { StartCoroutine(generate(polyHole, holeProb - 0.001f)); } //IntersectionsController.Instance.addPolyline (originPoly); actualMesh = m; } else //No hole could be done, reextrude will smaller distance //Force to have little extrusion distance { actualOpBackTrack.distanceOperation().forceOperation(1, DecisionGenerator.Instance.generateDistance(false)); //It can't be null if with bigger extrusion distance it wasn't already: if //with bigger distance it didn't intersect, it can't intersect with a smaller one newPoly = extrude(actualOpBackTrack, originPoly); actualOperation = actualOpBackTrack; actualMesh.addPolyline(newPoly); } actualOperation.forceHoleOperation(false); } else { //Adds the new polyline to the mesh, after all the changes previously done actualMesh.addPolyline(newPoly); } //Triangulate from origin to new polyline as a tube/cave shape actualMesh.triangulatePolylines(originPoly, newPoly); //Make stalagmite? if (!actualOpBackTrack.holeOperation() && actualOperation.stalagmiteOperation().needApply()) { makeStalagmite(actualOperation.stalagmiteOperation().apply(), originPoly, newPoly); } //Make light? /*if (actualOperation.pointLightOperation().needApply()) { * actualOperation.pointLightOperation().apply(); * makePointLight(originPoly,newPoly); * }*/ //Set next operation and continue from the new polyline originPoly = newPoly; //Add actual polyline to the next intersection BB and get next operation IntersectionsController.Instance.addPolyline(originPoly); DecisionGenerator.Instance.generateNextOperation(originPoly, actualOperation, i, holeProb, maxHoles); if (showGeneration) { gameObject.GetComponent <CaveGenerator> ().updateMeshes(this); gameObject.GetComponent <CaveGenerator> ().updateActualPolyline(originPoly.calculateBaricenter(), originPoly.calculateNormal()); yield return(new WaitForSeconds(extrusionTime)); } //else do nothing } //Duplicate last polyline, in order to avoid ugly results when smoothing a closed tunnel after hole originPoly = actualMesh.duplicatePoly(originPoly); //Finally, close the actual hallway/tunnel IntersectionsController.Instance.addActualBox(); actualMesh.closePolyline(originPoly); if (m == proceduralMeshes [0]) { finished = true; gameObject.GetComponent <CaveGenerator> ().updateMeshes(this); } else if (showGeneration) { gameObject.GetComponent <CaveGenerator> ().updateMeshes(this); } }
private void NotifySlotChanged(Mesh.CNC_Turning.Machine_Stuff.ToolSet.Slot slot) { if (m_SlotChangeEvent != null) m_SlotChangeEvent.Invoke(this, slot); }
public override IEnumerator generate(Polyline originPoly, float holeProb) { createDataStructure (gatePolyline); --maxHoles; Polyline newPoly; int actualExtrusionTimes, noIntersection; noIntersection = -1; while (isDataStructureEmpty()) { //new tunnel(hole) will be done, initialize all the data //Case base is implicit, as the operation generation takes into account the maxHoles variables in order to stop generating holes initializeDataStructure(ref noIntersection, ref originPoly); Geometry.Mesh m = initializeTunnel(ref originPoly); actualExtrusionTimes = 0; ExtrusionOperations operation = DecisionGenerator.Instance.generateNewOperation (originPoly); operation.setCanIntersect (noIntersection); //Add first polyline to the intersection BB IntersectionsController.Instance.addPolyline (originPoly); if (showGeneration) { gameObject.GetComponent<CaveGenerator> ().updateMeshes (this); gameObject.GetComponent<CaveGenerator> ().updateActualPolyline(originPoly.calculateBaricenter(), originPoly.calculateNormal()); yield return new WaitForSeconds(holeTime); } //Generate the tunnel while (actualExtrusionTimes <= maxExtrudeTimes) { ++actualExtrusionTimes; //In case the hole is finally not done, same operation will need to be applied ExtrusionOperations actualOpBackTrack = new ExtrusionOperations(operation); //Generate the new polyline applying the operation newPoly = extrude (operation, originPoly); if (newPoly == null) { //DecisionGenerator.Instance.generateNextOperation (ref operation, actualExtrusionTimes, holeProb); //operation = DecisionGenerator.Instance.generateNewOperation (originPoly); continue; } //Make hole? if (operation.holeOperation ()) { noIntersection = -1; operation.setCanIntersect (noIntersection); Polyline polyHole = makeHole (originPoly, newPoly); if (polyHole != null) {//Check the hole was done without problems addElementToDataStructure (polyHole, IntersectionsController.Instance.getLastBB () + 1); --maxHoles; } else { //No hole could be done, reextrude //Force to have little extrusion distance actualOpBackTrack.distanceOperation().forceOperation(1, DecisionGenerator.Instance.generateDistance (false)); //It can't be null if with bigger extrusion distance it wasn't already: if //with bigger distance it didn't intersect, it can't intersect with a smaller one newPoly = extrude (actualOpBackTrack, originPoly); operation = actualOpBackTrack; actualMesh.addPolyline (newPoly); } operation.forceHoleOperation (false); } else { //Adds the new polyline to the mesh, after all the changes previously done actualMesh.addPolyline (newPoly); } //Triangulate from origin to new polyline as a tube/cave shape actualMesh.triangulatePolylines (originPoly, newPoly); //Make stalagmite? if (!actualOpBackTrack.holeOperation() && operation.stalagmiteOperation ().needApply()) { makeStalagmite (operation.stalagmiteOperation().apply(), originPoly, newPoly); } //Make light? /*if (operation.pointLightOperation().needApply()) { operation.pointLightOperation().apply(); makePointLight(originPoly,newPoly); }*/ //Set next operation and continue from the new polyline originPoly = newPoly; //Add actual polyline to the next intersection BB ang get nexxt operation IntersectionsController.Instance.addPolyline(originPoly); DecisionGenerator.Instance.generateNextOperation(originPoly, operation,actualExtrusionTimes,holeProb, maxHoles); if (showGeneration) { gameObject.GetComponent<CaveGenerator> ().updateMeshes (this); gameObject.GetComponent<CaveGenerator> ().updateActualPolyline(originPoly.calculateBaricenter(), originPoly.calculateNormal()); yield return new WaitForSeconds(extrusionTime); } } //Duplicate last polyline, in order to avoid ugly results when smoothing a closed tunnel after hole originPoly = actualMesh.duplicatePoly (originPoly); IntersectionsController.Instance.addActualBox (); actualMesh.closePolyline(originPoly); holeProb -= 0.001f; } finished = true; gameObject.GetComponent<CaveGenerator> ().updateMeshes (this); }
public static Mesh CreatePlane(float sizeX, float sizeZ, uint segmentsX, uint segmentsZ) { float deltaX = (1.0f / segmentsX) * sizeX; float deltaZ = (1.0f / segmentsZ) * sizeZ; Mesh m = new Mesh(); //add vertices for (uint u = 0; u < segmentsX + 1; ++u) { for (uint v = 0; v < segmentsZ + 1; ++v) { float x = -sizeX / 2.0f + u * deltaX; float z = -sizeZ / 2.0f + v * deltaZ; m.positions.Add(new Vector3(x, 0.0f, z)); } } uint verticesZ = segmentsZ + 1; //add ids for (uint u = 0; u < segmentsX; ++u) { for (uint v = 0; v < segmentsZ; ++v) { m.ids.Add(u* verticesZ + v); m.ids.Add(u* verticesZ + v + 1); m.ids.Add((u + 1) * verticesZ + v); m.ids.Add((u + 1) * verticesZ + v); m.ids.Add(u* verticesZ + v + 1); m.ids.Add((u + 1) * verticesZ + v + 1); } } return m; }
public LightMap(ModelInstance mi, Mesh m, String lightmapName) : this(mi, m) { name = lightmapName; }
private static void Subdivide(Mesh m, uint id1, uint id2, uint id3, uint depth) { if (0 == depth) { m.ids.Add(id1); m.ids.Add(id2); m.ids.Add(id3); return; } uint i12 = CreateID(m, id1, id2); uint i23 = CreateID(m, id2, id3); uint i31 = CreateID(m, id3, id1); Subdivide(m, id1, i12, i31, depth - 1); Subdivide(m, id2, i23, i12, depth - 1); Subdivide(m, id3, i31, i23, depth - 1); Subdivide(m, i12, i23, i31, depth - 1); }
private static uint CreateID(Mesh m, uint id1, uint id2) { //todo: could detect if edge already calculated and reuse.... uint i12 = (uint)m.positions.Count; Vector3 v12 = m.positions[(int)id1] + m.positions[(int)id2]; v12 /= v12.Length(); m.normals.Add(v12); m.positions.Add(v12); return i12; }
public static Mesh SwitchTriangleMeshWinding(this Mesh m) { var mesh = new Mesh(); mesh.positions.AddRange(m.positions); mesh.normals.AddRange(m.normals); mesh.uvs.AddRange(m.uvs); for (int i = 0; i < m.ids.Count; i += 3) { mesh.ids.Add(m.ids[i]); mesh.ids.Add(m.ids[i + 2]); mesh.ids.Add(m.ids[i + 1]); } return mesh; }
public static Mesh SwitchHandedness(this Mesh m) { var mesh = new Mesh(); foreach (var pos in m.positions) { var newPos = pos; newPos.Z = -newPos.Z; mesh.positions.Add(newPos); } foreach (var n in m.normals) { var newN = n; newN.Z = -newN.Z; mesh.normals.Add(newN); } mesh.uvs.AddRange(m.uvs); mesh.ids.AddRange(m.ids); return mesh; }
public static Mesh CreateSphere(float radius_ = 1.0f, uint subdivision = 1) { //idea: subdivide icosahedron const float X = 0.525731112119133606f; const float Z = 0.850650808352039932f; var vdata = new float[12,3] { { -X, 0.0f, Z}, { X, 0.0f, Z}, { -X, 0.0f, -Z }, { X, 0.0f, -Z }, { 0.0f, Z, X }, { 0.0f, Z, -X }, { 0.0f, -Z, X }, { 0.0f, -Z, -X }, { Z, X, 0.0f }, { -Z, X, 0.0f }, { Z, -X, 0.0f }, { -Z, -X, 0.0f } }; var tindices = new uint[20,3] { { 0, 4, 1 }, { 0, 9, 4 }, { 9, 5, 4 }, { 4, 5, 8 }, { 4, 8, 1 }, { 8, 10, 1 }, { 8, 3, 10 }, { 5, 3, 8 }, { 5, 2, 3 }, { 2, 7, 3 }, { 7, 10, 3 }, { 7, 6, 10 }, { 7, 11, 6 }, { 11, 0, 6 }, { 0, 1, 6 }, { 6, 1, 10 }, { 9, 0, 11 }, { 9, 11, 2 }, { 9, 2, 5 }, { 7, 2, 11 } }; Mesh mesh = new Mesh(); for (int i = 0; i < 12; ++i) { var p = new Vector3(vdata[i, 0], vdata[i, 1], vdata[i, 2]); mesh.normals.Add(p); mesh.positions.Add(p); } for (int i = 0; i < 20; ++i) { Subdivide(mesh, tindices[i, 0], tindices[i, 1], tindices[i, 2], subdivision); } //scale for (int i = 0; i < mesh.positions.Count; ++i) { mesh.positions[i] *= radius_; } return mesh.SwitchTriangleMeshWinding(); }