Exemple #1
0
        //Adds a new collider to the group with the given properties
        public ColliderInstance AddCollider(GeneratorProps gp)
        {
            ColliderInstance newCol = new ColliderInstance(gp);

            colliders.Add(newCol);
            SetColliderComponents(false);
            return(newCol);
        }
Exemple #2
0
        //Creates a new collider by copying an existing one
        public ColliderInstance(ColliderInstance ci)
        {
            name = ci.name;
            if (ci.colMesh != null)
            {
                colMesh = Object.Instantiate(ci.colMesh);
            }

            props = new GeneratorProps(ci.props);
        }
Exemple #3
0
 //Creates a new collider with the given properties
 public ColliderInstance(GeneratorProps gp)
 {
     if (gp != null)
     {
         props = gp;
     }
     else
     {
         props = new GeneratorProps(Vector3.one, 0.1f);
     }
 }
Exemple #4
0
        //Creates a new collider with the given name and properties
        public ColliderInstance(string n, GeneratorProps gp)
        {
            name = n;

            if (gp != null)
            {
                props = gp;
            }
            else
            {
                props = new GeneratorProps(Vector3.one, 0.1f);
            }
        }
Exemple #5
0
        //Sets the collider at the index in the list to use the given mesh and properties
        public void SetCollider(int index, Mesh m, GeneratorProps gp)
        {
            if (m != null)
            {
                colliders[index].colMesh = Instantiate(m);
            }

            if (gp != null)
            {
                colliders[index].props = gp;
            }

            SetColliderComponents(true);
        }
Exemple #6
0
        //Creates a new collider with the given name, mesh, and properties
        public ColliderInstance(string n, Mesh m, GeneratorProps gp)
        {
            name = n;
            if (m != null)
            {
                colMesh = Object.Instantiate(m);
            }

            if (gp != null)
            {
                props = gp;
            }
            else
            {
                props = new GeneratorProps(Vector3.one, 0.1f);
            }
        }
        //Copies properties from another GeneratorProps instance
        //If copyPreset is true, it will also copy the linked preset reference from the other instance
        public void CopyProperties(GeneratorProps gp, bool copyPreset)
        {
            if (copyPreset)
            {
                linkedPreset = gp.linkedPreset;
            }

            meshAssetPath      = gp.meshAssetPath;
            cornerPositionMode = gp.cornerPositionMode;
            cornerRadiusMode   = gp.cornerRadiusMode;
            cornerOffsetMode   = gp.cornerOffsetMode;
            cornerDetailMode   = gp.cornerDetailMode;
            boxSize            = gp.boxSize;
            boxOffset          = gp.boxOffset;
            boxSidesPos        = gp.boxSidesPos;
            boxSidesNeg        = gp.boxSidesNeg;
            for (int i = 0; i < corners.Length; i++)
            {
                corners[i] = new ColliderCorner(gp.corners[i]);
            }

            for (int i = 0; i < cornerDetails.Length; i++)
            {
                cornerDetails[i] = gp.cornerDetails[i];
            }

            topSegments             = gp.topSegments;
            bottomSegments          = gp.bottomSegments;
            XYDetail                = gp.XYDetail;
            YZDetail                = gp.YZDetail;
            XZDetail                = gp.XZDetail;
            detailSmoothness        = gp.detailSmoothness;
            stripDistribution1      = gp.stripDistribution1;
            stripDistribution2      = gp.stripDistribution2;
            bypassPolyTest          = gp.bypassPolyTest;
            polyTestMode            = gp.polyTestMode;
            detailReduction         = gp.detailReduction;
            detailReductionAttempts = gp.detailReductionAttempts;
            boxedCorners            = gp.boxedCorners;
            hooks = new DeformHook[gp.hooks.Length];

            for (int i = 0; i < hooks.Length; i++)
            {
                hooks[i] = new DeformHook(gp.hooks[i]);
            }
        }
Exemple #8
0
        private void Update()
        {
            if (target == null || colGroup == null)
            {
                return;
            }

            if (colGroup.colliders.Count == 0)
            {
                //Add a collider to the group if it doesn't exist and add a deformation hook to it
                colProps = colGroup.AddCollider().props;
                colProps.AddHook(DeformHook.HookType.Pull, Vector3.zero, Quaternion.LookRotation(Vector3.up, Vector3.forward), 1.0f, 0.0f, 1.0f);
                GenerateCollider();
            }

            if (Input.GetKeyDown(KeyCode.Escape))
            {
                Application.Quit();
            }
        }
