Пример #1
0
    /**Decide which operations except from hole apply **/
    private void generateNoHoleOperation(Polyline p, ExtrusionOperations op)
    {
        //Check each different operation one by one
        int duration;

        if (op.directionOperation().needGenerate())
        {
            Vector3 newDirection = generateDirection(p);
            if (newDirection != Vector3.zero)               //Valid direction found
            {
                duration = generateFromRange(directionExtrBase, directionExtrDesv);
                op.directionOperation().forceOperation(duration, newDirection);
                op.directionOperation().setWait(duration + generateFromRange(directionKBase, directionKDesv));
                IntersectionsController.Instance.addActualBox();
                IntersectionsController.Instance.addPolyline(p);
                //op.setCanIntersect (-1);
                op.setCanIntersect(IntersectionsController.Instance.getLastBB());
            }
        }

        if (op.scaleOperation().needGenerate())
        {
            duration = generateFromRange(scaleExtrBase, scaleExtrDesv);
            op.scaleOperation().forceOperation(duration, Mathf.Pow(generateScale(), 1 / (float)duration));
            op.scaleOperation().setWait(duration + generateFromRange(scaleKBase, scaleKDesv));
        }

        if (op.rotateOperation().needGenerate())
        {
            duration = generateFromRange(rotationExtrBase, rotationExtrDesv);
            op.rotateOperation().forceOperation(duration, generateRotation() / duration);
            op.rotateOperation().setWait(duration + generateFromRange(rotationKBase, rotationKDesv));
        }

        if (op.stalagmiteOperation().needGenerate())
        {
            //TODO:Generate all types of stalagmites, add more than one stalagmite at a time
            int type = Random.Range(0, 17);
            duration = generateFromRange(stalgmExtrBase, stalgmExtrDesv);
            if (type < 7)
            {
                op.stalagmiteOperation().forceOperation(duration, ExtrusionOperations.stalgmOp.Stalagmite);
            }
            else if (type < 13)
            {
                op.stalagmiteOperation().forceOperation(duration, ExtrusionOperations.stalgmOp.Stalactite);
            }
            else
            {
                op.stalagmiteOperation().forceOperation(duration, ExtrusionOperations.stalgmOp.Pillar);
            }
            op.stalagmiteOperation().setWait(duration + generateFromRange(stalgmKBase, stalgmKDesv));
        }

        /*if (op.pointLightOperation().needGenerate()) {
         *      op.pointLightOperation().forceOperation(1,true);
         *      op.pointLightOperation().setWait(1 + generateFromRange (pointLightKBase, pointLightKDesv));
         * }*/
        //TODO: add stones, grass,...
    }
 /**Clone creator **/
 public ExtrusionOperations(ExtrusionOperations original)
 {
     distance   = new Operation <float> (original.distance);
     direction  = new LerpOperation(original.direction);
     scale      = new Operation <float> (original.scale);
     rotate     = new Operation <float> (original.rotate);
     hole       = original.hole;
     stalagmite = new Operation <stalgmOp>(original.stalagmite);
     //pointLight = new Operation<bool> (original.pointLight);
     canIntersect = original.canIntersect;
 }
Пример #3
0
    //public int pointLightKBase = 12;
    //public int pointLightKDesv = 5;

    /** Generates a new operation instance, as it was the beggining of a tunnel **/
    public ExtrusionOperations generateNewOperation(Polyline p)
    {
        ExtrusionOperations op = new ExtrusionOperations();

        op.distanceOperation().forceOperation(1, DecisionGenerator.Instance.generateDistance(false));
        op.directionOperation().forceOperation(0, p.calculateNormal(), p.calculateNormal());
        op.setCanIntersect(IntersectionsController.Instance.getLastBB());
        //op.scaleOperation().forceOperation (operationK,Mathf.Pow(2.0f,1/(float)operationK));
        //Generate extrusion wait for each operation
        op.directionOperation().setWait(generateFromRange(directionKBase, directionKDesv));
        op.scaleOperation().setWait(generateFromRange(scaleKBase, scaleKDesv));
        op.rotateOperation().setWait(generateFromRange(rotationKBase, rotationKDesv));
        op.stalagmiteOperation().setWait(generateFromRange(stalgmKBase, stalgmKDesv));
        //op.pointLightOperation ().forceOperation (1, true);
        //op.pointLightOperation().setWait (1+generateFromRange (pointLightKBase, pointLightKDesv));
        return(op);
    }
Пример #4
0
    /**It creates a new polyline from an exsiting one, applying the corresponding operations**/
    protected Polyline extrude(ExtrusionOperations operation, Polyline originPoly)
    {
        //Create the new polyline from the actual one
        Polyline newPoly   = new Polyline(originPoly.getSize());
        Vector3  direction = operation.directionOperation().apply();
        float    distance  = operation.distanceOperation().apply();
        //Generate the UVS of the new polyline from the coordinates of the original and on the same
        //same direction that the extrusion, as if it was a projection to XZ plane
        //Vector2 UVincr = new Vector2(direction.x,direction.z);
        Vector2 UVincr = new Vector2(0.0f, 1.0f);

        UVincr.Normalize();
        UVincr *= (distance / UVfactor);
        for (int i = 0; i < originPoly.getSize(); ++i)           //Generate the new vertices
        //Add vertex to polyline
        {
            newPoly.extrudeVertex(i, originPoly.getVertex(i).getPosition(), direction, distance);
            //Add the index to vertex
            newPoly.getVertex(i).setIndex(actualMesh.getNumVertices() + i);
            //Add UV
            newPoly.getVertex(i).setUV(originPoly.getVertex(i).getUV() + UVincr);
        }

        //Apply operations, if any
        if (operation.scaleOperation().needApply())
        {
            newPoly.scale(operation.scaleOperation().apply());
        }
        if (operation.rotateOperation().needApply())
        {
            newPoly.rotate(operation.rotateOperation().apply());
        }

        //Check there is no intersection
        if (IntersectionsController.Instance.doIntersect(originPoly, newPoly, operation.getCanIntersect()))
        {
            return(null);
        }

        return(newPoly);
    }
Пример #5
0
    /**Decide which operations apply to the next extrusion **/
    public void generateNextOperation(Polyline p, ExtrusionOperations op, int numExtrude, float tunnelProb, int holesCountdown)
    {
        //Change the distance always, in order to introduce more irregularity
        op.distanceOperation().forceOperation(1, generateDistance(false));
        //Decide to make hole or not
        if (!op.holeOperation())
        {
            op.forceHoleOperation(makeHole(numExtrude, tunnelProb, holesCountdown));
        }

        //Decide which operations generate and apply on next extrusions
        generateNoHoleOperation(p, op);

        //Distance for hole case
        if (op.holeOperation())
        {
            op.distanceOperation().forceOperation(1, generateDistance(true));
        }
        //TODO: Distance for stalagmite case?

        //Update the wait counter
        op.decreaseWait();
    }
	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);
	}
Пример #7
0
    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);
        }
    }