Exemplo n.º 1
0
            public void ApplyFriction(Rigidbody rigidbody, float staticCoefficient, float kineticCoefficient,
                                      Vector3 contactPoint)
            {
                // Square the threshold for efficiency.
                var threshold      = rigidbody.sleepThreshold * rigidbody.sleepThreshold;
                var gravityToApply = rigidbody.simulateGravity ? gravity : Vector3.zero;

                var rigidbodyToContact = (contactPoint - rigidbody.position);
                var gravitationalForce = rigidbody.mass * gravityToApply;
                var angle = Vector3.Angle(-rigidbodyToContact, Vector3.down) * Mathf.Deg2Rad;
                var N     = gravitationalForce * Mathf.Cos(angle);

                var force     = rigidbody.momentum / Time.fixedDeltaTime + gravitationalForce;
                var direction = force.normalized;

                // Apply to linear momentum.
                if (force.sqrMagnitude < threshold)
                {
                    rigidbody.AddForce(-staticCoefficient * direction * N.magnitude);
                }

                else
                {
                    rigidbody.AddForce(-kineticCoefficient * direction * N.magnitude);
                }

                rigidbody.AddForce(N);
            }
Exemplo n.º 2
0
        // TODO: could probably figure out "inverse" from direction of topY compared to bottomY
        public static Vector3[] GetConeFrustumVertices(CSGCircleDefinition definition, float topHeight, float rotation, int segments, ref Vector3[] vertices, bool inverse = false)
        {
            var rotate      = Quaternion.AngleAxis(rotation, Vector3.up);
            var bottomAxisX = rotate * Vector3.right * definition.diameterX * 0.5f;
            var bottomAxisZ = rotate * Vector3.forward * definition.diameterZ * 0.5f;
            var topY        = Vector3.up * topHeight;
            var bottomY     = Vector3.up * definition.height;

            if (vertices == null ||
                vertices.Length != segments + 1)
            {
                vertices = new Vector3[segments + 1];
            }

            float angleOffset = ((segments & 1) == 1) ? 0.0f : ((360.0f / segments) * 0.5f);

            vertices[0] = topY;
            for (int v = 0; v < segments; v++)
            {
                var r = (((v * 360.0f) / (float)segments) + angleOffset) * Mathf.Deg2Rad;
                var s = Mathf.Sin(r);
                var c = Mathf.Cos(r);

                var bottomVertex = (bottomAxisX * c) + (bottomAxisZ * s);
                bottomVertex += bottomY;
                var vi = inverse ? (segments - v) : (v + 1);
                vertices[vi] = bottomVertex;
            }

            return(vertices);
        }
Exemplo n.º 3
0
        public static Vector2 Rotate(Vector2 v, float rad)
        {
            float cos = Mathf.Cos(rad);
            float sin = Mathf.Sin(rad);

            return(new Vector2(cos * v.x - sin * v.y, sin * v.x + cos * v.y));
        }
Exemplo n.º 4
0
        public static void CreateSphereVertices(Vector3 diameterXYZ, float offsetY, bool generateFromCenter, int horzSegments, int vertSegments, ref Vector3[] vertices)
        {
            //var lastVertSegment	= vertSegments - 1;
            int vertexCount = (horzSegments * (vertSegments - 1)) + 2;

            if (vertices == null ||
                vertices.Length != vertexCount)
            {
                vertices = new Vector3[vertexCount];
            }

            var radius = 0.5f * diameterXYZ;

            var offset = generateFromCenter ? offsetY : radius.y + offsetY;

            vertices[0] = Vector3.down * radius.y;
            vertices[1] = Vector3.up * radius.y;

            vertices[0].y += offset;
            vertices[1].y += offset;

            // TODO: optimize

            var degreePerSegment = (360.0f / horzSegments) * Mathf.Deg2Rad;
            var angleOffset      = ((horzSegments & 1) == 1) ? 0.0f : ((360.0f / horzSegments) * 0.5f) * Mathf.Deg2Rad;

            for (int v = 1, vertexIndex = 2; v < vertSegments; v++)
            {
                var segmentFactor = ((v - (vertSegments / 2.0f)) / vertSegments);   // [-0.5f ... 0.5f]
                var segmentDegree = (segmentFactor * 180);                          // [-90 .. 90]
                var segmentHeight = Mathf.Sin(segmentDegree * Mathf.Deg2Rad);
                var segmentRadius = Mathf.Cos(segmentDegree * Mathf.Deg2Rad);       // [0 .. 0.707 .. 1 .. 0.707 .. 0]

                var yRingPos    = (segmentHeight * radius.y) + offset;
                var xRingRadius = segmentRadius * radius.x;
                var zRingRadius = segmentRadius * radius.z;

                if (radius.y < 0)
                {
                    for (int h = horzSegments - 1; h >= 0; h--, vertexIndex++)
                    {
                        var hRad = (h * degreePerSegment) + angleOffset;
                        vertices[vertexIndex] = new Vector3(Mathf.Cos(hRad) * segmentRadius * radius.x,
                                                            yRingPos,
                                                            Mathf.Sin(hRad) * segmentRadius * radius.z);
                    }
                }
                else
                {
                    for (int h = 0; h < horzSegments; h++, vertexIndex++)
                    {
                        var hRad = (h * degreePerSegment) + angleOffset;
                        vertices[vertexIndex] = new Vector3(Mathf.Cos(hRad) * segmentRadius * radius.x,
                                                            yRingPos,
                                                            Mathf.Sin(hRad) * segmentRadius * radius.z);
                    }
                }
            }
        }
Exemplo n.º 5
0
        Vector3 RandomCircle(Vector3 center, float radius, float angle)
        {
            Vector3 pos = new Vector3(0, 0, 0);

            pos.x = center.x + radius * Mathf.Sin(angle * Mathf.Deg2Rad);
            pos.y = center.y + radius * Mathf.Cos(angle * Mathf.Deg2Rad);
            pos.z = angle;
            return(pos);
        }