Exemple #9
0
        //The actual polygon test for the given properties and generation container using the indicated polygon test mode "pt"
        static bool MeshPolyTest(GeneratorInstance gi, GeneratorProps gp, PolygonTest pt)
        {
            if (gi.tris.Count >= 3 && gi.finalVerts.Length >= 3)
            {
                switch (pt)
                {
                case PolygonTest.TotalTriangles:
                    return(gi.tris.Count / 3 <= 255);

                case PolygonTest.TotalQuads:
                    return(gi.tris.Count / 6 <= 255);

                case PolygonTest.EdgeQuads:
                    return(((gp.topSegments + gp.bottomSegments) * (gp.cornerDetails[0] + gp.cornerDetails[1] + gp.cornerDetails[2] + gp.cornerDetails[3] + 6)) <= 255);

                case PolygonTest.FaceEdgeQuads:
                    return(((gp.topSegments + gp.bottomSegments) * ((gp.cornerDetails[0] + gp.cornerDetails[1] + gp.cornerDetails[2] + gp.cornerDetails[3]) * (gp.XZDetail + 1) + gp.XYDetail + gp.YZDetail + 2)) <= 255);
                }
            }
            return(false);
        }
Exemple #10
0
        //Mesh generation function wrapped by other methods; do not call this one directly
        static Mesh GenerationOperation(ref GeneratorProps genProps, out ColliderFinishStatus cFin, bool preview)
        {
            genProps.VerifyProperties();                       //Make sure properties are valid
            cFin = ColliderFinishStatus.Fail;                  //Default status
            PolygonTest polyTest = PolygonTest.TotalTriangles; //Default polygon test

            //Choose proper polygon test mode
            if (genProps.polyTestMode == PolygonTestMode.BestGuess)
            {
                polyTest = genProps.boxedCorners ? PolygonTest.EdgeQuads : PolygonTest.FaceEdgeQuads;
            }
            else if (genProps.polyTestMode == PolygonTestMode.SafeGuess)
            {
                polyTest = genProps.boxedCorners ? PolygonTest.TotalQuads : PolygonTest.TotalTriangles;
            }
            else
            {
                polyTest = (PolygonTest)(genProps.polyTestMode - 2);
            }

            GeneratorInstance gi = new GeneratorInstance();//Temporary container for generation data in the static method
            bool passedPolyTest  = false;
            bool generating      = true;
            int  genAttempts     = 0; //Generation attempts
            int  reductionType   = 0; //0 = plane strips, 1 = top/bottom segments, 2 = corners

            //Loop is for repeat detail reduction attempts
            while (generating)
            {
                if (gi != null)
                {
                    gi.ClearData();             //Clear generation data before next attempt
                }
                GenerateMesh(ref gi, genProps); //The true mesh generation function

                if (genProps.bypassPolyTest || preview)
                {
                    //Skipping polygon testing
                    passedPolyTest = true;
                    generating     = false;
                }
                else if (genProps.detailReduction == GeneratorProps.DetailReductionMode.None)
                {
                    //Skipping detail reduction and checking if polygon test was passed
                    passedPolyTest = MeshPolyTest(gi, genProps, polyTest);
                    generating     = false;
                }
                else if (genProps.detailReductionAttempts > 0)
                {
                    //Detail reduction process
                    passedPolyTest = MeshPolyTest(gi, genProps, polyTest);//Polygon testing
                    if (genProps.detailReduction == GeneratorProps.DetailReductionMode.All)
                    {
                        //Reduce all detail properties together, one at a time
                        if (genAttempts < genProps.detailReductionAttempts && !passedPolyTest)
                        {
                            switch (reductionType)
                            {
                            case 0:    //Place strip reduction
                                genProps.XYDetail = Mathf.Max(0, genProps.XYDetail - 1);
                                genProps.YZDetail = Mathf.Max(0, genProps.YZDetail - 1);
                                genProps.XZDetail = Mathf.Max(0, genProps.XZDetail - 1);
                                break;

                            case 1:    //Top and bottom segment reduction
                                genProps.topSegments    = Mathf.Max(0, genProps.topSegments - 1);
                                genProps.bottomSegments = Mathf.Max(0, genProps.bottomSegments - 1);
                                break;

                            case 2:    //Corner detail reduction
                                genProps.cornerDetails[0] = Mathf.Max(0, genProps.cornerDetails[0] - 1);
                                genProps.cornerDetails[1] = Mathf.Max(0, genProps.cornerDetails[1] - 1);
                                genProps.cornerDetails[2] = Mathf.Max(0, genProps.cornerDetails[2] - 1);
                                genProps.cornerDetails[3] = Mathf.Max(0, genProps.cornerDetails[3] - 1);
                                break;
                            }

                            reductionType = (reductionType + 1) % 3;//Increment to next reduction type for subsequent attempt
                        }
                        else
                        {
                            generating = false;
                        }
                    }
                    else if (genProps.detailReduction == GeneratorProps.DetailReductionMode.LargestFirst)
                    {
                        //Reduce greatest detail property values first
                        if (genAttempts < genProps.detailReductionAttempts && !passedPolyTest)
                        {
                            //Get maximum detail value
                            int maxDetail = Mathf.Max(
                                genProps.XYDetail,
                                genProps.YZDetail,
                                genProps.XZDetail,
                                genProps.topSegments,
                                genProps.bottomSegments,
                                genProps.cornerDetails[0],
                                genProps.cornerDetails[1],
                                genProps.cornerDetails[2],
                                genProps.cornerDetails[3]);

                            //Reduce all detail properties that match the maximum value
                            if (maxDetail == genProps.XYDetail)
                            {
                                genProps.XYDetail = Mathf.Max(0, genProps.XYDetail - 1);
                            }

                            if (maxDetail == genProps.YZDetail)
                            {
                                genProps.YZDetail = Mathf.Max(0, genProps.YZDetail - 1);
                            }

                            if (maxDetail == genProps.XZDetail)
                            {
                                genProps.XZDetail = Mathf.Max(0, genProps.XZDetail - 1);
                            }

                            if (maxDetail == genProps.topSegments)
                            {
                                genProps.topSegments = Mathf.Max(0, genProps.topSegments - 1);
                            }

                            if (maxDetail == genProps.bottomSegments)
                            {
                                genProps.bottomSegments = Mathf.Max(0, genProps.bottomSegments - 1);
                            }

                            if (maxDetail == genProps.cornerDetails[0])
                            {
                                genProps.cornerDetails[0] = Mathf.Max(0, genProps.cornerDetails[0] - 1);
                            }

                            if (maxDetail == genProps.cornerDetails[1])
                            {
                                genProps.cornerDetails[1] = Mathf.Max(0, genProps.cornerDetails[1] - 1);
                            }

                            if (maxDetail == genProps.cornerDetails[2])
                            {
                                genProps.cornerDetails[2] = Mathf.Max(0, genProps.cornerDetails[2] - 1);
                            }

                            if (maxDetail == genProps.cornerDetails[3])
                            {
                                genProps.cornerDetails[3] = Mathf.Max(0, genProps.cornerDetails[3] - 1);
                            }
                        }
                        else
                        {
                            generating = false;
                        }
                    }
                    else
                    {
                        generating = false;
                    }
                }
                else
                {
                    generating = false;
                }
                genAttempts++;

                if (genAttempts > genProps.detailReductionAttempts)
                {
                    //Quit detail reduction upon reaching maximum attempts and throw exception
                    generating = false;
                    if (!passedPolyTest)
                    {
                        cFin = ColliderFinishStatus.DetailTimeout;
                    }
                }
            }

            if (passedPolyTest)
            {
                cFin = ColliderFinishStatus.Success;//Successful generation after passing polygon test
            }
            else if (cFin != ColliderFinishStatus.DetailTimeout)
            {
                cFin = ColliderFinishStatus.FailTriCount;//Failed generation due to having to many polygons
            }
            return(gi.colMesh);
        }
