//Adds a new hook to the collider
        public void AddHook(DeformHook dh)
        {
            List <DeformHook> tempHooks = hooks.ToList();

            tempHooks.Add(dh);
            hooks = tempHooks.ToArray();
        }
        //Adds a new hook with the given properties to the collider
        public DeformHook AddHook(string name, DeformHook.HookType hType, Vector3 pos, Quaternion rot, float radius, float strength, float falloff)
        {
            List <DeformHook> tempHooks = hooks.ToList();
            DeformHook        newHook   = new DeformHook(name, hType, pos, rot, radius, strength, falloff);

            tempHooks.Add(newHook);
            hooks = tempHooks.ToArray();
            return(newHook);
        }
        //Removes a hook from the collider if it exists
        public void RemoveHook(DeformHook hook)
        {
            List <DeformHook> tempHooks = hooks.ToList();

            if (tempHooks.Contains(hook))
            {
                tempHooks.Remove(hook);
                hooks = tempHooks.ToArray();
            }
            else
            {
                Debug.LogWarning("Specified hook does not exist in hook list.");
            }
        }
Exemple #4
0
 //Creates a new hook by copying an existing one
 public DeformHook(DeformHook h)
 {
     name          = h.name;
     enabled       = h.enabled;
     showHandles   = h.showHandles;
     hookType      = h.hookType;
     localPos      = h.localPos;
     localRot      = h.localRot;
     localEulerRot = h.localEulerRot;
     radius        = h.radius;
     strength      = h.strength;
     falloff       = h.falloff;
     set           = true;
 }
        //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 #6
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();
        }
        //Function for flipping corners
        //cids must be a list of corner ID pairs where each pair represents corners being swapped
        void FlipOperation(ColliderCorner.CornerId[] cids, ref DeformHook[] mHooks, int xFactor, int yFactor, int zFactor)
        {
            if (cids.Length != 8)
            {
                Debug.LogError("Mirror operation failed, corner input array must contain 8 corners (4 pairs of corners being mirrored).");
                return;
            }

            //Temporary corners for swapping
            ColliderCorner[] tempCorners = new ColliderCorner[4]
            {
                new ColliderCorner(GetCornerAtLocation(cids[1])), new ColliderCorner(GetCornerAtLocation(cids[3])),
                new ColliderCorner(GetCornerAtLocation(cids[5])), new ColliderCorner(GetCornerAtLocation(cids[7]))
            };

            //First part of flipping by mirroring
            MirrorCorner(cids[0], cids[1], xFactor, yFactor, zFactor);
            MirrorCorner(cids[2], cids[3], xFactor, yFactor, zFactor);
            MirrorCorner(cids[4], cids[5], xFactor, yFactor, zFactor);
            MirrorCorner(cids[6], cids[7], xFactor, yFactor, zFactor);

            //Second part of flipping by mirroring temporary corners
            MirrorCorner(tempCorners[0], cids[0], xFactor, yFactor, zFactor);
            MirrorCorner(tempCorners[1], cids[2], xFactor, yFactor, zFactor);
            MirrorCorner(tempCorners[2], cids[4], xFactor, yFactor, zFactor);
            MirrorCorner(tempCorners[3], cids[6], xFactor, yFactor, zFactor);

            //Flipping hooks
            for (int i = 0; i < mHooks.Length; i++)
            {
                DeformHook curHook = mHooks[i];
                curHook.localPos.Set(xFactor * curHook.localPos.x, yFactor * curHook.localPos.y, zFactor * curHook.localPos.z);

                Vector3 forwardDir = curHook.localRot * Vector3.forward;
                Vector3 upDir      = curHook.localRot * Vector3.up;
                if (curHook.hookType != DeformHook.HookType.Twist)
                {
                    //Flipping rules for pull and expand hook types
                    Vector3 flippedForwardDir = new Vector3(xFactor * forwardDir.x, yFactor * forwardDir.y, zFactor * forwardDir.z);
                    Vector3 flippedUpDir      = new Vector3(xFactor * upDir.x, yFactor * upDir.y, zFactor * upDir.z);
                    curHook.localRot = Quaternion.LookRotation(flippedForwardDir, flippedUpDir);
                }
                else
                {
                    //Special rules for flipping twist hook types
                    if (xFactor == -1)
                    {
                        Vector3 flippedForwardDir = new Vector3(xFactor * forwardDir.x, yFactor * forwardDir.y, zFactor * forwardDir.z);
                        Vector3 flippedUpDir      = new Vector3(xFactor * upDir.x, yFactor * upDir.y, zFactor * upDir.z);
                        curHook.localRot = Quaternion.LookRotation(flippedForwardDir, flippedUpDir);
                    }
                    else if (yFactor == -1)
                    {
                        Vector3 flippedForwardDir = new Vector3(xFactor * forwardDir.x, yFactor * forwardDir.y, zFactor * forwardDir.z);
                        Vector3 flippedUpDir      = new Vector3(yFactor * upDir.x, upDir.y, yFactor * upDir.z);
                        curHook.localRot = Quaternion.LookRotation(flippedForwardDir, flippedUpDir);
                    }
                    else if (zFactor == -1)
                    {
                        Vector3 flippedForwardDir = new Vector3(zFactor * forwardDir.x, zFactor * forwardDir.y, forwardDir.z);
                        Vector3 flippedUpDir      = new Vector3(zFactor * upDir.x, yFactor * upDir.y, zFactor * upDir.z);
                        curHook.localRot = Quaternion.LookRotation(flippedForwardDir, flippedUpDir);
                    }
                }
                curHook.localEulerRot = curHook.localRot.eulerAngles;
            }
        }
        //Function for mirroring corners
        //cids must be a list of corner ID pairs where each pair represents a getter and setter corner, where one corner's properties are being mirrored and copied to the other one
        void MirrorOperation(ColliderCorner.CornerId[] cids, ref DeformHook[] mHooks, int xFactor, int yFactor, int zFactor, bool isPositiveSide)
        {
            if (cids.Length != 8)
            {
                Debug.LogError("Mirror operation failed, corner input array must contain 8 corners (4 pairs of corners being mirrored).");
                return;
            }

            //Mirroring corners
            MirrorCorner(cids[0], cids[1], xFactor, yFactor, zFactor);
            MirrorCorner(cids[2], cids[3], xFactor, yFactor, zFactor);
            MirrorCorner(cids[4], cids[5], xFactor, yFactor, zFactor);
            MirrorCorner(cids[6], cids[7], xFactor, yFactor, zFactor);

            //Tests to make sure not to mirror hooks at the center of the flipping axis and remove hooks opposite of the mirroring side
            List <DeformHook> tempHooks = mHooks.ToList();

            for (int i = 0; i < tempHooks.Count; i++)
            {
                if (isPositiveSide && ((xFactor < 0 && tempHooks[i].localPos.x < -0.001f) || (yFactor < 0 && tempHooks[i].localPos.y < -0.001f) || (zFactor < 0 && tempHooks[i].localPos.z < -0.001f)) ||
                    !isPositiveSide && ((xFactor <0 && tempHooks[i].localPos.x> 0.001f) || (yFactor <0 && tempHooks[i].localPos.y> 0.001f) || (zFactor <0 && tempHooks[i].localPos.z> 0.001f)))
                {
                    tempHooks[i] = null;
                }
            }
            tempHooks.RemoveAll(hook => hook == null);

            //Mirroring hooks
            List <DeformHook> mirroredHooks = new List <DeformHook>();

            for (int i = 0; i < tempHooks.Count; i++)
            {
                if ((xFactor < 0 && Mathf.Abs(tempHooks[i].localPos.x) > 0.001f) || (yFactor <0 && Mathf.Abs(tempHooks[i].localPos.y)> 0.001f) || (zFactor <0 && Mathf.Abs(tempHooks[i].localPos.z)> 0.001f))
                {
                    DeformHook newHook = new DeformHook(tempHooks[i]);
                    if (!newHook.name.EndsWith("Mirrored"))
                    {
                        newHook.name += " Mirrored";
                    }
                    newHook.localPos.Set(xFactor * newHook.localPos.x, yFactor * newHook.localPos.y, zFactor * newHook.localPos.z);

                    Vector3 forwardDir = newHook.localRot * Vector3.forward;
                    Vector3 upDir      = newHook.localRot * Vector3.up;
                    if (newHook.hookType != DeformHook.HookType.Twist)
                    {
                        //Mirroring rules for pull and expand hook types
                        Vector3 flippedForwardDir = new Vector3(xFactor * forwardDir.x, yFactor * forwardDir.y, zFactor * forwardDir.z);
                        Vector3 flippedUpDir      = new Vector3(xFactor * upDir.x, yFactor * upDir.y, zFactor * upDir.z);
                        newHook.localRot = Quaternion.LookRotation(flippedForwardDir, flippedUpDir);
                    }
                    else
                    {
                        //Special rules for mirroring twist hook types
                        if (xFactor == -1)
                        {
                            Vector3 flippedForwardDir = new Vector3(xFactor * forwardDir.x, yFactor * forwardDir.y, zFactor * forwardDir.z);
                            Vector3 flippedUpDir      = new Vector3(xFactor * upDir.x, yFactor * upDir.y, zFactor * upDir.z);
                            newHook.localRot = Quaternion.LookRotation(flippedForwardDir, flippedUpDir);
                        }
                        else if (yFactor == -1)
                        {
                            Vector3 flippedForwardDir = new Vector3(xFactor * forwardDir.x, yFactor * forwardDir.y, zFactor * forwardDir.z);
                            Vector3 flippedUpDir      = new Vector3(yFactor * upDir.x, upDir.y, yFactor * upDir.z);
                            newHook.localRot = Quaternion.LookRotation(flippedForwardDir, flippedUpDir);
                        }
                        else if (zFactor == -1)
                        {
                            Vector3 flippedForwardDir = new Vector3(zFactor * forwardDir.x, zFactor * forwardDir.y, forwardDir.z);
                            Vector3 flippedUpDir      = new Vector3(zFactor * upDir.x, yFactor * upDir.y, zFactor * upDir.z);
                            newHook.localRot = Quaternion.LookRotation(flippedForwardDir, flippedUpDir);
                        }
                    }
                    newHook.localEulerRot = newHook.localRot.eulerAngles;
                    mirroredHooks.Add(newHook);
                }
            }
            tempHooks.AddRange(mirroredHooks);
            mHooks = tempHooks.ToArray();
        }