예제 #1
0
        int ConnectRings(UncheckedMesh m, int ring1Offset, int ring2Offset, int vertCount, int triOffset, bool inverse = false)
        {
            int tri = triOffset;

            for (int i = 0; i < vertCount; ++i)
            {
                //Debug.Log(i);
                if (i < vertCount - 1)
                {
                    m.triangles[tri++] = ring1Offset + i;
                    m.triangles[tri++] = ring1Offset + i + 1;
                    m.triangles[tri++] = ring2Offset + i + 1;

                    m.triangles[tri++] = ring1Offset + i;
                    m.triangles[tri++] = ring2Offset + i + 1;
                    m.triangles[tri++] = ring2Offset + i;
                }
                else
                {
                    //m.triangles[tri++] = ring1Offset + i;
                    //m.triangles[tri++] = ring1Offset;
                    //m.triangles[tri++] = ring2Offset;

                    //m.triangles[tri++] = ring1Offset + i;
                    //m.triangles[tri++] = ring2Offset;
                    //m.triangles[tri++] = ring2Offset + i;
                }
            }
            return(tri);
        }
 private void GenerateCapVertices(UncheckedMesh mesh, float y, int offset)
 {
     for (var cornerNumber = 0; cornerNumber < CornerCount; cornerNumber++)
     {
         CreateCapCornerVertices(mesh, y, offset, cornerNumber);
     }
 }
예제 #3
0
        private void GenerateSideVertices(UncheckedMesh mesh, bool outside, float bottomOuterRadius, float bottomInnerRadius, float topOuterRadius, float topInnerRadius, float height, int nbSides, int verticalPoints, int offset)
        {
            for (int side = 0; side <= nbSides; side++)
            {
                int currSide = side == nbSides ? 0 : side;

                // Angle around the part, offset to align texture with other parts orientation
                float t1 = ((float)currSide / nbSides + 0.25f) * 2f * Mathf.PI;

                for (int verticalPoint = 0; verticalPoint <= verticalPoints; verticalPoint++)
                {
                    float   currFrac = (float)verticalPoint / verticalPoints;
                    float   xLength  = outside ? (topOuterRadius + currFrac * (bottomOuterRadius - topOuterRadius)) : (topInnerRadius + currFrac * (bottomInnerRadius - topInnerRadius));
                    Vector3 xVector  = Quaternion.AngleAxis(-t1 * Mathf.Rad2Deg, Vector3.up) * new Vector3((outside ? 1:1), 0) * xLength;
                    Vector3 yVector  = Vector3.up * (0.5f - currFrac) * height;

                    mesh.vertices[offset + ((verticalPoints + 1) * side + verticalPoint)] = xVector + yVector;
                    Vector3 normalInPlane = new Vector3(Mathf.Cos(t1), 0f, Mathf.Sin(t1)) * (outside ? 1 : -1);
                    Vector3 normal        = (normalInPlane * height + Vector3.up * (outside ? (bottomOuterRadius - topOuterRadius) : (topInnerRadius - bottomInnerRadius))).normalized;
                    mesh.normals[offset + ((verticalPoints + 1) * side + verticalPoint)]  = normal;
                    mesh.tangents[offset + ((verticalPoints + 1) * side + verticalPoint)] = new Vector4(-Mathf.Sin(t1), 0, Mathf.Cos(t1), (outside ? -1 : 1));
                    mesh.uv[offset + ((verticalPoints + 1) * side + verticalPoint)]       = new Vector2((float)side / nbSides * (outside ? 1 : -1), 1 - currFrac);
                }
            }
        }
예제 #4
0
        private void GenerateMeshes(float bottomOuterRadius, float bottomInnerRadius, float topOuterRadius, float topInnerRadius, float height, int nbSides)
        {
            float         verticalpointDensity  = 12f;
            int           outsideVerticalPoints = (int)Math.Floor(Mathf.Abs(bottomOuterRadius - topOuterRadius) * verticalpointDensity) + 2;
            int           insideVerticalPoints  = (int)Math.Floor(Mathf.Abs(bottomInnerRadius - topInnerRadius) * verticalpointDensity) + 2;
            UncheckedMesh sideMesh = new UncheckedMesh((outsideVerticalPoints + insideVerticalPoints) * (nbSides + 1), (outsideVerticalPoints + insideVerticalPoints - 2) * 3 * (nbSides + 1));

            GenerateSideVertices(sideMesh, true, bottomOuterRadius, bottomInnerRadius, topOuterRadius, topInnerRadius, height, nbSides, outsideVerticalPoints - 1, 0);
            GenerateSideVertices(sideMesh, false, bottomOuterRadius, bottomInnerRadius, topOuterRadius, topInnerRadius, height, nbSides, insideVerticalPoints - 1, outsideVerticalPoints * (nbSides + 1));
            GenerateSideTriangles(sideMesh, true, nbSides, outsideVerticalPoints, 0, 0);
            GenerateSideTriangles(sideMesh, false, nbSides, insideVerticalPoints, outsideVerticalPoints * (nbSides + 1), (outsideVerticalPoints - 1) * 6 * (nbSides + 1));

            var tankULength = numSides * NormSideLength * (topOuterRadius + bottomOuterRadius) * 2;
            var tankVLength = length;

            RaiseChangeTextureScale("sides", PPart.legacyTextureHandler.SidesMaterial, new Vector2(tankULength, tankVLength));
            WriteToAppropriateMesh(sideMesh, PPart.SidesIconMesh, SidesMesh);

            UncheckedMesh capMesh = new UncheckedMesh(4 * (nbSides + 1), 4 * (nbSides + 1));

            GenerateCapVertices(capMesh, true, topOuterRadius, topInnerRadius, height, nbSides, 0);
            GenerateCapVertices(capMesh, false, bottomOuterRadius, bottomInnerRadius, height, nbSides, 2 * (nbSides + 1));
            GenerateCapTriangles(capMesh, true, nbSides, 0, 0);
            GenerateCapTriangles(capMesh, false, nbSides, 2 * (nbSides + 1), 6 * (nbSides + 1));
            WriteToAppropriateMesh(capMesh, PPart.EndsIconMesh, EndsMesh);
        }
예제 #5
0
        private void GenerateSideVertices(UncheckedMesh mesh, bool outside, float revolutionRadius, float majorFeatureRadius, float height, float filletRadius, int pointsInProfile, int nbSides, int offset)
        {
            int pointsInCornerProfile = pointsInProfile / 2;

            #region Vertices
            float _2pi = Mathf.PI * 2f;
            for (int side = 0; side <= nbSides; side++)
            {
                int currSide = side == nbSides ? 0 : side;

                float   t1 = ((float)currSide / nbSides + 0.25f) * 2f * Mathf.PI;
                Vector3 r1 = new Vector3(Mathf.Cos(t1) * revolutionRadius, 0f, Mathf.Sin(t1) * revolutionRadius);

                foreach (bool top in new [] { true, false })
                {
                    for (int profilePoint = 0; profilePoint < pointsInCornerProfile; profilePoint++)
                    {
                        Vector3 xVector = Quaternion.AngleAxis(-t1 * Mathf.Rad2Deg, Vector3.up) * new Vector3((outside ? 1:-1), 0) * (majorFeatureRadius - filletRadius * (1 - Mathf.Sin(((float)profilePoint / (pointsInCornerProfile - 1) + (top ? 0:1)) * Mathf.PI / 2)));
                        Vector3 yVector = Vector3.up * (top ? 1:-1) * (height / 2 - filletRadius * (1 - Mathf.Cos(((float)profilePoint / (pointsInCornerProfile - 1) - (top ? 0:1)) * Mathf.PI / 2)));

                        mesh.vertices[offset + (2 * side + (top?0:1)) * pointsInCornerProfile + profilePoint] = r1 + xVector + yVector;
                        Vector3 normalInPlane = new Vector3(Mathf.Cos(t1), 0f, Mathf.Sin(t1)) * (outside ? 1:-1) * (Mathf.Sin(((float)profilePoint / (pointsInCornerProfile - 1) + (top ? 0f:1f)) * Mathf.PI / 2));
                        Vector3 normalUp      = Vector3.up * (Mathf.Cos(((float)profilePoint / (pointsInCornerProfile - 1) + (top ? 0f:1f)) * Mathf.PI / 2));
                        Vector3 normal        = (normalInPlane + normalUp).normalized;
                        mesh.normals[offset + (2 * side + (top?0:1)) * pointsInCornerProfile + profilePoint]  = normal;
                        mesh.tangents[offset + (2 * side + (top?0:1)) * pointsInCornerProfile + profilePoint] = new Vector4(-Mathf.Sin(t1), 0, Mathf.Cos(t1), (outside?-1:1));
                        float distanceIntoBend = (float)profilePoint / (pointsInCornerProfile - 1) * _2pi / 4 * filletRadius;
                        mesh.uv[offset + (2 * side + (top?0:1)) * pointsInCornerProfile + profilePoint] = new Vector2((float)side / nbSides, 1 - (distanceIntoBend + (top?0:1) * (height + filletRadius * (_2pi / 4 - 2))) / (height + filletRadius * (_2pi / 2 - 2)));
                    }
                }
            }
            #endregion
        }