Exemplo n.º 6
0
        public static bool GenerateHemisphereVertices(Vector3 diameterXYZ, Matrix4x4 transform, int horzSegments, int vertSegments, ref Vector3[] vertices)
        {
            var bottomCap     = true;
            var topCap        = false;
            var extraVertices = ((!bottomCap) ? 1 : 0) + ((!topCap) ? 1 : 0);

            var rings       = (vertSegments) + (topCap ? 1 : 0);
            var vertexCount = (horzSegments * rings) + extraVertices;

            var topVertex    = 0;
            var bottomVertex = (!topCap) ? 1 : 0;
            var radius       = new Vector3(diameterXYZ.x * 0.5f,
                                           diameterXYZ.y,
                                           diameterXYZ.z * 0.5f);

            if (vertices == null ||
                vertices.Length != vertexCount)
            {
                vertices = new Vector3[vertexCount];
            }
            if (!topCap)
            {
                vertices[topVertex] = transform.MultiplyPoint(Vector3.up * radius.y);                // top
            }
            if (!bottomCap)
            {
                vertices[bottomVertex] = transform.MultiplyPoint(Vector3.zero);                      // bottom
            }
            var degreePerSegment = (360.0f / horzSegments) * Mathf.Deg2Rad;
            var angleOffset      = ((horzSegments & 1) == 1) ? 0.0f : 0.5f * degreePerSegment;
            var vertexIndex      = extraVertices;

            {
                for (int h = 0; h < horzSegments; h++, vertexIndex++)
                {
                    var hRad = (h * degreePerSegment) + angleOffset;
                    vertices[vertexIndex] = transform.MultiplyPoint(new Vector3(Mathf.Cos(hRad) * radius.x,
                                                                                0.0f,
                                                                                Mathf.Sin(hRad) * radius.z));
                }
            }
            for (int v = 1; v < rings; v++)
            {
                var segmentFactor = ((v - (rings / 2.0f)) / rings) + 0.5f;                          // [0.0f ... 1.0f]
                var segmentDegree = (segmentFactor * 90);                                           // [0 .. 90]
                var segmentHeight = Mathf.Sin(segmentDegree * Mathf.Deg2Rad) * radius.y;
                var segmentRadius = Mathf.Cos(segmentDegree * Mathf.Deg2Rad);                       // [0 .. 0.707 .. 1 .. 0.707 .. 0]
                for (int h = 0; h < horzSegments; h++, vertexIndex++)
                {
                    vertices[vertexIndex].x = vertices[h + extraVertices].x * segmentRadius;
                    vertices[vertexIndex].y = segmentHeight;
                    vertices[vertexIndex].z = vertices[h + extraVertices].z * segmentRadius;
                }
            }
            return(true);
        }
Exemplo n.º 7
0
        public static UnityEngine.Vector2 Rotate(this UnityEngine.Vector2 v, float degrees)
        {
            float radians = degrees * Mathf.Deg2Rad;
            float sin     = Mathf.Sin(radians);
            float cos     = Mathf.Cos(radians);

            float tx = v.x;
            float ty = v.y;

            return(new UnityEngine.Vector2(cos * tx - sin * ty, sin * tx + cos * ty));
        }
Exemplo n.º 8
0
        /** Clamps the velocity to the max speed and optionally the forwards direction.
         * \param velocity Desired velocity of the character. In world units per second.
         * \param maxSpeed Max speed of the character. In world units per second.
         * \param slowdownFactor Value between 0 and 1 which determines how much slower the character should move than normal.
         *      Normally 1 but should go to 0 when the character approaches the end of the path.
         * \param slowWhenNotFacingTarget Prevent the velocity from being too far away from the forward direction of the character
         *      and slow the character down if the desired velocity is not in the same direction as the forward vector.
         * \param forward Forward direction of the character. Used together with the \a slowWhenNotFacingTarget parameter.
         *
         * Note that all vectors are 2D vectors, not 3D vectors.
         *
         * \returns The clamped velocity in world units per second.
         */
        public static Vector2 ClampVelocity(Vector2 velocity, float maxSpeed, float slowdownFactor, bool slowWhenNotFacingTarget, Vector2 forward)
        {
            // Max speed to use for this frame
            var currentMaxSpeed = maxSpeed * slowdownFactor;

            // Check if the agent should slow down in case it is not facing the direction it wants to move in
            if (slowWhenNotFacingTarget && (forward.x != 0 || forward.y != 0))
            {
                float currentSpeed;
                var   normalizedVelocity = VectorMath.Normalize(velocity.ToPFV2(), out currentSpeed);
                float dot = Vector2.Dot(normalizedVelocity.ToUnityV2(), forward);

                // Lower the speed when the character's forward direction is not pointing towards the desired velocity
                // 1 when velocity is in the same direction as forward
                // 0.2 when they point in the opposite directions
                float directionSpeedFactor = Mathf.Clamp(dot + 0.707f, 0.2f, 1.0f);
                currentMaxSpeed *= directionSpeedFactor;
                currentSpeed     = Mathf.Min(currentSpeed, currentMaxSpeed);

                // Angle between the forwards direction of the character and our desired velocity
                float angle = Mathf.Acos(Mathf.Clamp(dot, -1, 1));

                // Clamp the angle to 20 degrees
                // We cannot keep the velocity exactly in the forwards direction of the character
                // because we use the rotation to determine in which direction to rotate and if
                // the velocity would always be in the forwards direction of the character then
                // the character would never rotate.
                // Allow larger angles when near the end of the path to prevent oscillations.
                angle = Mathf.Min(angle, (20f + 180f * (1 - slowdownFactor * slowdownFactor)) * Mathf.Deg2Rad);

                float sin = Mathf.Sin(angle);
                float cos = Mathf.Cos(angle);

                // Determine if we should rotate clockwise or counter-clockwise to move towards the current velocity
                sin *= Mathf.Sign(normalizedVelocity.x * forward.y - normalizedVelocity.y * forward.x);
                // Rotate the #forward vector by #angle radians
                // The rotation is done using an inlined rotation matrix.
                // See https://en.wikipedia.org/wiki/Rotation_matrix
                return(new Vector2(forward.x * cos + forward.y * sin, forward.y * cos - forward.x * sin) * currentSpeed);
            }
            else
            {
                return(Vector2.ClampMagnitude(velocity, currentMaxSpeed));
            }
        }
Exemplo n.º 9
0
        public static Vector3[] GetConicalFrustumVertices(CSGCircleDefinition bottom, CSGCircleDefinition top, float rotation, int segments, ref Vector3[] vertices)
        {
            if (top.height > bottom.height)
            {
                var temp = top; top = bottom; bottom = temp;
            }

            var rotate      = Quaternion.AngleAxis(rotation, Vector3.up);
            var topAxisX    = rotate * Vector3.right * top.diameterX * 0.5f;
            var topAxisZ    = rotate * Vector3.forward * top.diameterZ * 0.5f;
            var bottomAxisX = rotate * Vector3.right * bottom.diameterX * 0.5f;
            var bottomAxisZ = rotate * Vector3.forward * bottom.diameterZ * 0.5f;
            var topY        = Vector3.up * top.height;
            var bottomY     = Vector3.up * bottom.height;

            // TODO: handle situation where diameterX & diameterZ are 0 (only create one vertex)

            if (vertices == null ||
                vertices.Length != segments * 2)
            {
                vertices = new Vector3[segments * 2];
            }

            float angleOffset = ((segments & 1) == 1) ? 0.0f : ((360.0f / segments) * 0.5f);

            for (int v = 0; v < segments; v++)
            {
                var r = (((v * 360.0f) / (float)segments) + angleOffset) * Mathf.Deg2Rad;
                var s = Mathf.Sin(r);
                var c = Mathf.Cos(r);

                var topVertex    = (topAxisX * c) + (topAxisZ * s);
                var bottomVertex = (bottomAxisX * c) + (bottomAxisZ * s);
                topVertex             += topY;
                bottomVertex          += bottomY;
                vertices[v]            = topVertex;
                vertices[v + segments] = bottomVertex;
            }

            return(vertices);
        }
