/**From two extrusion polylines, get the polylines that are the start of a stalgmite, with the nearest objective direction **/ protected Polyline[] getStalagmiteIni(int numStalgm, int stalgmSize, Polyline originPoly, Polyline newPoly, Vector3 objective) { InitialPolyline[] result = new InitialPolyline[numStalgm]; List <int> startIndex = new List <int>(); //Indices of the first vertices used for each polyline for (int p = 0; p < numStalgm; ++p) { InitialPolyline stalgmPoly = new InitialPolyline(stalgmSize); float stalgmAngle = float.MaxValue; float auxAngle; int finalIndex = -1; for (int i = 0; i < originPoly.getSize() - 1; ++i) { bool invalidIndex = false; int aux = 0; //Check it's vertices don't intersect with any of the stalgmites of the same extrusion for (int j = 0; j < startIndex.Count && !invalidIndex; ++j) { aux = startIndex [j]; //Check i is not any of the vertices corresponding to jth estalgmite invalidIndex = (i >= aux && i < aux + stalgmSize / 2 - 1) || (aux >= i && aux < i + stalgmSize / 2 - 1); } if (invalidIndex) { i = aux + stalgmSize / 2 - 1; //Jump the next index not corresponding to the intersected stalagmite continue; } //Construct the stalgmite polyline InitialPolyline auxPoly = new InitialPolyline(stalgmSize); for (int j = (stalgmSize / 2) - 1; j >= 0; --j) { auxPoly.addVertex(originPoly.getVertex(i + j)); } for (int j = 0; j < (stalgmSize / 2); ++j) { auxPoly.addVertex(newPoly.getVertex(i + j)); } auxAngle = Vector3.Angle(auxPoly.calculateNormal(), objective); //Get the one with minimum angle if (auxAngle < stalgmAngle) { stalgmPoly = auxPoly; stalgmAngle = auxAngle; finalIndex = i; } } //Add obtained polyline avoid intersection with another one on same extrusion startIndex.Add(finalIndex); //If angle with objective direction is very high, cancel its creation if (stalgmAngle > maxDiffAngle) { stalgmPoly = null; } //Add stalgmite initial polyline to result result[p] = stalgmPoly; } return(result); }
/** Makes a hole betwen two polylines and return this hole as a new polyline **/ protected Polyline makeHole(Polyline originPoly, Polyline destinyPoly) { //TODO: more than one hole, Make two holes on same polylines pairs can cause intersections! //could take the negate direction of the already make hole and try to do a new one // FIRST: Decide where the hole will be done, take advantatge indices // on the two polylines are at the same order (the new is kind of a projection of the old) int sizeHole; int firstIndex; //DecisionGenerator.Instance.whereToDig (originPoly.getSize(), out sizeHole, out firstIndex); DecisionGenerator.Instance.whereToDig(originPoly, out sizeHole, out firstIndex); if (sizeHole < DecisionGenerator.Instance.holeMinVertices) { return(null); } //SECOND: Create the hole polyline by marking and adding the hole vertices (from old a new polylines) InitialPolyline polyHole = new InitialPolyline(sizeHole); //Increasing order for the origin and decreasing for the destiny polyline in order to //make a correct triangulation int i = 0; while (i < sizeHole / 2) { originPoly.getVertex(firstIndex + i).setInHole(true); polyHole.addVertex(originPoly.getVertex(firstIndex + i)); ++i; } //at this point i = sizeHole / 2; while (i > 0) { --i; destinyPoly.getVertex(firstIndex + i).setInHole(true); polyHole.addVertex(destinyPoly.getVertex(firstIndex + i)); } /*//THIRD: Check is a valid hole: no artifacts will be produced, * bool invalidHole = false; * //invalidHole = Geometry.Utils.checkArtifacts (polyHole); * //and in the walking case, check if the hole is not too upwards or downwards(y component) * //invalidHole = invalidHole || Geometry.Utils.checkInvalidWalk(polyHole); * //Undo hole if invalid * if (invalidHole) { * Debug.Log ("Invalid walk"); * for (int j = 0; j < sizeHole/2; ++j) { * originPoly.getVertex (firstIndex + j).setInHole (false); * destinyPoly.getVertex (firstIndex + j).setInHole (false); * } * return null; * }*/ //FOURTH: Do the hole smooth: Project the polyline(3D) into a plane(2D) on the polyline normal direction, just n (not very big) vertices InitialPolyline planePoly = Geometry.Utils.generateProjection(polyHole, entranceSize, smoothIterations); //FIFTH: Last check if hole is really valid (intersection stuff, convex polyline and not too small check) if (planePoly.computeMinimumRadius() < planePoly.getMinRadius() || !planePoly.isConvex() || IntersectionsController.Instance.doIntersect(polyHole, planePoly, -1)) { /*if (!planePoly.isConvex ()) * Debug.Log ("Not Convex"); * else * Debug.Log ("Intersection");*/ for (int j = 0; j < sizeHole / 2; ++j) { originPoly.getVertex(firstIndex + j).setInHole(false); destinyPoly.getVertex(firstIndex + j).setInHole(false); } return(null); } //In case the hole can really be done, add the extruded polyline to the mesh // (needed for triangulate correctly between the hole and the projection) actualMesh.addPolyline(destinyPoly); //And the corresponding hole vertices for (int j = 0; j < polyHole.getSize(); ++j) { actualMesh.addHoleIndex(polyHole.getVertex(j).getIndex()); } //SIXTH: Final propoerties of the projection //Generate new UVs coordinates of the projection, from y coord of the hole (not works very well) float yCoord = (polyHole.getVertex(0).getUV().y + polyHole.getVertex(-1).getUV().y) / 2; planePoly.generateUVs(yCoord); //Duplicate the first vertex in order to have good texturization between last and first vertex planePoly.duplicateFirstVertex(); //And put the corresponding indices for (int j = 0; j < planePoly.getSize(); ++j) { planePoly.getVertex(j).setIndex(actualMesh.getNumVertices() + j); } //Add the new polyline information to the mesh actualMesh.addPolyline(planePoly); ///FINALLY: Triangulate between the hole and the projection and add the projection to the B intersections actualMesh.triangulateTunnelStart(polyHole, planePoly); IntersectionsController.Instance.addPolyline(planePoly); return(planePoly); }