예제 #6
0
            /// <summary>
            /// writes this.totVerticies + 1 xy, verticies, and tangents and this.totVerticies triangles to the passed arrays for a single endcap.
            /// Callers will need to fill the normals. This will be { 0, 1, 0 } for pt endcap, and { 0, -1, 0 } for bottom.
            /// </summary>
            /// <param name="dia">diameter of circle</param>
            /// <param name="y">y dimension for points</param>
            /// <param name="up">If this endcap faces up</param>
            /// <param name="vOff">offset into xy, verticies, and normal arrays to begin at</param>
            /// <param name="to">offset into triangles array</param>
            /// <param name="m">Mesh to write into</param>
            /// <param name="odd">If this is an odd row</param>
            public void WriteEndcap(float dia, float y, bool up, int vOff, int to, UncheckedMesh m, bool odd)
            {
                Complete();

                int o = odd ? 1 : 0;

                for (int i = 0; i <= subdivCount; ++i)
                {
                    int o0 = vOff + i;
                    m.uv[o0]        = new Vector2((-xCoords[o][i] + 1f) * 0.5f, (-zCoords[o][i] + 1f) * 0.5f);
                    m.verticies[o0] = new Vector3(xCoords[o][i] * dia * 0.5f, y, zCoords[o][i] * dia * 0.5f);

                    int o1 = vOff + i + subdivCount + 1;
                    m.uv[o1]        = new Vector2((zCoords[o][i] + 1f) * 0.5f, (-xCoords[o][i] + 1f) * 0.5f);
                    m.verticies[o1] = new Vector3(-zCoords[o][i] * dia * 0.5f, y, xCoords[o][i] * dia * 0.5f);

                    int o2 = vOff + i + 2 * (subdivCount + 1);
                    m.uv[o2]        = new Vector2((xCoords[o][i] + 1f) * 0.5f, (zCoords[o][i] + 1f) * 0.5f);
                    m.verticies[o2] = new Vector3(-xCoords[o][i] * dia * 0.5f, y, -zCoords[o][i] * dia * 0.5f);

                    int o3 = vOff + i + 3 * (subdivCount + 1);
                    m.uv[o3]        = new Vector2((-zCoords[o][i] + 1f) * 0.5f, (xCoords[o][i] + 1f) * 0.5f);
                    m.verticies[o3] = new Vector3(zCoords[o][i] * dia * 0.5f, y, -xCoords[o][i] * dia * 0.5f);

                    m.tangents[o0] = m.tangents[o1] = m.tangents[o2] = m.tangents[o3] = new Vector4(-1, 0, 0, up ? 1 : -1);
                    m.normals[o0]  = m.normals[o1] = m.normals[o2] = m.normals[o3] = new Vector3(0, up ? 1 : -1, 0);
                }

                for (int i = 1; i < totVertexes - 1; ++i)
                {
                    m.triangles[to++] = vOff;
                    m.triangles[to++] = vOff + i + (up ? 1 : 0);
                    m.triangles[to++] = vOff + i + (up ? 0 : 1);
                }
            }
예제 #7
0
        private void GenerateMeshes(float revolutionRadius, float majorFeatureRadius, float height, float filletRadius, int nbSides)
        {
            float         maxMeshBendError = 0.05f;
            int           pointsperprofile = (int)Math.Max(Mathf.PI * Mathf.Sqrt(Mathf.Sqrt(fillet) / (2f * maxMeshBendError)), 2) * 2;
            UncheckedMesh sideMesh         = new UncheckedMesh(2 * pointsperprofile * (nbSides + 1), (pointsperprofile - 1) * 3 * (nbSides + 1) * 2);

            GenerateSideVertices(sideMesh, true, revolutionRadius, majorFeatureRadius, height, filletRadius, pointsperprofile, nbSides, 0);
            GenerateSideVertices(sideMesh, false, revolutionRadius, majorFeatureRadius, height, filletRadius, pointsperprofile, nbSides, pointsperprofile * (nbSides + 1));
            GenerateSideTriangles(sideMesh, true, nbSides, pointsperprofile, 0, 0);
            GenerateSideTriangles(sideMesh, false, nbSides, pointsperprofile, pointsperprofile * (nbSides + 1), (pointsperprofile - 1) * 2 * 3 * (nbSides + 1));

            var tankULength = numSides * NormSideLength * (revolutionRadius + majorFeatureRadius) * 4;
            var tankVLength = length;

            RaiseChangeTextureScale("sides", PPart.legacyTextureHandler.SidesMaterial, new Vector2(tankULength, tankVLength));
            WriteToAppropriateMesh(sideMesh, PPart.SidesIconMesh, SidesMesh);

            UncheckedMesh capMesh = new UncheckedMesh(2 * 2 * (nbSides + 1), 2 * 2 * (nbSides + 1));

            GenerateCapVertices(capMesh, true, revolutionRadius, majorFeatureRadius - filletRadius, height, nbSides, 0);
            GenerateCapVertices(capMesh, false, revolutionRadius, majorFeatureRadius - filletRadius, height, nbSides, 2 * (nbSides + 1));
            GenerateCapTriangles(capMesh, true, nbSides, 0, 0);
            GenerateCapTriangles(capMesh, false, nbSides, 2 * (nbSides + 1), 2 * 3 * (nbSides + 1));
            WriteToAppropriateMesh(capMesh, PPart.EndsIconMesh, EndsMesh);
        }
        private void SetSideVertexData(UncheckedMesh mesh, float v, int cornerNumber, float cornerAngle, int vertexCornerIndex, int vertexIndex)
        {
            mesh.uv[vertexIndex] = new Vector2((float)cornerNumber / CornerCount, v);

            var normalAngle = cornerAngle + CornerCenterCornerAngle / 2 * (-1 + 2 * vertexCornerIndex);
            var normal      = CreateVectorFromAngle(normalAngle, 0, 1);

            mesh.normals[vertexIndex]  = normal;
            mesh.tangents[vertexIndex] = new Vector4(normal.z, 0, -normal.x, 1f);
        }
        private void GenerateCapMesh()
        {
            var mesh = new UncheckedMesh(CornerCount * 2, TrianglesPerCap * 2);

            GenerateCapVertices(mesh, -HalfHeight, 0);
            GenerateCapVertices(mesh, HalfHeight, CornerCount);
            GenerateCapTriangles(mesh, false, 0);
            GenerateCapTriangles(mesh, true, TrianglesPerCap);

            WriteToAppropriateMesh(mesh, PPart.EndsIconMesh, EndsMesh);
        }
 private static void WriteToAppropriateMesh(UncheckedMesh mesh, Mesh iconMesh, Mesh normalMesh)
 {
     if (HighLogic.LoadedScene == GameScenes.LOADING)
     {
         mesh.WriteTo(iconMesh);
     }
     else
     {
         mesh.WriteTo(normalMesh);
     }
 }
        private void GenerateCapTriangles(UncheckedMesh mesh, bool up, int triangleOffset)
        {
            var triangleIndexOffset = triangleOffset * 3;
            var vertexOffset        = up ? CornerCount : 0;

            for (var i = 0; i < TrianglesPerCap; i++)
            {
                mesh.triangles[i * 3 + triangleIndexOffset]     = vertexOffset;
                mesh.triangles[i * 3 + 1 + triangleIndexOffset] = (up ? i + 2 : i + 1) + vertexOffset;
                mesh.triangles[i * 3 + 2 + triangleIndexOffset] = (up ? i + 1 : i + 2) + vertexOffset;
            }
        }
        private void GenerateSideMesh()
        {
            var mesh = new UncheckedMesh(SideVerticesPerCap * 2, SideTriangles);

            GenerateSideVertices(mesh, -HalfHeight, 0, 0);
            GenerateSideVertices(mesh, HalfHeight, 1, SideVerticesPerCap);
            GenerateSideTriangles(mesh, SideVerticesPerCap, 2);

            var tankULength = CornerCount * NormSideLength * InnerDiameter * 2;
            var tankVLength = Length;

            RaiseChangeTextureScale("sides", PPart.legacyTextureHandler.SidesMaterial, new Vector2(tankULength, tankVLength));
            WriteToAppropriateMesh(mesh, PPart.SidesIconMesh, SidesMesh);
        }
        private void CreateCapCornerVertices(UncheckedMesh mesh, float y, int offset, int cornerNumber)
        {
            var cornerAngle       = GetCornerAngle(cornerNumber);
            var cornerVector      = CreateVectorFromAngle(cornerAngle, y, OuterRadius);
            var verticesPerCorner = 1;

            for (var vertexCornerIndex = 0; vertexCornerIndex < verticesPerCorner; vertexCornerIndex++)
            {
                var vertexIndex = offset + cornerNumber * verticesPerCorner + vertexCornerIndex;
                mesh.vertices[vertexIndex] = cornerVector;

                SetCapVertexData(mesh, cornerVector, vertexIndex, y > 0);
            }
        }
        private void GenerateSideTriangles(UncheckedMesh mesh, int numberOfCapVertices, int verticesPerCorner)
        {
            for (var i = 0; i < CornerCount; i++)
            {
                var baseVertex = i * verticesPerCorner + verticesPerCorner - 1;
                mesh.triangles[i * 6]     = baseVertex;
                mesh.triangles[i * 6 + 1] = baseVertex + numberOfCapVertices;
                mesh.triangles[i * 6 + 2] = (baseVertex + 1) % numberOfCapVertices;

                mesh.triangles[i * 6 + 3] = (baseVertex + 1) % numberOfCapVertices;
                mesh.triangles[i * 6 + 4] = baseVertex + numberOfCapVertices;
                mesh.triangles[i * 6 + 5] = (baseVertex + 1) % numberOfCapVertices + numberOfCapVertices;
            }
        }