Exemplo n.º 10
0
 /// <summary>
 /// Modeled after half sine wave
 /// </summary>
 internal static float EaseInOutSine(float p)
 {
     return(0.5f * (1 - Math.Cos(p * PI)));
 }
        // possible situations:
        //	capsule with top AND bottom set to >0 height
        //	capsule with top OR bottom set to 0 height
        //	capsule with both top AND bottom set to 0 height
        //	capsule with height equal to top and bottom height
        public static bool GenerateCapsuleVertices(ref CSGCapsuleDefinition definition, ref Vector3[] vertices)
        {
            definition.Validate();
            var haveTopHemisphere    = definition.haveRoundedTop;
            var haveBottomHemisphere = definition.haveRoundedBottom;
            var haveMiddleCylinder   = definition.haveCylinder;

            if (!haveBottomHemisphere && !haveTopHemisphere && !haveMiddleCylinder)
            {
                return(false);
            }

            var radiusX        = definition.diameterX * 0.5f;
            var radiusZ        = definition.diameterZ * 0.5f;
            var topHeight      = haveTopHemisphere    ? definition.topHeight    : 0;
            var bottomHeight   = haveBottomHemisphere ? definition.bottomHeight : 0;
            var totalHeight    = definition.height;
            var cylinderHeight = definition.cylinderHeight;

            var sides = definition.sides;

            var extraVertices = definition.extraVertexCount;

            var bottomRings = definition.bottomRingCount;
            var topRings    = definition.topRingCount;
            var ringCount   = definition.ringCount;
            var vertexCount = definition.vertexCount;

            var bottomVertex = definition.bottomVertex;
            var topVertex    = definition.topVertex;

            var topOffset    = definition.topOffset + definition.offsetY;
            var bottomOffset = definition.bottomOffset + definition.offsetY;

            if (vertices == null ||
                vertices.Length != vertexCount)
            {
                vertices = new Vector3[vertexCount];
            }

            if (haveBottomHemisphere)
            {
                vertices[bottomVertex] = Vector3.up * (bottomOffset - bottomHeight);                       // bottom
            }
            if (haveTopHemisphere)
            {
                vertices[topVertex] = Vector3.up * (topOffset + topHeight);                                // top
            }
            var degreePerSegment = (360.0f / sides) * Mathf.Deg2Rad;
            var angleOffset      = definition.rotation + (((sides & 1) == 1) ? 0.0f : 0.5f * degreePerSegment);

            var topVertexOffset    = extraVertices + ((topRings - 1) * sides);
            var bottomVertexOffset = extraVertices + ((ringCount - bottomRings) * sides);
            var unitCircleOffset   = topVertexOffset;
            var vertexIndex        = unitCircleOffset;

            {
                for (int h = sides - 1; h >= 0; h--, vertexIndex++)
                {
                    var hRad = (h * degreePerSegment) + angleOffset;
                    vertices[vertexIndex] = new Vector3(Mathf.Cos(hRad) * radiusX,
                                                        0.0f,
                                                        Mathf.Sin(hRad) * radiusZ);
                }
            }
            for (int v = 1; v < topRings; v++)
            {
                vertexIndex = topVertexOffset - (v * sides);
                var segmentFactor = ((v - (topRings * 0.5f)) / topRings) + 0.5f;        // [0.0f ... 1.0f]
                var segmentDegree = (segmentFactor * 90);                               // [0 .. 90]
                var segmentHeight = topOffset +
                                    (Mathf.Sin(segmentDegree * Mathf.Deg2Rad) *
                                     topHeight);
                var segmentRadius = Mathf.Cos(segmentDegree * Mathf.Deg2Rad);                   // [0 .. 0.707 .. 1 .. 0.707 .. 0]
                for (int h = 0; h < sides; h++, vertexIndex++)
                {
                    vertices[vertexIndex].x = vertices[h + unitCircleOffset].x * segmentRadius;
                    vertices[vertexIndex].y = segmentHeight;
                    vertices[vertexIndex].z = vertices[h + unitCircleOffset].z * segmentRadius;
                }
            }
            vertexIndex = bottomVertexOffset;
            {
                for (int h = 0; h < sides; h++, vertexIndex++)
                {
                    vertices[vertexIndex] = new Vector3(vertices[h + unitCircleOffset].x,
                                                        bottomOffset,
                                                        vertices[h + unitCircleOffset].z);
                }
            }
            for (int v = 1; v < bottomRings; v++)
            {
                var segmentFactor = ((v - (bottomRings * 0.5f)) / bottomRings) + 0.5f;          // [0.0f ... 1.0f]
                var segmentDegree = (segmentFactor * 90);                                       // [0 .. 90]
                var segmentHeight = bottomOffset - bottomHeight +
                                    ((1 - Mathf.Sin(segmentDegree * Mathf.Deg2Rad)) *
                                     bottomHeight);
                var segmentRadius = Mathf.Cos(segmentDegree * Mathf.Deg2Rad);                                   // [0 .. 0.707 .. 1 .. 0.707 .. 0]
                for (int h = 0; h < sides; h++, vertexIndex++)
                {
                    vertices[vertexIndex].x = vertices[h + unitCircleOffset].x * segmentRadius;
                    vertices[vertexIndex].y = segmentHeight;
                    vertices[vertexIndex].z = vertices[h + unitCircleOffset].z * segmentRadius;
                }
            }
            {
                for (int h = 0; h < sides; h++, vertexIndex++)
                {
                    vertices[h + unitCircleOffset].y = topOffset;
                }
            }
            return(true);
        }
Exemplo n.º 12
0
 /// <summary>
 /// Modeled after half sine wave
 /// </summary>
 internal static float EaseInOutSine(float p) => 0.5f * (1 - Math.Cos(p * PI));