Exemple #11
0
        //Actual mesh generation with the indicated properties and generation container; do not call this directly
        static void GenerateMesh(ref GeneratorInstance gi, GeneratorProps genProps)
        {
            //Important vertex strips at ends of sections
            VertexStrip firstBottomStrip = new VertexStrip();
            VertexStrip lastBottomStrip  = new VertexStrip();
            VertexStrip firstTopStrip    = new VertexStrip();
            VertexStrip lastTopStrip     = new VertexStrip();

            int bottomSegments = Mathf.Max(1, genProps.bottomSegments);
            int topSegments    = Mathf.Max(1, genProps.topSegments);

            //Bottom section verts
            for (int i = 0; i < bottomSegments + 1; i++)
            {
                float stripProgress = (i * 1.0f) / (bottomSegments * 1.0f);

                //Properties for current vertex strip
                VertexStripProps stripProps = new VertexStripProps
                {
                    isTop            = false,
                    flat             = genProps.bottomSegments == 0,
                    cornerDetails    = genProps.cornerDetails,
                    XYDetail         = genProps.XYDetail,
                    YZDetail         = genProps.YZDetail,
                    cornerProgress   = Mathf.Pow(1.0f - Mathf.Pow(stripProgress, genProps.stripDistribution1), genProps.stripDistribution2),
                    corners          = genProps.corners,
                    detailSmoothness = genProps.detailSmoothness
                };

                lastBottomStrip = new VertexStrip(stripProps);
                gi.strips.Add(lastBottomStrip);

                if (i == 0)
                {
                    firstBottomStrip = new VertexStrip(stripProps);
                }
            }

            //Top section verts
            for (int i = 0; i < topSegments + 1; i++)
            {
                float stripProgress = 1.0f - (i * 1.0f) / (topSegments * 1.0f);

                //Properties for current vertex strip
                VertexStripProps stripProps = new VertexStripProps
                {
                    isTop            = true,
                    flat             = genProps.topSegments == 0,
                    cornerDetails    = genProps.cornerDetails,
                    XYDetail         = genProps.XYDetail,
                    YZDetail         = genProps.YZDetail,
                    cornerProgress   = Mathf.Pow(1.0f - Mathf.Pow(stripProgress, genProps.stripDistribution1), genProps.stripDistribution2),
                    corners          = genProps.corners,
                    detailSmoothness = genProps.detailSmoothness
                };

                firstTopStrip = new VertexStrip(stripProps);

                //Add lateral strips between top and bottom sections
                if (genProps.XZDetail > 0 && i == 0)
                {
                    int curStrip = 1;
                    while (curStrip < genProps.XZDetail + 1)
                    {
                        gi.strips.Add(new VertexStrip(lastBottomStrip, firstTopStrip, ((curStrip * 1.0f) / ((genProps.XZDetail + 1) * 1.0f)), genProps.detailSmoothness));
                        curStrip++;
                    }
                }
                else if (i == topSegments)
                {
                    lastTopStrip = new VertexStrip(stripProps);
                }

                gi.strips.Add(firstTopStrip);
            }

            //Top cap
            lastTopStrip.ArrangeSides();
            lastTopStrip.GenerateCap();

            //Bottom cap
            firstBottomStrip.ArrangeSides();
            firstBottomStrip.GenerateCap();

            //Final vert array concatenation
            List <Vector3> tempVerts = new List <Vector3>();

            for (int i = 0; i < gi.strips.Count; i++)
            {
                tempVerts.AddRange(gi.strips[i].verts);
            }

            //Adding vertices of the caps
            int capStartIndex = tempVerts.Count;

            tempVerts.AddRange(lastTopStrip.capVerts);
            tempVerts.AddRange(firstBottomStrip.capVerts);
            gi.finalVerts = tempVerts.ToArray();

            //Triangle assignment
            int stripLength = gi.strips[0].verts.Count;
            int baseVert    = 0;
            int stripLoop   = 0;

            while (stripLoop < gi.strips.Count - 1)
            {
                for (int i = 0; i < stripLength - 1; i++)
                {
                    gi.tris.Add(baseVert + i);
                    gi.tris.Add(baseVert + stripLength + 1 + i);
                    gi.tris.Add(baseVert + i + 1);

                    gi.tris.Add(baseVert + stripLength + i);
                    gi.tris.Add(baseVert + stripLength + 1 + i);
                    gi.tris.Add(baseVert + i);
                }
                baseVert += stripLength;
                stripLoop++;
            }

            //Top cap triangles
            stripLength = lastTopStrip.side1.Count;
            for (int i = 0; i < lastTopStrip.capVerts.Count - stripLength - 1; i++)
            {
                if ((i + 1) % stripLength != 0)
                {
                    gi.tris.Add(capStartIndex + i);
                    gi.tris.Add(capStartIndex + i + 1);
                    gi.tris.Add(capStartIndex + stripLength + i);

                    gi.tris.Add(capStartIndex + stripLength + i);
                    gi.tris.Add(capStartIndex + i + 1);
                    gi.tris.Add(capStartIndex + stripLength + 1 + i);
                }
            }

            //Bottom cap triangles
            capStartIndex += lastTopStrip.capVerts.Count;
            stripLength    = firstBottomStrip.side1.Count;
            for (int i = 0; i < firstBottomStrip.capVerts.Count - stripLength - 1; i++)
            {
                if ((i + 1) % stripLength != 0)
                {
                    gi.tris.Add(capStartIndex + i + 1);
                    gi.tris.Add(capStartIndex + i);
                    gi.tris.Add(capStartIndex + stripLength + i);

                    gi.tris.Add(capStartIndex + i + 1);
                    gi.tris.Add(capStartIndex + stripLength + i);
                    gi.tris.Add(capStartIndex + stripLength + 1 + i);
                }
            }

            //Hook Deformation
            if (genProps.hooks.Length > 0)
            {
                for (int i = 0; i < genProps.hooks.Length; i++)
                {
                    DeformHook curHook = genProps.hooks[i];
                    if (curHook.enabled)
                    {
                        for (int j = 0; j < gi.finalVerts.Length; j++)
                        {
                            Vector3 curVert      = gi.finalVerts[j];
                            float   deformAmount = Mathf.Pow(Mathf.Max(0.0f, curHook.radius - Vector3.Distance(curVert, curHook.localPos)), curHook.falloff);
                            switch (curHook.hookType)
                            {
                            case DeformHook.HookType.Pull:
                                gi.finalVerts[j] += curHook.localRot * Vector3.forward * deformAmount * curHook.strength;
                                break;

                            case DeformHook.HookType.Twist:
                                Vector3 newVert = curHook.localPos + curHook.localRot * (curVert - curHook.localPos);
                                gi.finalVerts[j] += (newVert - curVert) * deformAmount * curHook.strength;
                                break;

                            case DeformHook.HookType.Expand:
                                gi.finalVerts[j] += curHook.localPos + (curVert - curHook.localPos) * (1.0f + (curHook.strength - 1.0f) * deformAmount) - curVert;
                                break;
                            }
                        }
                    }
                }
            }

            //Set final mesh data
            gi.colMesh           = new Mesh();
            gi.colMesh.vertices  = gi.finalVerts;
            gi.colMesh.triangles = gi.tris.ToArray();
        }