예제 #15
0
        private void GenerateCapTriangles(UncheckedMesh mesh, bool up, int nbSides, int vertexOffset, int triangleOffset)
        {
            int i = 0;

            for (int side = 0; side < nbSides; side++)
            {
                mesh.triangles[triangleOffset + i++] = vertexOffset + side * 2;
                mesh.triangles[triangleOffset + i++] = vertexOffset + side * 2 + (up ? 1 : 2);
                mesh.triangles[triangleOffset + i++] = vertexOffset + side * 2 + (up ? 2 : 1);

                mesh.triangles[triangleOffset + i++] = vertexOffset + side * 2 + (up ? 1 : 3);
                mesh.triangles[triangleOffset + i++] = vertexOffset + side * 2 + (up ? 3 : 1);
                mesh.triangles[triangleOffset + i++] = vertexOffset + side * 2 + 2;
            }
        }
        private void GenerateColliderMesh()
        {
            var mesh = new UncheckedMesh(CornerCount * 2, SideTriangles + 2 * TrianglesPerCap);

            GenerateCapVertices(mesh, -HalfHeight, 0);
            GenerateCapVertices(mesh, HalfHeight, CornerCount);
            GenerateSideTriangles(mesh, CornerCount, 1);
            GenerateCapTriangles(mesh, false, SideTriangles);
            GenerateCapTriangles(mesh, true, SideTriangles + TrianglesPerCap);

            var colliderMesh = new Mesh();

            mesh.WriteTo(colliderMesh);
            PPart.ColliderMesh = colliderMesh;
        }
        private void CreateSideCornerVertices(UncheckedMesh mesh, float y, float v, int offset, int cornerNumber)
        {
            var cornerAngle       = GetCornerAngle(cornerNumber);
            var cornerVector      = CreateVectorFromAngle(cornerAngle, y, OuterRadius);
            var verticesPerCorner = 2;

            for (var vertexCornerIndex = 0; vertexCornerIndex < verticesPerCorner; vertexCornerIndex++)
            {
                var vertexIndex = offset + cornerNumber * verticesPerCorner + vertexCornerIndex;
                mesh.vertices[vertexIndex] = cornerVector;

                SetSideVertexData(mesh, v, cornerNumber, cornerAngle, vertexCornerIndex, vertexIndex);
            }
            mesh.uv[offset].x = 1;
        }
예제 #18
0
        private void GenerateSideTriangles(UncheckedMesh mesh, bool outside, int nbSides, int pointsInProfile, int vertexOffset, int triangleOffset)
        {
            int i = 0;

            for (int side = 0; side <= nbSides; side++)
            {
                for (int segment = 0; segment <= pointsInProfile - 2; segment++)
                {
                    int current = segment + side * pointsInProfile;
                    int next    = segment + (side < nbSides ? (side + 1) * pointsInProfile : 0);

                    mesh.triangles[triangleOffset + i++] = vertexOffset + current;
                    mesh.triangles[triangleOffset + i++] = vertexOffset + next + (outside ? 0 : 1);
                    mesh.triangles[triangleOffset + i++] = vertexOffset + next + (outside ? 1 : 0);

                    mesh.triangles[triangleOffset + i++] = vertexOffset + current + (outside ? 0 : 1);
                    mesh.triangles[triangleOffset + i++] = vertexOffset + next + 1;
                    mesh.triangles[triangleOffset + i++] = vertexOffset + current + (outside ? 1 : 0);
                }
            }
        }
예제 #19
0
        private void GenerateCapVertices(UncheckedMesh mesh, bool top, float revolutionRadius, float majorFeatureRadius, float height, int nbSides, int offset)
        {
            #region Vertices
            float _2pi = Mathf.PI * 2f;
            for (int side = 0; side <= nbSides; side++)
            {
                int currSide = side == nbSides ? 0 : side;

                float   t1 = (float)currSide / nbSides * _2pi;
                Vector3 r1 = new Vector3(Mathf.Cos(t1) * revolutionRadius, 0f, Mathf.Sin(t1) * revolutionRadius);
                Vector3 r2 = Quaternion.AngleAxis(-t1 * Mathf.Rad2Deg, Vector3.up) * new Vector3(majorFeatureRadius, 0);

                mesh.vertices[offset + 2 * side]     = r1 + r2 + Vector3.up * height / 2 * (top ? 1:-1);
                mesh.vertices[offset + 2 * side + 1] = r1 - r2 + Vector3.up * height / 2 * (top ? 1:-1);
                // ugly, but quick to write
                mesh.normals[offset + 2 * side]      = Vector3.up * (top ? 1:-1);
                mesh.normals[offset + 2 * side + 1]  = Vector3.up * (top ? 1:-1);
                mesh.uv[offset + 2 * side]           = new Vector2(Mathf.Cos(t1) * (top ? 1:-1), Mathf.Sin(t1)) / 2 + new Vector2(0.5f, 0.5f);
                mesh.uv[offset + 2 * side + 1]       = new Vector2(Mathf.Cos(t1) * (top ? 1:-1), Mathf.Sin(t1)) * (revolutionRadius - majorFeatureRadius) / (revolutionRadius + majorFeatureRadius) / 2 + new Vector2(0.5f, 0.5f);
                mesh.tangents[offset + 2 * side]     = new Vector4(1, 0, 0, 1f);
                mesh.tangents[offset + 2 * side + 1] = new Vector4(1, 0, 0, 1f);
            }
            #endregion
        }
예제 #20
0
        private void GenerateCapVertices(UncheckedMesh mesh, bool top, float outsideRadius, float insideRadius, float height, int nbSides, int offset)
        {
            for (int side = 0; side <= nbSides; side++)
            {
                int currSide = side == nbSides ? 0 : side;

                // Angle around the part, offset to align texture with other parts orientation
                float t1 = ((float)currSide / nbSides + 0.25f) * 2f * Mathf.PI;

                Vector3 r1 = new Vector3(Mathf.Cos(t1) * outsideRadius, 0f, Mathf.Sin(t1) * outsideRadius);
                Vector3 r2 = new Vector3(Mathf.Cos(t1) * insideRadius, 0f, Mathf.Sin(t1) * insideRadius);

                mesh.vertices[offset + 2 * side]     = r1 + Vector3.up * height / 2 * (top ? 1 : -1);
                mesh.vertices[offset + 2 * side + 1] = r2 + Vector3.up * height / 2 * (top ? 1 : -1);

                mesh.normals[offset + 2 * side]     = Vector3.up * (top ? 1 : -1);
                mesh.normals[offset + 2 * side + 1] = Vector3.up * (top ? 1 : -1);

                mesh.uv[offset + 2 * side]           = new Vector2(Mathf.Cos(t1) * (top ? 1 : -1), Mathf.Sin(t1)) / 2 + new Vector2(0.5f, 0.5f);
                mesh.uv[offset + 2 * side + 1]       = new Vector2(Mathf.Cos(t1) * (top ? 1 : -1), Mathf.Sin(t1)) * (insideRadius) / (outsideRadius) / 2 + new Vector2(0.5f, 0.5f);
                mesh.tangents[offset + 2 * side]     = new Vector4(1, 0, 0, 1f);
                mesh.tangents[offset + 2 * side + 1] = new Vector4(1, 0, 0, 1f);
            }
        }
예제 #21
0
        private void GenerateMeshes(float outerRadius, float innerRadius, float height, int nbSides)
        {
            int           verticalPoints = 2;
            UncheckedMesh sideMesh       = new UncheckedMesh(verticalPoints * 2 * (nbSides + 1), (verticalPoints - 1) * 6 * (nbSides + 1));

            GenerateSideVertices(sideMesh, true, outerRadius, innerRadius, height, nbSides, verticalPoints - 1, 0);
            GenerateSideVertices(sideMesh, false, outerRadius, innerRadius, height, nbSides, verticalPoints - 1, verticalPoints * (nbSides + 1));
            GenerateSideTriangles(sideMesh, true, nbSides, verticalPoints, 0, 0);
            GenerateSideTriangles(sideMesh, false, nbSides, verticalPoints, verticalPoints * (nbSides + 1), (verticalPoints - 1) * 6 * (nbSides + 1));

            var tankULength = numSides * NormSideLength * outerRadius * 2;
            var tankVLength = length;

            RaiseChangeTextureScale("sides", PPart.legacyTextureHandler.SidesMaterial, new Vector2(tankULength, tankVLength));
            WriteToAppropriateMesh(sideMesh, PPart.SidesIconMesh, SidesMesh);

            UncheckedMesh capMesh = new UncheckedMesh(4 * (nbSides + 1), 4 * (nbSides + 1));

            GenerateCapVertices(capMesh, true, outerRadius, innerRadius, height, nbSides, 0);
            GenerateCapVertices(capMesh, false, outerRadius, innerRadius, height, nbSides, 2 * (nbSides + 1));
            GenerateCapTriangles(capMesh, true, nbSides, 0, 0);
            GenerateCapTriangles(capMesh, false, nbSides, 2 * (nbSides + 1), 6 * (nbSides + 1));
            WriteToAppropriateMesh(capMesh, PPart.EndsIconMesh, EndsMesh);
        }