Exemplo n.º 13
0
        public static bool GenerateStadiumVertices(CSGStadiumDefinition definition, ref Vector3[] vertices)
        {
            definition.Validate();

            var topSides    = definition.topSides;
            var bottomSides = definition.bottomSides;
            var sides       = definition.sides;

            var length       = definition.length;
            var topLength    = definition.topLength;
            var bottomLength = definition.bottomLength;
            var diameter     = definition.diameter;
            var radius       = diameter * 0.5f;

            if (vertices == null ||
                vertices.Length != sides * 2)
            {
                vertices = new Vector3[sides * 2];
            }

            var firstTopSide    = definition.firstTopSide;
            var lastTopSide     = definition.lastTopSide;
            var firstBottomSide = definition.firstBottomSide;
            var lastBottomSide  = definition.lastBottomSide;

            var haveCenter = definition.haveCenter;

            int vertexIndex = 0;

            if (!definition.haveRoundedTop)
            {
                vertices[vertexIndex] = new Vector3(-radius, 0, length * -0.5f); vertexIndex++;
                vertices[vertexIndex] = new Vector3(radius, 0, length * -0.5f); vertexIndex++;
            }
            else
            {
                var degreeOffset     = -180.0f * Mathf.Deg2Rad;
                var degreePerSegment = (180.0f / topSides) * Mathf.Deg2Rad;
                var center           = new Vector3(0, 0, (length * -0.5f) + topLength);
                for (int s = 0; s <= topSides; s++)
                {
                    var hRad = (s * degreePerSegment) + degreeOffset;

                    var x = center.x + (Mathf.Cos(hRad) * radius);
                    var y = center.y;
                    var z = center.z + (Mathf.Sin(hRad) * topLength);

                    vertices[vertexIndex] = new Vector3(x, y, z);
                    vertexIndex++;
                }
            }

            if (!haveCenter)
            {
                vertexIndex--;
            }

            //vertexIndex = definition.firstBottomSide;
            if (!definition.haveRoundedBottom)
            {
                vertices[vertexIndex] = new Vector3(radius, 0, length * 0.5f); vertexIndex++;
                vertices[vertexIndex] = new Vector3(-radius, 0, length * 0.5f); vertexIndex++;
            }
            else
            {
                var degreeOffset     = 0.0f * Mathf.Deg2Rad;
                var degreePerSegment = (180.0f / bottomSides) * Mathf.Deg2Rad;
                var center           = new Vector3(0, 0, (length * 0.5f) - bottomLength);
                for (int s = 0; s <= bottomSides; s++)
                {
                    var hRad = (s * degreePerSegment) + degreeOffset;

                    var x = center.x + (Mathf.Cos(hRad) * radius);
                    var y = center.y;
                    var z = center.z + (Mathf.Sin(hRad) * bottomLength);

                    vertices[vertexIndex] = new Vector3(x, y, z);
                    vertexIndex++;
                }
            }

            var extrusion = Vector3.up * definition.height;

            for (int s = 0; s < sides; s++)
            {
                vertices[s + sides] = vertices[s] + extrusion;
            }
            return(true);
        }
Exemplo n.º 14
0
        public static bool GenerateHemisphereSubMesh(CSGBrushSubMesh subMesh, Vector3 diameterXYZ, Matrix4x4 transform, int horzSegments, int vertSegments, CSGSurfaceAsset[] surfaceAssets, SurfaceDescription[] surfaceDescriptions)
        {
            if (diameterXYZ.x == 0 ||
                diameterXYZ.y == 0 ||
                diameterXYZ.z == 0)
            {
                subMesh.Clear();
                return(false);
            }

            var bottomCap     = true;
            var topCap        = false;
            var extraVertices = ((!bottomCap) ? 1 : 0) + ((!topCap) ? 1 : 0);

            var rings       = (vertSegments) + (topCap ? 1 : 0);
            var vertexCount = (horzSegments * rings) + extraVertices;

            var topVertex    = 0;
            var bottomVertex = (!topCap) ? 1 : 0;
            var radius       = new Vector3(diameterXYZ.x * 0.5f,
                                           diameterXYZ.y,
                                           diameterXYZ.z * 0.5f);

            var   heightY = radius.y;
            float topY, bottomY;

            if (heightY < 0)
            {
                topY    = 0;
                bottomY = heightY;
            }
            else
            {
                topY    = heightY;
                bottomY = 0;
            }

            var vertices = new Vector3[vertexCount];

            if (!topCap)
            {
                vertices[topVertex] = transform.MultiplyPoint(Vector3.up * topY);                   // top
            }
            if (!bottomCap)
            {
                vertices[bottomVertex] = transform.MultiplyPoint(Vector3.up * bottomY);             // bottom
            }
            var degreePerSegment = (360.0f / horzSegments) * Mathf.Deg2Rad;
            var angleOffset      = ((horzSegments & 1) == 1) ? 0.0f : 0.5f * degreePerSegment;
            var vertexIndex      = extraVertices;

            if (heightY < 0)
            {
                for (int h = horzSegments - 1; h >= 0; h--, vertexIndex++)
                {
                    var hRad = (h * degreePerSegment) + angleOffset;
                    vertices[vertexIndex] = transform.MultiplyPoint(new Vector3(Mathf.Cos(hRad) * radius.x,
                                                                                0.0f,
                                                                                Mathf.Sin(hRad) * radius.z));
                }
            }
            else
            {
                for (int h = 0; h < horzSegments; h++, vertexIndex++)
                {
                    var hRad = (h * degreePerSegment) + angleOffset;
                    vertices[vertexIndex] = transform.MultiplyPoint(new Vector3(Mathf.Cos(hRad) * radius.x,
                                                                                0.0f,
                                                                                Mathf.Sin(hRad) * radius.z));
                }
            }
            for (int v = 1; v < rings; v++)
            {
                var segmentFactor = ((v - (rings / 2.0f)) / rings) + 0.5f;                      // [0.0f ... 1.0f]
                var segmentDegree = (segmentFactor * 90);                                       // [0 .. 90]
                var segmentHeight = Mathf.Sin(segmentDegree * Mathf.Deg2Rad) * heightY;
                var segmentRadius = Mathf.Cos(segmentDegree * Mathf.Deg2Rad);                   // [0 .. 0.707 .. 1 .. 0.707 .. 0]
                for (int h = 0; h < horzSegments; h++, vertexIndex++)
                {
                    vertices[vertexIndex].x = vertices[h + extraVertices].x * segmentRadius;
                    vertices[vertexIndex].y = segmentHeight;
                    vertices[vertexIndex].z = vertices[h + extraVertices].z * segmentRadius;
                }
            }

            return(GenerateSegmentedSubMesh(subMesh, horzSegments, vertSegments, vertices, bottomCap, topCap, bottomVertex, topVertex, surfaceAssets, surfaceDescriptions));
        }
Exemplo n.º 15
0
 public static float SineIn(float p)
 {
     return(-Mathf.Cos(p * (Mathf.PI * 0.5f)) + 1f);
 }