Exemple #12
0
 //Generates a collision mesh with the indicated properties and status information
 public static Mesh GenerateCollider(ref GeneratorProps genProps, out ColliderFinishStatus cFin)
 {
     return(GenerationOperation(ref genProps, out cFin, false));
 }
Exemple #13
0
 //Generates a collision mesh with the indicated properties and status holder
 //Preview indicates the mesh is used for previewing and not the actual collider component; will bypass polygon testing
 public static Mesh GenerateCollider(ref GeneratorProps genProps, out ColliderFinishStatus cFin, bool preview)
 {
     return(GenerationOperation(ref genProps, out cFin, preview));
 }
Exemple #14
0
        //Generates a collision mesh with the indicated properties
        public static Mesh GenerateCollider(ref GeneratorProps genProps)
        {
            ColliderFinishStatus cFin = ColliderFinishStatus.Fail;

            return(GenerationOperation(ref genProps, out cFin, true));
        }
Exemple #15
0
 //Creates a new collider with the given name and default properties
 public ColliderInstance(string n)
 {
     name  = n;
     props = new GeneratorProps(Vector3.one, 0.1f);
 }
Exemple #16
0
        public GeneratorProps props;     //The properties of the collider for mesh generation

        //Creates a new collider with default properties
        public ColliderInstance()
        {
            props = new GeneratorProps(Vector3.one, 0.1f);
        }
 //Creates a new instance of collider properties by copying from an existing one
 public GeneratorProps(GeneratorProps gp)
 {
     CopyProperties(gp, true);
 }