예제 #22
0
            /// <summary>
            /// Write vertexes for the circle.
            /// </summary>
            /// <param name="diameter">diameter of the circle</param>
            /// <param name="y">y coordinate</param>
            /// <param name="norm">unit normal vector along the generator curve for increasing y. The y param becomes the y of the normal, the x multiplies the normals to the circle</param>
            /// <param name="v">v coordinate for UV</param>
            /// <param name="off">offset into following arrays</param>
            /// <param name="xy">UVs to copy into</param>
            /// <param name="verticies">vertexes</param>
            /// <param name="normals">normals</param>
            /// <param name="tangents">tangents</param>
            public void WriteVertexes(float diameter, float y, float v, Vector2 norm, int off, bool odd, UncheckedMesh m)
            {
                Complete();

                int o = odd ? 1 : 0;

                for (int i = 0; i <= subdivCount; ++i)
                {
                    int o0 = off + i;
                    m.uv[o0] = new Vector2(uCoords[o][i], v);
                    m.verticies[o0] = new Vector3(xCoords[o][i] * 0.5f * diameter, y, zCoords[o][i] * 0.5f * diameter);
                    m.normals[o0] = new Vector3(xCoords[o][i] * norm.x, norm.y, zCoords[o][i] * norm.x);
                    m.tangents[o0] = new Vector4(zCoords[o][i], 0, -xCoords[o][i], -1.0f);
                    //MonoBehaviour.print("Vertex #" + i + " off=" + o0 + " u=" + xy[o0][0] + " coords=" + verticies[o0]);

                    int o1 = off + i + subdivCount + 1;
                    m.uv[o1] = new Vector2(uCoords[o][i] + 0.25f, v);
                    m.verticies[o1] = new Vector3(-zCoords[o][i] * 0.5f * diameter, y, xCoords[o][i] * 0.5f * diameter);
                    m.normals[o1] = new Vector3(-zCoords[o][i] * norm.x, norm.y, xCoords[o][i] * norm.x);
                    m.tangents[o1] = new Vector4(xCoords[o][i], 0, zCoords[o][i], -1.0f);

                    int o2 = off + i + 2 * (subdivCount + 1);
                    m.uv[o2] = new Vector2(uCoords[o][i] + 0.50f, v);
                    m.verticies[o2] = new Vector3(-xCoords[o][i] * 0.5f * diameter, y, -zCoords[o][i] * 0.5f * diameter);
                    m.normals[o2] = new Vector3(-xCoords[o][i] * norm.x, norm.y, -zCoords[o][i] * norm.x);
                    m.tangents[o2] = new Vector4(-zCoords[o][i], 0, xCoords[o][i], -1.0f);

                    int o3 = off + i + 3 * (subdivCount + 1);
                    m.uv[o3] = new Vector2(uCoords[o][i] + 0.75f, v);
                    m.verticies[o3] = new Vector3(zCoords[o][i] * 0.5f * diameter, y, -xCoords[o][i] * 0.5f * diameter);
                    m.normals[o3] = new Vector3(zCoords[o][i] * norm.x, norm.y, -xCoords[o][i] * norm.x);
                    m.tangents[o3] = new Vector4(-xCoords[o][i], 0, -zCoords[o][i], -1.0f);
                }

                // write the wrapping vertex. This is identical to the first one except for u coord += 1
                int lp = off + totVertexes;
                m.uv[lp] = new Vector2(uCoords[o][0] + 1.0f, v);
                m.verticies[lp] = m.verticies[off];
                m.normals[lp] = m.normals[off];
                m.tangents[lp] = m.tangents[off];
            }