Exemplo n.º 16
0
        public static bool GenerateTorusAsset(CSGBrushMeshAsset brushMeshAsset, CSGTorusDefinition definition)
        {
            Vector3[] vertices = null;
            if (!GenerateTorusVertices(definition, ref vertices))
            {
                brushMeshAsset.Clear();
                return(false);
            }

            definition.Validate();
            var surfaces     = definition.surfaceAssets;
            var descriptions = definition.surfaceDescriptions;
            var tubeRadiusX  = (definition.tubeWidth * 0.5f);
            var tubeRadiusY  = (definition.tubeHeight * 0.5f);
            var torusRadius  = (definition.outerDiameter * 0.5f) - tubeRadiusX;


            var horzSegments = definition.horizontalSegments;
            var vertSegments = definition.verticalSegments;

            var horzDegreePerSegment = (definition.totalAngle / horzSegments);
            var vertDegreePerSegment = (360.0f / vertSegments) * Mathf.Deg2Rad;
            var descriptionIndex     = new int[2 + vertSegments];

            descriptionIndex[0] = 0;
            descriptionIndex[1] = 1;

            var circleVertices = new Vector2[vertSegments];

            var min             = new Vector2(float.PositiveInfinity, float.PositiveInfinity);
            var max             = new Vector2(float.NegativeInfinity, float.NegativeInfinity);
            var tubeAngleOffset = ((((vertSegments & 1) == 1) ? 0.0f : ((360.0f / vertSegments) * 0.5f)) + definition.tubeRotation) * Mathf.Deg2Rad;

            for (int v = 0; v < vertSegments; v++)
            {
                var vRad = tubeAngleOffset + (v * vertDegreePerSegment);
                circleVertices[v] = new Vector2((Mathf.Cos(vRad) * tubeRadiusX) - torusRadius,
                                                (Mathf.Sin(vRad) * tubeRadiusY));
                min.x = Mathf.Min(min.x, circleVertices[v].x);
                min.y = Mathf.Min(min.y, circleVertices[v].y);
                max.x = Mathf.Max(max.x, circleVertices[v].x);
                max.y = Mathf.Max(max.y, circleVertices[v].y);
                descriptionIndex[v + 2] = 2;
            }

            if (definition.fitCircle)
            {
                var center = (max + min) * 0.5f;
                var size   = (max - min) * 0.5f;
                size.x = tubeRadiusX / size.x;
                size.y = tubeRadiusY / size.y;
                for (int v = 0; v < vertSegments; v++)
                {
                    circleVertices[v].x  = (circleVertices[v].x - center.x) * size.x;
                    circleVertices[v].y  = (circleVertices[v].y - center.y) * size.y;
                    circleVertices[v].x -= torusRadius;
                }
            }

            var subMeshes  = new CSGBrushSubMesh[horzSegments];
            var horzOffset = definition.startAngle;

            for (int h = 1, p = 0; h < horzSegments + 1; p = h, h++)
            {
                var hDegree0        = (p * horzDegreePerSegment) + horzOffset;
                var hDegree1        = (h * horzDegreePerSegment) + horzOffset;
                var rotation0       = Quaternion.AngleAxis(hDegree0, Vector3.up);
                var rotation1       = Quaternion.AngleAxis(hDegree1, Vector3.up);
                var subMeshVertices = new Vector3[vertSegments * 2];
                for (int v = 0; v < vertSegments; v++)
                {
                    subMeshVertices[v + vertSegments] = rotation0 * circleVertices[v];
                    subMeshVertices[v] = rotation1 * circleVertices[v];
                }

                var subMesh = new CSGBrushSubMesh();
                CreateExtrudedSubMesh(subMesh, vertSegments, descriptionIndex, descriptionIndex, 0, 1, subMeshVertices, surfaces, descriptions);
                if (!subMesh.Validate())
                {
                    brushMeshAsset.Clear();
                    return(false);
                }
                subMeshes[h - 1] = subMesh;
            }

            brushMeshAsset.SubMeshes = subMeshes;

            brushMeshAsset.CalculatePlanes();
            brushMeshAsset.SetDirty();
            return(true);
        }
Exemplo n.º 17
0
        public static bool GenerateTorusVertices(CSGTorusDefinition definition, ref Vector3[] vertices)
        {
            definition.Validate();
            //var surfaces		= definition.surfaceAssets;
            //var descriptions	= definition.surfaceDescriptions;
            var tubeRadiusX = (definition.tubeWidth * 0.5f);
            var tubeRadiusY = (definition.tubeHeight * 0.5f);
            var torusRadius = (definition.outerDiameter * 0.5f) - tubeRadiusX;


            var horzSegments = definition.horizontalSegments;
            var vertSegments = definition.verticalSegments;

            var horzDegreePerSegment = (definition.totalAngle / horzSegments);
            var vertDegreePerSegment = (360.0f / vertSegments) * Mathf.Deg2Rad;

            var circleVertices = new Vector2[vertSegments];

            var min             = new Vector2(float.PositiveInfinity, float.PositiveInfinity);
            var max             = new Vector2(float.NegativeInfinity, float.NegativeInfinity);
            var tubeAngleOffset = ((((vertSegments & 1) == 1) ? 0.0f : ((360.0f / vertSegments) * 0.5f)) + definition.tubeRotation) * Mathf.Deg2Rad;

            for (int v = 0; v < vertSegments; v++)
            {
                var vRad = tubeAngleOffset + (v * vertDegreePerSegment);
                circleVertices[v] = new Vector2((Mathf.Cos(vRad) * tubeRadiusX) - torusRadius,
                                                (Mathf.Sin(vRad) * tubeRadiusY));
                min.x = Mathf.Min(min.x, circleVertices[v].x);
                min.y = Mathf.Min(min.y, circleVertices[v].y);
                max.x = Mathf.Max(max.x, circleVertices[v].x);
                max.y = Mathf.Max(max.y, circleVertices[v].y);
            }

            if (definition.fitCircle)
            {
                var center = (max + min) * 0.5f;
                var size   = (max - min) * 0.5f;
                size.x = tubeRadiusX / size.x;
                size.y = tubeRadiusY / size.y;
                for (int v = 0; v < vertSegments; v++)
                {
                    circleVertices[v].x  = (circleVertices[v].x - center.x) * size.x;
                    circleVertices[v].y  = (circleVertices[v].y - center.y) * size.y;
                    circleVertices[v].x -= torusRadius;
                }
            }

            if (definition.totalAngle != 360)
            {
                horzSegments++;
            }

            var horzOffset  = definition.startAngle;
            var vertexCount = vertSegments * horzSegments;

            if (vertices == null ||
                vertices.Length != vertexCount)
            {
                vertices = new Vector3[vertexCount];
            }
            for (int h = 0, v = 0; h < horzSegments; h++)
            {
                var hDegree1  = (h * horzDegreePerSegment) + horzOffset;
                var rotation1 = Quaternion.AngleAxis(hDegree1, Vector3.up);
                for (int i = 0; i < vertSegments; i++, v++)
                {
                    vertices[v] = rotation1 * circleVertices[i];
                }
            }
            return(true);
        }