예제 #23
0
        void UpdateFairing()
        {
            Transform fairing     = part.FindModelTransform("fairing");
            Mesh      fairingMesh = fairing.GetComponent <MeshFilter>().mesh;

            if (useFairing && fairingMesh is Mesh && PPart?.CurrentShape is ProceduralAbstractSoRShape shape)
            {
                Vector3[] topEndcapVerticies = shape.GetEndcapVerticies(true);

                Vector3[] topInner = new Vector3[topEndcapVerticies.Length + 1];

                topEndcapVerticies.CopyTo(topInner, 0);
                topInner[topEndcapVerticies.Length] = topEndcapVerticies[0];

                int       vertCount = topInner.Length;
                Vector3[] topOuter  = (Vector3[])topInner.Clone();

                for (int i = 0; i < vertCount; ++i)
                {
                    float r           = topInner[i].magnitude;
                    float r_          = r + fairingThickness;
                    float scaleFactor = r_ / r;
                    topOuter[i].x *= scaleFactor;
                    topOuter[i].z *= scaleFactor;
                }

                Vector3[] sideTop    = (Vector3[])topOuter.Clone();
                Vector3[] sideBottom = (Vector3[])sideTop.Clone();

                Vector3[] bottomInner = (Vector3[])topInner.Clone();
                Vector3[] bottomOuter = (Vector3[])topOuter.Clone();

                for (int i = 0; i < vertCount; ++i)
                {
                    if (bottomNode != null)
                    {
                        sideBottom[i].y  = bottomNode.position.y;
                        bottomInner[i].y = bottomNode.position.y;
                        bottomOuter[i].y = bottomNode.position.y;
                    }
                }

                Vector3[] innerSideTop    = (Vector3[])topInner.Clone();
                Vector3[] innerSideBottom = (Vector3[])bottomInner.Clone();

                int topInnerStart        = 0;
                int topOuterStart        = topInnerStart + vertCount;
                int sideTopStart         = topOuterStart + vertCount;
                int sideBottomStart      = sideTopStart + vertCount;
                int bottomInnerStart     = sideBottomStart + vertCount;
                int bottomOuterStart     = bottomInnerStart + vertCount;
                int innerSideTopStart    = bottomOuterStart + vertCount;
                int innerSideBottomStart = innerSideTopStart + vertCount;

                UncheckedMesh m = new UncheckedMesh(vertCount * 8, vertCount * 8 * 6);
                //int tri = 0;
                for (int i = 0; i < vertCount; ++i)
                {
                    m.vertices[topInnerStart + i]        = topInner[i];
                    m.vertices[topOuterStart + i]        = topOuter[i];
                    m.vertices[sideTopStart + i]         = sideTop[i];
                    m.vertices[sideBottomStart + i]      = sideBottom[i];
                    m.vertices[bottomInnerStart + i]     = bottomInner[i];
                    m.vertices[bottomOuterStart + i]     = bottomOuter[i];
                    m.vertices[innerSideTopStart + i]    = innerSideTop[i];
                    m.vertices[innerSideBottomStart + i] = innerSideBottom[i];

                    m.normals[topInnerStart + i] = new Vector3(0.0f, 1.0f, 0.0f);
                    m.normals[topOuterStart + i] = new Vector3(0.0f, 1.0f, 0.0f);

                    m.normals[sideTopStart + i]    = m.vertices[sideTopStart + i].xz().normalized;
                    m.normals[sideBottomStart + i] = m.vertices[sideBottomStart + i].xz().normalized;

                    m.normals[bottomInnerStart + i] = new Vector3(0.0f, -1.0f, 0.0f);
                    m.normals[bottomOuterStart + i] = new Vector3(0.0f, -1.0f, 0.0f);

                    m.normals[innerSideTopStart + i]    = -m.vertices[innerSideTopStart + i].xz().normalized;
                    m.normals[innerSideBottomStart + i] = -m.vertices[innerSideBottomStart + i].xz().normalized;

                    m.uv[topInnerStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);
                    m.uv[topOuterStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);

                    m.uv[sideTopStart + i]    = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);
                    m.uv[sideBottomStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);

                    m.uv[bottomInnerStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);
                    m.uv[bottomOuterStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);

                    m.uv[innerSideTopStart + i]    = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);
                    m.uv[innerSideBottomStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);

                    m.tangents[topInnerStart + i] = Vector3.Cross(m.normals[topInnerStart + i], m.vertices[topInnerStart + i]).xz().normalized.toVec4(-1);
                    m.tangents[topOuterStart + i] = Vector3.Cross(m.normals[topOuterStart + i], m.vertices[topOuterStart + i]).xz().normalized.toVec4(-1);

                    m.tangents[sideTopStart + i]    = Vector3.Cross(m.normals[sideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);
                    m.tangents[sideBottomStart + i] = Vector3.Cross(m.normals[sideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);

                    m.tangents[bottomInnerStart + i] = Vector3.Cross(m.normals[bottomInnerStart + i], m.vertices[topInnerStart + i]).xz().normalized.toVec4(-1);
                    m.tangents[bottomOuterStart + i] = Vector3.Cross(m.normals[bottomOuterStart + i], m.vertices[topOuterStart + i]).xz().normalized.toVec4(-1);

                    m.tangents[innerSideTopStart + i]    = Vector3.Cross(m.normals[innerSideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);
                    m.tangents[innerSideBottomStart + i] = Vector3.Cross(m.normals[innerSideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);
                }

                int triangleOffset = 0;
                triangleOffset = ConnectRings(m, topInnerStart, topOuterStart, vertCount, triangleOffset);
                triangleOffset = ConnectRings(m, sideTopStart, sideBottomStart, vertCount, triangleOffset);
                triangleOffset = ConnectRings(m, bottomOuterStart, bottomInnerStart, vertCount, triangleOffset);
                _ = ConnectRings(m, innerSideBottomStart, innerSideTopStart, vertCount, triangleOffset);

                m.WriteTo(fairingMesh);
                fairingMesh.RecalculateNormals();
            }
            UpdateMass();
        }
예제 #24
0
        void UpdateFairing()
        {
            ProceduralPart ppart = PPart;

            if (useFairing && ppart != null)
            {
                ProceduralAbstractSoRShape shape = ppart.CurrentShape as ProceduralAbstractSoRShape;

                if (shape != null)
                {
                    Vector3[] topEndcapVerticies = shape.GetEndcapVerticies(true);

                    Vector3[] topInner = new Vector3[topEndcapVerticies.Length + 1];

                    topEndcapVerticies.CopyTo(topInner, 0);
                    topInner[topEndcapVerticies.Length] = topEndcapVerticies[0];

                    int vertCount = topInner.Length;

                    //foreach (Vector3 v in topInner)
                    //    Debug.Log(v);

                    Vector3[] topOuter = (Vector3[])topInner.Clone();

                    for (int i = 0; i < vertCount; ++i)
                    {
                        float r           = topInner[i].magnitude;
                        float r_          = r + fairingThickness;
                        float scaleFactor = r_ / r;
                        topOuter[i].x *= scaleFactor;
                        topOuter[i].z *= scaleFactor;
                    }

                    TextureScale.x = topOuter[0].magnitude * 2 * Mathf.PI;

                    Vector3[] sideTop    = (Vector3[])topOuter.Clone();
                    Vector3[] sideBottom = (Vector3[])sideTop.Clone();

                    Vector3[] bottomInner = (Vector3[])topInner.Clone();
                    Vector3[] bottomOuter = (Vector3[])topOuter.Clone();



                    for (int i = 0; i < vertCount; ++i)
                    {
                        if (bottomNode != null)
                        {
                            sideBottom[i].y  = bottomNode.position.y;
                            bottomInner[i].y = bottomNode.position.y;
                            bottomOuter[i].y = bottomNode.position.y;
                        }
                    }

                    TextureScale.y = Mathf.Abs(topOuter[0].y - bottomOuter[0].y);

                    Vector3[] innerSideTop    = (Vector3[])topInner.Clone();
                    Vector3[] innerSideBottom = (Vector3[])bottomInner.Clone();

                    int topInnerStart        = 0;
                    int topOuterStart        = topInnerStart + vertCount;
                    int sideTopStart         = topOuterStart + vertCount;
                    int sideBottomStart      = sideTopStart + vertCount;
                    int bottomInnerStart     = sideBottomStart + vertCount;
                    int bottomOuterStart     = bottomInnerStart + vertCount;
                    int innerSideTopStart    = bottomOuterStart + vertCount;
                    int innerSideBottomStart = innerSideTopStart + vertCount;

                    UncheckedMesh m = new UncheckedMesh(vertCount * 8, vertCount * 8 * 6);
                    //int tri = 0;
                    for (int i = 0; i < vertCount; ++i)
                    {
                        m.verticies[topInnerStart + i]        = topInner[i];
                        m.verticies[topOuterStart + i]        = topOuter[i];
                        m.verticies[sideTopStart + i]         = sideTop[i];
                        m.verticies[sideBottomStart + i]      = sideBottom[i];
                        m.verticies[bottomInnerStart + i]     = bottomInner[i];
                        m.verticies[bottomOuterStart + i]     = bottomOuter[i];
                        m.verticies[innerSideTopStart + i]    = innerSideTop[i];
                        m.verticies[innerSideBottomStart + i] = innerSideBottom[i];

                        m.normals[topInnerStart + i] = new Vector3(0.0f, 1.0f, 0.0f);
                        m.normals[topOuterStart + i] = new Vector3(0.0f, 1.0f, 0.0f);

                        m.normals[sideTopStart + i]    = m.verticies[sideTopStart + i].xz().normalized;
                        m.normals[sideBottomStart + i] = m.verticies[sideBottomStart + i].xz().normalized;

                        m.normals[bottomInnerStart + i] = new Vector3(0.0f, -1.0f, 0.0f);
                        m.normals[bottomOuterStart + i] = new Vector3(0.0f, -1.0f, 0.0f);

                        m.normals[innerSideTopStart + i]    = -m.verticies[innerSideTopStart + i].xz().normalized;
                        m.normals[innerSideBottomStart + i] = -m.verticies[innerSideBottomStart + i].xz().normalized;

                        m.uv[topInnerStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);
                        m.uv[topOuterStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);

                        m.uv[sideTopStart + i]    = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);
                        m.uv[sideBottomStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);

                        m.uv[bottomInnerStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);
                        m.uv[bottomOuterStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);

                        m.uv[innerSideTopStart + i]    = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);
                        m.uv[innerSideBottomStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);

                        m.tangents[topInnerStart + i] = Vector3.Cross(m.normals[topInnerStart + i], m.verticies[topInnerStart + i]).xz().normalized.toVec4(-1);
                        m.tangents[topOuterStart + i] = Vector3.Cross(m.normals[topOuterStart + i], m.verticies[topOuterStart + i]).xz().normalized.toVec4(-1);

                        m.tangents[sideTopStart + i]    = Vector3.Cross(m.normals[sideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);
                        m.tangents[sideBottomStart + i] = Vector3.Cross(m.normals[sideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);

                        m.tangents[bottomInnerStart + i] = Vector3.Cross(m.normals[bottomInnerStart + i], m.verticies[topInnerStart + i]).xz().normalized.toVec4(-1);
                        m.tangents[bottomOuterStart + i] = Vector3.Cross(m.normals[bottomOuterStart + i], m.verticies[topOuterStart + i]).xz().normalized.toVec4(-1);

                        m.tangents[innerSideTopStart + i]    = Vector3.Cross(m.normals[innerSideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);
                        m.tangents[innerSideBottomStart + i] = Vector3.Cross(m.normals[innerSideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);

                        //Debug.Log(i +" uv: " + Mathf.InverseLerp(0, vertCount - 1, i));
                    }

                    int triangleOffset = 0;
                    triangleOffset = ConnectRings(m, topInnerStart, topOuterStart, vertCount, 0);
                    triangleOffset = ConnectRings(m, sideTopStart, sideBottomStart, vertCount, triangleOffset);
                    triangleOffset = ConnectRings(m, bottomOuterStart, bottomInnerStart, vertCount, triangleOffset);
                    triangleOffset = ConnectRings(m, innerSideBottomStart, innerSideTopStart, vertCount, triangleOffset);

                    if (fairingMesh != null)
                    {
                        m.WriteTo(fairingMesh);
                        fairingMesh.RecalculateNormals();
                    }
                    else
                    {
                        Debug.Log("no fairing mesh");
                    }
                }
                oldTextureSet = null;
                UpdateTexture();
            }
        }
예제 #25
0
        /// <summary>
        /// Generate the compShape from profile points from pt to bottom.
        /// Note that this list will have extra interpolated points added if the change in radius is high to avoid
        /// texture stretching.
        /// </summary>
        /// <param name="pts"></param>
        protected void WriteMeshes(LinkedList<ProfilePoint> pts)
        {
            if (pts == null || pts.Count < 2)
                return;

            // update nodes
            UpdateNodeSize(pts.First(), bottomNodeName);
            UpdateNodeSize(pts.Last(), topNodeName);

            // Move attachments first, before subdividing
            MoveAttachments(pts);

            // Horizontal profile point subdivision
            SubdivHorizontal(pts);

            // Tank stats
            float tankULength = 0;
            float tankVLength = 0;

            int nVrt = 0;
            int nTri = 0;
            int nColVrt = 0;
            int nColTri = 0;
            bool customCollider = false;

            ProfilePoint first = pts.First.Value;
            ProfilePoint last = pts.Last.Value;

            if (!first.inCollider || !last.inCollider)
                throw new InvalidOperationException("First and last profile points must be used in the collider");

            foreach (ProfilePoint pt in pts)
            {
                customCollider = customCollider || pt.customCollider;

                if (pt.inRender)
                {
                    nVrt += pt.circ.totVertexes + 1;
                    // one for above, one for below
                    nTri += 2 * pt.circ.totVertexes;
                }

                if (pt.inCollider)
                {
                    nColVrt += pt.colliderCirc.totVertexes + 1;
                    nColTri += 2 * pt.colliderCirc.totVertexes;
                }
            }
            // Have double counted for the first and last circles.
            nTri -= first.circ.totVertexes + last.circ.totVertexes;
            nColTri -= first.colliderCirc.totVertexes + last.colliderCirc.totVertexes;

            UncheckedMesh m = new UncheckedMesh(nVrt, nTri);

            float sumDiameters = 0;
            //Debug.LogWarning("Display mesh vert=" + nVrt + " tris=" + nTri);

            bool odd = false;
            {
                ProfilePoint prev = null;
                int off = 0, prevOff = 0;
                int tOff = 0;
                foreach (ProfilePoint pt in pts)
                {
                    if (!pt.inRender)
                        continue;

                    pt.circ.WriteVertexes(diameter: pt.dia, y: pt.y, v: pt.v, norm: pt.norm, off: off, m: m, odd: odd);
                    if (prev != null)
                    {
                        CirclePoints.WriteTriangles(prev.circ, prevOff, pt.circ, off, m.triangles, tOff * 3, !odd);
                        tOff += prev.circ.totVertexes + pt.circ.totVertexes;

                        // Deprecated: Volume has been moved up to callers. This way we can use the idealized rather than aproximate volume
                        // Work out the area of the truncated cone

                        // integral_y1^y2 pi R(y)^2 dy   where R(y) = ((r2-r1)(y-y1))/(r2-r1) + r1   Integrate circles along a line
                        // integral_y1^y2 pi ( ((r2-r1)(y-y1))/(r2-r1) + r1) ^2 dy                Substituted in formula.
                        // == -1/3 pi (y1-y2) (r1^2+r1*r2+r2^2)                                   Do the calculus
                        // == -1/3 pi (y1-y2) (d1^2/4+d1*d2/4+d2^2/4)                             r = d/2
                        // == -1/12 pi (y1-y2) (d1^2+d1*d2+d2^2)                                  Take out the factor
                        //volume += (Mathf.PI * (pt.y - prev.y) * (prev.dia * prev.dia + prev.dia * pt.dia + pt.dia * pt.dia)) / 12f;

                        float dy = (pt.y - prev.y);
                        float dr = (prev.dia - pt.dia) * 0.5f;

                        //print("dy=" + dy + " dr=" + dr + " len=" + Mathf.Sqrt(dy * dy + dr * dr).ToString("F3"));
                        tankVLength += Mathf.Sqrt(dy * dy + dr * dr);

                        // average diameter weighted by dy
                        sumDiameters += (pt.dia + prev.dia) * dy;
                    }

                    prev = pt;
                    prevOff = off;
                    off += pt.circ.totVertexes + 1;
                    odd = !odd;
                }
            }

            // Use the weighted average diameter across segments to set the ULength
            tankULength = Mathf.PI * sumDiameters / (last.y - first.y);

            //print("ULength=" + tankULength + " VLength=" + tankVLength);

            // set the texture scale.
            RaiseChangeTextureScale("sides", pPart.sidesMaterial, new Vector2(tankULength, tankVLength));

            m.WriteTo(sidesMesh);

            // The endcaps.
            nVrt = first.circ.totVertexes + last.circ.totVertexes;
            nTri = first.circ.totVertexes - 2 + last.circ.totVertexes - 2;
            m = new UncheckedMesh(nVrt, nTri);

            first.circ.WriteEndcap(first.dia, first.y, false, 0, 0, m, false);
            last.circ.WriteEndcap(last.dia, last.y, true, first.circ.totVertexes, (first.circ.totVertexes - 2) * 3, m, !odd);

            m.WriteTo(endsMesh);

            // build the collider mesh at a lower resolution than the visual mesh.
            if (customCollider)
            {
                //Debug.LogWarning("Collider mesh vert=" + nColVrt + " tris=" + nColTri);
                m = new UncheckedMesh(nColVrt, nColTri);
                odd = false;
                {
                    ProfilePoint prev = null;
                    int off = 0, prevOff = 0;
                    int tOff = 0;
                    foreach (ProfilePoint pt in pts)
                    {
                        if (!pt.inCollider)
                            continue;
                        //Debug.LogWarning("Collider circ (" + pt.dia + ", " + pt.y + ") verts=" + pt.colliderCirc.totVertexes);
                        pt.colliderCirc.WriteVertexes(diameter: pt.dia, y: pt.y, v: pt.v, norm: pt.norm, off: off, m: m, odd: odd);
                        if (prev != null)
                        {
                            CirclePoints.WriteTriangles(prev.colliderCirc, prevOff, pt.colliderCirc, off, m.triangles, tOff * 3, !odd);
                            tOff += prev.colliderCirc.totVertexes + pt.colliderCirc.totVertexes;
                        }

                        prev = pt;
                        prevOff = off;
                        off += pt.colliderCirc.totVertexes + 1;
                        odd = !odd;
                    }
                }

                if (colliderMesh == null)
                    colliderMesh = new Mesh();

                m.WriteTo(colliderMesh);

                pPart.colliderMesh = colliderMesh;
            }
            else
            {
                pPart.colliderMesh = sidesMesh;
            }

            RaiseModelAndColliderChanged();
        }
예제 #26
0
            /// <summary>
            /// writes this.totVerticies + 1 xy, verticies, and tangents and this.totVerticies triangles to the passed arrays for a single endcap.
            /// Callers will need to fill the normals. This will be { 0, 1, 0 } for pt endcap, and { 0, -1, 0 } for bottom.
            /// </summary>
            /// <param name="dia">diameter of circle</param>
            /// <param name="y">y dimension for points</param>
            /// <param name="vOff">offset into xy, verticies, and normal arrays to begin at</param>
            /// <param name="xy">xy array, data will be written</param>
            /// <param name="verticies">verticies array</param>
            /// <param name="tangents">tangents array</param>
            /// <param name="to">offset into triangles array</param>
            /// <param name="triangles"></param>
            public void WriteEndcap(float dia, float y, bool up, int vOff, int to, UncheckedMesh m, bool odd)
            {
                Complete();

                int o = odd ? 1 : 0;

                for (int i = 0; i <= subdivCount; ++i)
                {
                    int o0 = vOff + i;
                    m.uv[o0] = new Vector2((-xCoords[o][i] + 1f) * 0.5f, (-zCoords[o][i] + 1f) * 0.5f);
                    m.verticies[o0] = new Vector3(xCoords[o][i] * dia * 0.5f, y, zCoords[o][i] * dia * 0.5f);

                    int o1 = vOff + i + subdivCount + 1;
                    m.uv[o1] = new Vector2((zCoords[o][i] + 1f) * 0.5f, (-xCoords[o][i] + 1f) * 0.5f);
                    m.verticies[o1] = new Vector3(-zCoords[o][i] * dia * 0.5f, y, xCoords[o][i] * dia * 0.5f);

                    int o2 = vOff + i + 2 * (subdivCount + 1);
                    m.uv[o2] = new Vector2((xCoords[o][i] + 1f) * 0.5f, (zCoords[o][i] + 1f) * 0.5f);
                    m.verticies[o2] = new Vector3(-xCoords[o][i] * dia * 0.5f, y, -zCoords[o][i] * dia * 0.5f);

                    int o3 = vOff + i + 3 * (subdivCount + 1);
                    m.uv[o3] = new Vector2((-zCoords[o][i] + 1f) * 0.5f, (xCoords[o][i] + 1f) * 0.5f);
                    m.verticies[o3] = new Vector3(zCoords[o][i] * dia * 0.5f, y, -xCoords[o][i] * dia * 0.5f);

                    m.tangents[o0] = m.tangents[o1] = m.tangents[o2] = m.tangents[o3] = new Vector4(-1, 0, 0, up ? 1 : -1);
                    m.normals[o0] = m.normals[o1] = m.normals[o2] = m.normals[o3] = new Vector3(0, up ? 1 : -1, 0);
                }

                for (int i = 1; i < totVertexes - 1; ++i)
                {
                    m.triangles[to++] = vOff;
                    m.triangles[to++] = vOff + i + (up ? 1 : 0);
                    m.triangles[to++] = vOff + i + (up ? 0 : 1);
                }
            }
 private void SetCapVertexData(UncheckedMesh mesh, Vector3 cornerVector, int vertexIndex, bool up)
 {
     mesh.uv[vertexIndex]       = new Vector2(cornerVector.x, cornerVector.z) / InnerDiameter / NormHorizontalDiameter + new Vector2(0.5f, 0.5f);
     mesh.normals[vertexIndex]  = new Vector3(0, up ? 1 : -1, 0);
     mesh.tangents[vertexIndex] = new Vector4(1, 0, 0, 1f);
 }
예제 #28
0
            /// <summary>
            /// Write vertexes for the circle.
            /// </summary>
            /// <param name="diameter">diameter of the circle</param>
            /// <param name="y">y coordinate</param>
            /// <param name="norm">unit normal vector along the generator curve for increasing y. The y param becomes the y of the normal, the x multiplies the normals to the circle</param>
            /// <param name="v">v coordinate for UV</param>
            /// <param name="off">offset into following arrays</param>
            /// <param name="odd">If this is an odd row</param>
            /// <param name="m">Mesh to write vertexes into</param>
            public void WriteVertexes(float diameter, float y, float v, Vector2 norm, int off, bool odd, UncheckedMesh m)
            {
                Complete();

                int o = odd ? 1 : 0;

                for (int i = 0; i <= subdivCount; ++i)
                {
                    int o0 = off + i;
                    m.uv[o0]        = new Vector2(uCoords[o][i], v);
                    m.verticies[o0] = new Vector3(xCoords[o][i] * 0.5f * diameter, y, zCoords[o][i] * 0.5f * diameter);
                    m.normals[o0]   = new Vector3(xCoords[o][i] * norm.x, norm.y, zCoords[o][i] * norm.x);
                    m.tangents[o0]  = new Vector4(-zCoords[o][i], 0, xCoords[o][i], -1.0f);
                    //MonoBehaviour.print("Vertex #" + i + " off=" + o0 + " u=" + xy[o0][0] + " coords=" + verticies[o0]);

                    int o1 = off + i + subdivCount + 1;
                    m.uv[o1]        = new Vector2(uCoords[o][i] + 0.25f, v);
                    m.verticies[o1] = new Vector3(-zCoords[o][i] * 0.5f * diameter, y, xCoords[o][i] * 0.5f * diameter);
                    m.normals[o1]   = new Vector3(-zCoords[o][i] * norm.x, norm.y, xCoords[o][i] * norm.x);
                    m.tangents[o1]  = new Vector4(-xCoords[o][i], 0, -zCoords[o][i], -1.0f);

                    int o2 = off + i + 2 * (subdivCount + 1);
                    m.uv[o2]        = new Vector2(uCoords[o][i] + 0.50f, v);
                    m.verticies[o2] = new Vector3(-xCoords[o][i] * 0.5f * diameter, y, -zCoords[o][i] * 0.5f * diameter);
                    m.normals[o2]   = new Vector3(-xCoords[o][i] * norm.x, norm.y, -zCoords[o][i] * norm.x);
                    m.tangents[o2]  = new Vector4(zCoords[o][i], 0, -xCoords[o][i], -1.0f);

                    int o3 = off + i + 3 * (subdivCount + 1);
                    m.uv[o3]        = new Vector2(uCoords[o][i] + 0.75f, v);
                    m.verticies[o3] = new Vector3(zCoords[o][i] * 0.5f * diameter, y, -xCoords[o][i] * 0.5f * diameter);
                    m.normals[o3]   = new Vector3(zCoords[o][i] * norm.x, norm.y, -xCoords[o][i] * norm.x);
                    m.tangents[o3]  = new Vector4(xCoords[o][i], 0, zCoords[o][i], -1.0f);
                }

                // write the wrapping vertex. This is identical to the first one except for u coord += 1
                int lp = off + totVertexes;

                m.uv[lp]        = new Vector2(uCoords[o][0] + 1.0f, v);
                m.verticies[lp] = m.verticies[off];
                m.normals[lp]   = m.normals[off];
                m.tangents[lp]  = m.tangents[off];
            }
        void UpdateFairing()
        {
            ProceduralPart ppart = PPart;

            if (useFairing && ppart != null)
            {
                ProceduralAbstractSoRShape shape = ppart.CurrentShape as ProceduralAbstractSoRShape;

                if (shape != null)
                {
                    Vector3[] topEndcapVerticies = shape.GetEndcapVerticies(true);

                    Vector3[] topInner = new Vector3[topEndcapVerticies.Length + 1];

                    topEndcapVerticies.CopyTo(topInner, 0);
                    topInner[topEndcapVerticies.Length] = topEndcapVerticies[0];

                    int vertCount = topInner.Length;

                    //foreach (Vector3 v in topInner)
                    //    Debug.Log(v);

                    Vector3[] topOuter = (Vector3[])topInner.Clone();

                    for (int i = 0; i < vertCount; ++i)
                    {
                        float r = topInner[i].magnitude;
                        float r_ = r + fairingThickness;
                        float scaleFactor = r_ / r;
                        topOuter[i].x *= scaleFactor;
                        topOuter[i].z *= scaleFactor;
                    }

                    TextureScale.x = topOuter[0].magnitude * 2 * Mathf.PI;

                    Vector3[] sideTop = (Vector3[])topOuter.Clone();
                    Vector3[] sideBottom = (Vector3[])sideTop.Clone();

                    Vector3[] bottomInner = (Vector3[])topInner.Clone();
                    Vector3[] bottomOuter = (Vector3[])topOuter.Clone();

                    for (int i = 0; i < vertCount; ++i)
                    {
                        if (bottomNode != null)
                        {
                            sideBottom[i].y = bottomNode.position.y;
                            bottomInner[i].y = bottomNode.position.y;
                            bottomOuter[i].y = bottomNode.position.y;
                        }
                    }

                    TextureScale.y = Mathf.Abs(topOuter[0].y - bottomOuter[0].y);

                    Vector3[] innerSideTop = (Vector3[])topInner.Clone();
                    Vector3[] innerSideBottom = (Vector3[])bottomInner.Clone();

                    int topInnerStart = 0;
                    int topOuterStart = topInnerStart + vertCount;
                    int sideTopStart = topOuterStart + vertCount;
                    int sideBottomStart = sideTopStart + vertCount;
                    int bottomInnerStart = sideBottomStart + vertCount;
                    int bottomOuterStart = bottomInnerStart + vertCount;
                    int innerSideTopStart = bottomOuterStart + vertCount;
                    int innerSideBottomStart = innerSideTopStart + vertCount;

                    UncheckedMesh m = new UncheckedMesh(vertCount * 8, vertCount * 8 * 6);
                    //int tri = 0;
                    for (int i = 0; i < vertCount; ++i)
                    {
                        m.verticies[topInnerStart + i] = topInner[i];
                        m.verticies[topOuterStart + i] = topOuter[i];
                        m.verticies[sideTopStart + i] = sideTop[i];
                        m.verticies[sideBottomStart + i] = sideBottom[i];
                        m.verticies[bottomInnerStart + i] = bottomInner[i];
                        m.verticies[bottomOuterStart + i] = bottomOuter[i];
                        m.verticies[innerSideTopStart + i] = innerSideTop[i];
                        m.verticies[innerSideBottomStart + i] = innerSideBottom[i];

                        m.normals[topInnerStart + i] = new Vector3(0.0f, 1.0f, 0.0f);
                        m.normals[topOuterStart + i] = new Vector3(0.0f, 1.0f, 0.0f);

                        m.normals[sideTopStart + i] = m.verticies[sideTopStart + i].xz().normalized;
                        m.normals[sideBottomStart + i] = m.verticies[sideBottomStart + i].xz().normalized;

                        m.normals[bottomInnerStart + i] = new Vector3(0.0f, -1.0f, 0.0f);
                        m.normals[bottomOuterStart + i] = new Vector3(0.0f, -1.0f, 0.0f);

                        m.normals[innerSideTopStart + i] = -m.verticies[innerSideTopStart + i].xz().normalized;
                        m.normals[innerSideBottomStart + i] = -m.verticies[innerSideBottomStart + i].xz().normalized;

                        m.uv[topInnerStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);
                        m.uv[topOuterStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);

                        m.uv[sideTopStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);
                        m.uv[sideBottomStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);

                        m.uv[bottomInnerStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);
                        m.uv[bottomOuterStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);

                        m.uv[innerSideTopStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 0.0f);
                        m.uv[innerSideBottomStart + i] = new Vector2(Mathf.InverseLerp(0, vertCount - 1, i), 1.0f);

                        m.tangents[topInnerStart + i] = Vector3.Cross(m.normals[topInnerStart + i], m.verticies[topInnerStart + i]).xz().normalized.toVec4(-1);
                        m.tangents[topOuterStart + i] = Vector3.Cross(m.normals[topOuterStart + i], m.verticies[topOuterStart + i]).xz().normalized.toVec4(-1);

                        m.tangents[sideTopStart + i] = Vector3.Cross(m.normals[sideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);
                        m.tangents[sideBottomStart + i] = Vector3.Cross(m.normals[sideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);

                        m.tangents[bottomInnerStart + i] = Vector3.Cross(m.normals[bottomInnerStart + i], m.verticies[topInnerStart + i]).xz().normalized.toVec4(-1);
                        m.tangents[bottomOuterStart + i] = Vector3.Cross(m.normals[bottomOuterStart + i], m.verticies[topOuterStart + i]).xz().normalized.toVec4(-1);

                        m.tangents[innerSideTopStart + i] = Vector3.Cross(m.normals[innerSideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);
                        m.tangents[innerSideBottomStart + i] = Vector3.Cross(m.normals[innerSideTopStart + i], new Vector3(0, 1, 0)).normalized.toVec4(-1);

                        //Debug.Log(i +" uv: " + Mathf.InverseLerp(0, vertCount - 1, i));

                    }

                    int triangleOffset = 0;
                    triangleOffset = ConnectRings(m, topInnerStart, topOuterStart, vertCount, 0);
                    triangleOffset = ConnectRings(m, sideTopStart, sideBottomStart, vertCount, triangleOffset);
                    triangleOffset = ConnectRings(m, bottomOuterStart, bottomInnerStart, vertCount, triangleOffset);
                    triangleOffset = ConnectRings(m, innerSideBottomStart, innerSideTopStart, vertCount, triangleOffset);

                    if (fairingMesh != null)
                    {
                        m.WriteTo(fairingMesh);
                        fairingMesh.RecalculateNormals();

                    }
                    else
                        Debug.Log("no fairing mesh");

                }
                oldTextureSet = null;
                UpdateTexture();
            }
        }
        int ConnectRings(UncheckedMesh m, int ring1Offset, int ring2Offset, int vertCount, int triOffset, bool inverse = false)
        {
            int tri = triOffset;
            for (int i = 0; i < vertCount; ++i)
            {
                //Debug.Log(i);
                if (i < vertCount - 1)
                {
                    m.triangles[tri++] = ring1Offset + i;
                    m.triangles[tri++] = ring1Offset + i + 1;
                    m.triangles[tri++] = ring2Offset + i + 1;

                    m.triangles[tri++] = ring1Offset + i;
                    m.triangles[tri++] = ring2Offset + i + 1;
                    m.triangles[tri++] = ring2Offset + i;
                }
                else
                {
                    //m.triangles[tri++] = ring1Offset + i;
                    //m.triangles[tri++] = ring1Offset;
                    //m.triangles[tri++] = ring2Offset;

                    //m.triangles[tri++] = ring1Offset + i;
                    //m.triangles[tri++] = ring2Offset;
                    //m.triangles[tri++] = ring2Offset + i;
                }
            }
            return tri;
        }
예제 #31
0
        private static void WriteToAppropriateMesh(UncheckedMesh mesh, Mesh iconMesh, Mesh normalMesh)
        {
            var target = (HighLogic.LoadedScene == GameScenes.LOADING) ? iconMesh : normalMesh;

            mesh.WriteTo(target);
        }
예제 #32
0
        /// <summary>
        /// Generate the compShape from profile points from pt to bottom.
        /// Note that this list will have extra interpolated points added if the change in radius is high to avoid
        /// texture stretching.
        /// </summary>
        /// <param name="pts"></param>
        protected void WriteMeshes(LinkedList <ProfilePoint> pts)
        {
            if (pts == null || pts.Count < 2)
            {
                return;
            }

            // update nodes
            UpdateNodeSize(pts.First(), bottomNodeName);
            UpdateNodeSize(pts.Last(), topNodeName);

            // Move attachments first, before subdividing
            MoveAttachments(pts);

            // Horizontal profile point subdivision
            SubdivHorizontal(pts);

            // Tank stats
            float tankVLength = 0;

            int  nVrt           = 0;
            int  nTri           = 0;
            int  nColVrt        = 0;
            int  nColTri        = 0;
            bool customCollider = false;

            ProfilePoint first = pts.First.Value;
            ProfilePoint last  = pts.Last.Value;

            if (!first.inCollider || !last.inCollider)
            {
                throw new InvalidOperationException("First and last profile points must be used in the collider");
            }

            foreach (ProfilePoint pt in pts)
            {
                customCollider = customCollider || pt.CustomCollider;

                if (pt.inRender)
                {
                    nVrt += pt.circ.totVertexes + 1;
                    // one for above, one for below
                    nTri += 2 * pt.circ.totVertexes;
                }

                if (pt.inCollider)
                {
                    nColVrt += pt.colliderCirc.totVertexes + 1;
                    nColTri += 2 * pt.colliderCirc.totVertexes;
                }
            }
            // Have double counted for the first and last circles.
            nTri    -= first.circ.totVertexes + last.circ.totVertexes;
            nColTri -= first.colliderCirc.totVertexes + last.colliderCirc.totVertexes;

            UncheckedMesh m = new UncheckedMesh(nVrt, nTri);

            float sumDiameters = 0;
            //Debug.LogWarning("Display mesh vert=" + nVrt + " tris=" + nTri);

            bool odd = false;
            {
                ProfilePoint prev = null;
                int          off = 0, prevOff = 0;
                int          tOff = 0;
                foreach (ProfilePoint pt in pts)
                {
                    if (!pt.inRender)
                    {
                        continue;
                    }

                    pt.circ.WriteVertexes(diameter: pt.dia, y: pt.y, v: pt.v, norm: pt.norm, off: off, m: m, odd: odd);
                    if (prev != null)
                    {
                        CirclePoints.WriteTriangles(prev.circ, prevOff, pt.circ, off, m.triangles, tOff * 3, !odd);
                        tOff += prev.circ.totVertexes + pt.circ.totVertexes;

                        // Deprecated: Volume has been moved up to callers. This way we can use the idealized rather than aproximate volume
                        // Work out the area of the truncated cone

                        // integral_y1^y2 pi R(y)^2 dy   where R(y) = ((r2-r1)(y-y1))/(r2-r1) + r1   Integrate circles along a line
                        // integral_y1^y2 pi ( ((r2-r1)(y-y1))/(r2-r1) + r1) ^2 dy                Substituted in formula.
                        // == -1/3 pi (y1-y2) (r1^2+r1*r2+r2^2)                                   Do the calculus
                        // == -1/3 pi (y1-y2) (d1^2/4+d1*d2/4+d2^2/4)                             r = d/2
                        // == -1/12 pi (y1-y2) (d1^2+d1*d2+d2^2)                                  Take out the factor
                        //volume += (Mathf.PI * (pt.y - prev.y) * (prev.dia * prev.dia + prev.dia * pt.dia + pt.dia * pt.dia)) / 12f;

                        float dy = (pt.y - prev.y);
                        float dr = (prev.dia - pt.dia) * 0.5f;

                        //print("dy=" + dy + " dr=" + dr + " len=" + Mathf.Sqrt(dy * dy + dr * dr).ToString("F3"));
                        tankVLength += Mathf.Sqrt(dy * dy + dr * dr);

                        // average diameter weighted by dy
                        sumDiameters += (pt.dia + prev.dia) * dy;
                    }

                    prev    = pt;
                    prevOff = off;
                    off    += pt.circ.totVertexes + 1;
                    odd     = !odd;
                }
            }

            // Use the weighted average diameter across segments to set the ULength
            float tankULength = Mathf.PI * sumDiameters / (last.y - first.y);

            //print("ULength=" + tankULength + " VLength=" + tankVLength);

            // set the texture scale.
            RaiseChangeTextureScale("sides", PPart.SidesMaterial, new Vector2(tankULength, tankVLength));

            m.WriteTo(SidesMesh);

            // The endcaps.
            nVrt = first.circ.totVertexes + last.circ.totVertexes;
            nTri = first.circ.totVertexes - 2 + last.circ.totVertexes - 2;
            m    = new UncheckedMesh(nVrt, nTri);

            first.circ.WriteEndcap(first.dia, first.y, false, 0, 0, m, false);
            last.circ.WriteEndcap(last.dia, last.y, true, first.circ.totVertexes, (first.circ.totVertexes - 2) * 3, m, !odd);

            m.WriteTo(EndsMesh);

            // build the collider mesh at a lower resolution than the visual mesh.
            if (customCollider)
            {
                //Debug.LogWarning("Collider mesh vert=" + nColVrt + " tris=" + nColTri);
                m   = new UncheckedMesh(nColVrt, nColTri);
                odd = false;
                {
                    ProfilePoint prev = null;
                    int          off = 0, prevOff = 0;
                    int          tOff = 0;
                    foreach (ProfilePoint pt in pts)
                    {
                        if (!pt.inCollider)
                        {
                            continue;
                        }
                        //Debug.LogWarning("Collider circ (" + pt.dia + ", " + pt.y + ") verts=" + pt.colliderCirc.totVertexes);
                        pt.colliderCirc.WriteVertexes(diameter: pt.dia, y: pt.y, v: pt.v, norm: pt.norm, off: off, m: m, odd: odd);
                        if (prev != null)
                        {
                            CirclePoints.WriteTriangles(prev.colliderCirc, prevOff, pt.colliderCirc, off, m.triangles, tOff * 3, !odd);
                            tOff += prev.colliderCirc.totVertexes + pt.colliderCirc.totVertexes;
                        }

                        prev    = pt;
                        prevOff = off;
                        off    += pt.colliderCirc.totVertexes + 1;
                        odd     = !odd;
                    }
                }

                if (colliderMesh == null)
                {
                    colliderMesh = new Mesh();
                }

                m.WriteTo(colliderMesh);

                PPart.ColliderMesh = colliderMesh;
            }
            else
            {
                PPart.ColliderMesh = SidesMesh;
            }

            RaiseModelAndColliderChanged();
        }