Exemplo n.º 18
0
        public static bool GenerateSpiralStairsAsset(CSGBrushMeshAsset brushMeshAsset, ref CSGSpiralStairsDefinition definition, CSGSurfaceAsset[] surfaceAssets, ref SurfaceDescription[] surfaceDescriptions)
        {
            if (surfaceAssets == null ||
                surfaceDescriptions == null ||
                surfaceAssets.Length != 6 ||
                surfaceDescriptions.Length != 6)
            {
                brushMeshAsset.Clear();
                return(false);
            }

            definition.Validate();

            const float kEpsilon = 0.001f;

            var nosingDepth = definition.nosingDepth;
            var treadHeight = (nosingDepth < kEpsilon) ? 0 : definition.treadHeight;
            var haveTread   = (treadHeight >= kEpsilon);

            var innerDiameter = definition.innerDiameter;
            var haveInnerCyl  = (innerDiameter >= kEpsilon);

            var riserType = definition.riserType;
            var haveRiser = riserType != StairsRiserType.None;

            if (!haveRiser && !haveTread)
            {
                brushMeshAsset.Clear();
                return(false);
            }


            var origin = definition.origin;

            var startAngle   = definition.startAngle * Mathf.Deg2Rad;
            var anglePerStep = definition.AnglePerStep * Mathf.Deg2Rad;

            var nosingWidth   = definition.nosingWidth;
            var outerDiameter = definition.outerDiameter;

            var p0 = new Vector2(Mathf.Sin(0), Mathf.Cos(0));
            var p1 = new Vector2(Mathf.Sin(anglePerStep), Mathf.Cos(anglePerStep));
            var pm = new Vector2(Mathf.Sin(anglePerStep * 0.5f), Mathf.Cos(anglePerStep * 0.5f));
            var pn = (p0 + p1) * 0.5f;

            var stepOuterDiameter = outerDiameter + ((pm.magnitude - pn.magnitude) * (outerDiameter * 1.25f));               // TODO: figure out why we need the 1.25 magic number to fit the step in the outerDiameter?
            var stepOuterRadius   = stepOuterDiameter * 0.5f;
            var stepInnerRadius   = 0.0f;
            var stepHeight        = definition.stepHeight;
            var height            = definition.height;
            var stepCount         = definition.StepCount;

            if (height < 0)
            {
                origin.y += height;
                height    = -height;
            }

            // TODO: expose this to user
            var smoothSubDivisions = 3;

            var cylinderSubMeshCount = haveInnerCyl ? 2 : 1;
            var subMeshPerRiser      = (riserType == StairsRiserType.None) ? 0 :
                                       (riserType == StairsRiserType.Smooth) ? (2 * smoothSubDivisions)
                                                                                : 1;
            var riserSubMeshCount = (stepCount * subMeshPerRiser) + ((riserType == StairsRiserType.None) ? 0 : cylinderSubMeshCount);
            var treadSubMeshCount = (haveTread ? stepCount + cylinderSubMeshCount : 0);
            var subMeshCount      = (treadSubMeshCount + riserSubMeshCount);

            var treadStart = !haveRiser ? 0 : riserSubMeshCount;
            var innerSides = definition.innerSegments;
            var outerSides = definition.outerSegments;
            var riserDepth = definition.riserDepth;

            CSGBrushSubMesh[] subMeshes;
            if (brushMeshAsset.SubMeshCount != subMeshCount)
            {
                subMeshes = new CSGBrushSubMesh[subMeshCount];
                for (int i = 0; i < subMeshCount; i++)
                {
                    subMeshes[i] = new CSGBrushSubMesh();
                }
            }
            else
            {
                subMeshes = brushMeshAsset.SubMeshes;
            }

            if (haveRiser)
            {
                if (riserType == StairsRiserType.ThinRiser)
                {
                    var     minY = origin.y;
                    var     maxY = origin.y + stepHeight - treadHeight;
                    Vector2 o0, o1;
                    float   angle = startAngle;
                    var     c1    = Mathf.Sin(angle) * stepOuterRadius;
                    var     s1    = Mathf.Cos(angle) * stepOuterRadius;
                    for (int i = 0; i < stepCount; i++)
                    {
                        var c0 = c1;
                        var s0 = s1;
                        angle += anglePerStep;
                        c1     = Mathf.Sin(angle) * stepOuterRadius;
                        s1     = Mathf.Cos(angle) * stepOuterRadius;

                        o0 = new Vector2(origin.x + c0, origin.z + s0);
                        o1 = new Vector2(origin.x, origin.z);

                        var riserVector = (new Vector2((c0 - c1), (s0 - s1)).normalized) * riserDepth;

                        var i0 = o0 - riserVector;
                        var i1 = o1 - riserVector;

                        var vertices = new[] {
                            new Vector3(i0.x, maxY, i0.y),                      // 0
                            new Vector3(i1.x, maxY, i1.y),                      // 1
                            new Vector3(o1.x, maxY, o1.y),                      // 2
                            new Vector3(o0.x, maxY, o0.y),                      // 3

                            new Vector3(i0.x, minY, i0.y),                      // 4
                            new Vector3(i1.x, minY, i1.y),                      // 5
                            new Vector3(o1.x, minY, o1.y),                      // 6
                            new Vector3(o0.x, minY, o0.y),                      // 7
                        };

                        if (i == 0)
                        {
                            subMeshes[i].Polygons = CreateBoxAssetPolygons(surfaceAssets, surfaceDescriptions);
                            minY -= treadHeight;
                        }
                        else
                        {
                            subMeshes[i].Polygons = subMeshes[0].Polygons.ToArray();
                        }
                        subMeshes[i].HalfEdges = (anglePerStep > 0) ? invertedBoxHalfEdges.ToArray() : boxHalfEdges.ToArray();
                        subMeshes[i].Vertices  = vertices;

                        minY += stepHeight;
                        maxY += stepHeight;
                    }
                }
                else
                if (riserType == StairsRiserType.Smooth)
                {
                    //var stepY = stepHeight;
                    var   minY  = origin.y;
                    var   maxY  = origin.y + stepHeight - treadHeight;
                    var   maxY2 = origin.y + (stepHeight * 2) - treadHeight;
                    float angle = startAngle;
                    var   c1    = Mathf.Sin(angle);
                    var   s1    = Mathf.Cos(angle);
                    angle += anglePerStep;
                    var c2 = Mathf.Sin(angle);
                    var s2 = Mathf.Cos(angle);

                    for (int i = 0; i < riserSubMeshCount; i += subMeshPerRiser)
                    {
                        var c0 = c1;
                        var s0 = s1;
                        c1     = c2;
                        s1     = s2;
                        angle += anglePerStep;
                        c2     = Mathf.Sin(angle);
                        s2     = Mathf.Cos(angle);

                        var c0o = c0 * stepOuterRadius;
                        var c1o = c1 * stepOuterRadius;
                        var s0o = s0 * stepOuterRadius;
                        var s1o = s1 * stepOuterRadius;

                        var o0 = new Vector2(origin.x + c0o, origin.z + s0o);
                        var o1 = new Vector2(origin.x + c1o, origin.z + s1o);

                        var i0 = o0;
                        var i1 = o1;

                        int subMeshIndex = i;
                        for (int subDiv = 1; subDiv < smoothSubDivisions; subDiv++)
                        {
                            // TODO: need to space the subdivisions from smallest spaces to bigger spaces
                            float stepMidRadius;
                            stepMidRadius = (((outerDiameter * 0.5f) * (1.0f / (smoothSubDivisions + 1))) * ((smoothSubDivisions - 1) - (subDiv - 1)));
                            if (subDiv == (smoothSubDivisions - 1))
                            {
                                var innerRadius = (innerDiameter * 0.5f) - 0.1f;
                                stepMidRadius = (innerRadius < 0.1f) ? stepMidRadius : innerRadius;
                            }

                            var c0i = c0 * stepMidRadius;
                            var c1i = c1 * stepMidRadius;
                            var s0i = s0 * stepMidRadius;
                            var s1i = s1 * stepMidRadius;

                            i0 = new Vector2(origin.x + c0i, origin.z + s0i);
                            i1 = new Vector2(origin.x + c1i, origin.z + s1i);

                            {
                                var vertices = new[] {
                                    new Vector3(i0.x, maxY, i0.y),                        // 0
                                    new Vector3(i0.x, minY, i0.y),                        // 1
                                    new Vector3(o0.x, minY, o0.y),                        // 2
                                    new Vector3(o0.x, maxY, o0.y),                        // 3

                                    new Vector3(o1.x, maxY, o1.y),                        // 4
                                };

                                if (i == 0)
                                {
                                    subMeshes[subMeshIndex].Polygons = CreateSquarePyramidAssetPolygons(surfaceAssets, surfaceDescriptions);
                                }
                                else
                                {
                                    subMeshes[subMeshIndex].Polygons = subMeshes[subMeshIndex - i].Polygons.ToArray();
                                }
                                subMeshes[subMeshIndex].HalfEdges = (anglePerStep > 0) ? invertedSquarePyramidHalfEdges.ToArray() : squarePyramidHalfEdges.ToArray();
                                subMeshes[subMeshIndex].Vertices  = vertices;
                                subMeshIndex++;
                            }

                            {
                                var vertices = new[] {
                                    new Vector3(i0.x, maxY, i0.y),                        // 0
                                    new Vector3(i0.x, minY, i0.y),                        // 1
                                    new Vector3(i1.x, maxY, i1.y),                        // 2

                                    new Vector3(o1.x, maxY, o1.y),                        // 3
                                };

                                if (i == 0)
                                {
                                    subMeshes[subMeshIndex].Polygons = CreateTriangularPyramidAssetPolygons(surfaceAssets, surfaceDescriptions);
                                }
                                else
                                {
                                    subMeshes[subMeshIndex].Polygons = subMeshes[subMeshIndex - i].Polygons.ToArray();
                                }
                                subMeshes[subMeshIndex].HalfEdges = (anglePerStep > 0) ? invertedTriangularPyramidHalfEdges.ToArray() : triangularPyramidHalfEdges.ToArray();
                                subMeshes[subMeshIndex].Vertices  = vertices;
                                subMeshIndex++;
                            }

                            o0 = i0;
                            o1 = i1;
                        }

                        {
                            var vertices = new[] {
                                new Vector3(i0.x, maxY, i0.y),                        // 0
                                new Vector3(i1.x, maxY, i1.y),                        // 2
                                new Vector3(i0.x, minY, i0.y),                        // 1

                                new Vector3(origin.x, minY, origin.y),                // 3
                            };

                            if (i == 0)
                            {
                                subMeshes[subMeshIndex].Polygons = CreateTriangularPyramidAssetPolygons(surfaceAssets, surfaceDescriptions);
                            }
                            else
                            {
                                subMeshes[subMeshIndex].Polygons = subMeshes[subMeshIndex - i].Polygons.ToArray();
                            }
                            subMeshes[subMeshIndex].HalfEdges = (anglePerStep > 0) ? invertedTriangularPyramidHalfEdges.ToArray() : triangularPyramidHalfEdges.ToArray();
                            subMeshes[subMeshIndex].Vertices  = vertices;
                            subMeshIndex++;
                        }

                        {
                            var vertices = new[] {
                                new Vector3(i1.x, maxY, i1.y),                        // 2
                                new Vector3(i0.x, maxY, i0.y),                        // 0
                                new Vector3(origin.x, maxY, origin.y),                // 1

                                new Vector3(origin.x, minY, origin.y),                // 3
                            };

                            if (i == 0)
                            {
                                subMeshes[subMeshIndex].Polygons = CreateTriangularPyramidAssetPolygons(surfaceAssets, surfaceDescriptions);
                            }
                            else
                            {
                                subMeshes[subMeshIndex].Polygons = subMeshes[subMeshIndex - i].Polygons.ToArray();
                            }
                            subMeshes[subMeshIndex].HalfEdges = (anglePerStep > 0) ? invertedTriangularPyramidHalfEdges.ToArray() : triangularPyramidHalfEdges.ToArray();
                            subMeshes[subMeshIndex].Vertices  = vertices;
                            subMeshIndex++;
                        }

                        if (i == 0)
                        {
                            minY -= treadHeight;
                        }

                        minY  += stepHeight;
                        maxY  += stepHeight;
                        maxY2 += stepHeight;
                    }
                }
                else
                {
                    var     minY = origin.y;
                    var     maxY = origin.y + stepHeight - treadHeight;
                    Vector2 o0, o1;
                    float   angle = startAngle;
                    var     c1    = Mathf.Sin(angle) * stepOuterRadius;
                    var     s1    = Mathf.Cos(angle) * stepOuterRadius;
                    for (int i = 0; i < stepCount; i++)
                    {
                        var c0 = c1;
                        var s0 = s1;
                        angle += anglePerStep;
                        c1     = Mathf.Sin(angle) * stepOuterRadius;
                        s1     = Mathf.Cos(angle) * stepOuterRadius;

                        o0 = new Vector2(origin.x + c0, origin.z + s0);
                        o1 = new Vector2(origin.x + c1, origin.z + s1);
                        var vertices = new[] {
                            new Vector3(origin.x, maxY, origin.z),                // 0
                            new Vector3(o1.x, maxY, o1.y),                        // 1
                            new Vector3(o0.x, maxY, o0.y),                        // 2

                            new Vector3(origin.x, minY, origin.z),                // 3
                            new Vector3(o1.x, minY, o1.y),                        // 4
                            new Vector3(o0.x, minY, o0.y),                        // 5
                        };

                        if (i == 0)
                        {
                            subMeshes[i].Polygons = CreateWedgeAssetPolygons(surfaceAssets, surfaceDescriptions);
                            minY -= treadHeight;
                        }
                        else
                        {
                            subMeshes[i].Polygons = subMeshes[0].Polygons.ToArray();
                        }
                        subMeshes[i].HalfEdges = (anglePerStep > 0) ? invertedWedgeHalfEdges.ToArray() : wedgeHalfEdges.ToArray();
                        subMeshes[i].Vertices  = vertices;

                        if (riserType != StairsRiserType.FillDown)
                        {
                            minY += stepHeight;
                        }
                        maxY += stepHeight;
                    }
                }

                {
                    var subMeshIndex          = treadStart - cylinderSubMeshCount;
                    var cylinderSurfaceAssets = new CSGSurfaceAsset[3] {
                        surfaceAssets[0], surfaceAssets[1], surfaceAssets[2]
                    };
                    var cylinderSurfaceDescriptions = new SurfaceDescription[outerSides + 2]; //surfaceDescriptions[0]
                    cylinderSurfaceDescriptions[0] = surfaceDescriptions[0];
                    cylinderSurfaceDescriptions[1] = surfaceDescriptions[1];
                    for (int i = 0; i < outerSides; i++)
                    {
                        cylinderSurfaceDescriptions[i + 2] = surfaceDescriptions[2];
                    }
                    GenerateCylinderSubMesh(subMeshes[subMeshIndex], outerDiameter, origin.y, origin.y + height, 0, outerSides, cylinderSurfaceAssets, cylinderSurfaceDescriptions);
                    subMeshes[subMeshIndex].Operation = CSGOperationType.Intersecting;
                }

                if (haveInnerCyl)
                {
                    var subMeshIndex          = treadStart - 1;
                    var cylinderSurfaceAssets = new CSGSurfaceAsset[3] {
                        surfaceAssets[0], surfaceAssets[1], surfaceAssets[2]
                    };
                    var cylinderSurfaceDescriptions = new SurfaceDescription[innerSides + 2]; //surfaceDescriptions[0]
                    cylinderSurfaceDescriptions[0] = surfaceDescriptions[0];
                    cylinderSurfaceDescriptions[1] = surfaceDescriptions[1];
                    for (int i = 0; i < innerSides; i++)
                    {
                        cylinderSurfaceDescriptions[i + 2] = surfaceDescriptions[2];
                    }
                    GenerateCylinderSubMesh(subMeshes[subMeshIndex], innerDiameter, origin.y, origin.y + height, 0, innerSides, cylinderSurfaceAssets, cylinderSurfaceDescriptions);
                    subMeshes[subMeshIndex].Operation = CSGOperationType.Subtractive;
                }
            }

            if (haveTread)
            {
                var     minY = origin.y + stepHeight - treadHeight;
                var     maxY = origin.y + stepHeight;
                Vector2 i0, i1, o0, o1;
                float   angle      = startAngle;
                var     c1         = Mathf.Sin(angle);
                var     s1         = Mathf.Cos(angle);
                var     startIndex = treadStart;
                for (int n = 0, i = startIndex; n < stepCount; n++, i++)
                {
                    var c0 = c1;
                    var s0 = s1;
                    angle += anglePerStep;
                    c1     = Mathf.Sin(angle);
                    s1     = Mathf.Cos(angle);

                    i0 = new Vector2(origin.x + (c0 * (stepInnerRadius)), origin.z + (s0 * (stepInnerRadius)));
                    i1 = new Vector2(origin.x + (c1 * (stepInnerRadius)), origin.z + (s1 * (stepInnerRadius)));
                    o0 = new Vector2(origin.x + (c0 * (stepOuterRadius + nosingWidth)), origin.z + (s0 * (stepOuterRadius + nosingWidth)));
                    o1 = new Vector2(origin.x + (c1 * (stepOuterRadius + nosingWidth)), origin.z + (s1 * (stepOuterRadius + nosingWidth)));

                    var noseSizeDeep = (new Vector2((c0 - c1), (s0 - s1)).normalized) * nosingDepth;
                    i0 += noseSizeDeep;
                    o0 += noseSizeDeep;

                    var vertices = new[] {
                        new Vector3(i1.x, maxY, i1.y),                      // 1
                        new Vector3(i0.x, maxY, i0.y),                      // 0
                        new Vector3(o0.x, maxY, o0.y),                      // 3
                        new Vector3(o1.x, maxY, o1.y),                      // 2

                        new Vector3(i1.x, minY, i1.y),                      // 5
                        new Vector3(i0.x, minY, i0.y),                      // 4
                        new Vector3(o0.x, minY, o0.y),                      // 7
                        new Vector3(o1.x, minY, o1.y),                      // 6
                    };

                    if (n == 0)
                    {
                        subMeshes[i].Polygons = CreateBoxAssetPolygons(surfaceAssets, surfaceDescriptions);
                    }
                    else
                    {
                        subMeshes[i].Polygons = subMeshes[startIndex].Polygons.ToArray();
                    }

                    subMeshes[i].HalfEdges = (anglePerStep > 0) ? invertedBoxHalfEdges.ToArray() : boxHalfEdges.ToArray();
                    subMeshes[i].Vertices  = vertices;

                    minY += stepHeight;
                    maxY += stepHeight;
                }
            }


            {
                var subMeshIndex          = subMeshCount - cylinderSubMeshCount;
                var cylinderSurfaceAssets = new CSGSurfaceAsset[3] {
                    surfaceAssets[0], surfaceAssets[1], surfaceAssets[2]
                };
                var cylinderSurfaceDescriptions = new SurfaceDescription[outerSides + 2]; //surfaceDescriptions[0]
                cylinderSurfaceDescriptions[0] = surfaceDescriptions[0];
                cylinderSurfaceDescriptions[1] = surfaceDescriptions[1];
                for (int i = 0; i < outerSides; i++)
                {
                    cylinderSurfaceDescriptions[i + 2] = surfaceDescriptions[2];
                }
                GenerateCylinderSubMesh(subMeshes[subMeshIndex], outerDiameter + nosingWidth, origin.y, origin.y + height, 0, outerSides, cylinderSurfaceAssets, cylinderSurfaceDescriptions);
                subMeshes[subMeshIndex].Operation = CSGOperationType.Intersecting;
            }

            if (haveInnerCyl)
            {
                var subMeshIndex          = subMeshCount - 1;
                var cylinderSurfaceAssets = new CSGSurfaceAsset[3] {
                    surfaceAssets[0], surfaceAssets[1], surfaceAssets[2]
                };
                var cylinderSurfaceDescriptions = new SurfaceDescription[innerSides + 2]; //surfaceDescriptions[0]
                cylinderSurfaceDescriptions[0] = surfaceDescriptions[0];
                cylinderSurfaceDescriptions[1] = surfaceDescriptions[1];
                for (int i = 0; i < innerSides; i++)
                {
                    cylinderSurfaceDescriptions[i + 2] = surfaceDescriptions[2];
                }
                GenerateCylinderSubMesh(subMeshes[subMeshIndex], innerDiameter - nosingWidth, origin.y, origin.y + height, 0, innerSides, cylinderSurfaceAssets, cylinderSurfaceDescriptions);
                subMeshes[subMeshIndex].Operation = CSGOperationType.Subtractive;
            }


            brushMeshAsset.SubMeshes = subMeshes;
            brushMeshAsset.CalculatePlanes();
            brushMeshAsset.SetDirty();
            return(true);
        }
Exemplo n.º 19
0
 /// <summary>
 /// Modeled after half sine wave
 /// </summary>
 public static float SineEaseInOut(float p)
 {
     return(0.5f * (1 - Math.Cos(p * Pi)));
 }
Exemplo n.º 20
0
 /// <summary>
 /// Modeled after half sine wave
 /// </summary>
 public static float EaseInOutSine(this float This)
 {
     return(0.5f * (1 - Math.Cos(This * Pi)));
 }