StretchyTanks.StretchyConicTank.rescaleModel C# (CSharp) Method

rescaleModel() public method

public rescaleModel ( ) : void
return void
        public override void rescaleModel()
        {
            // get side mesh
            var tr = transform.GetChild(0).GetChild(0).GetChild(0);

            var mf = tr.GetComponent<MeshFilter>();
            if (!mf) { Debug.LogError("[StretchyConicTank] no model to reshape", part); return; }

            var m = mf.mesh;
            if (!m) { Debug.LogError("[StretchyConicTank] no mesh to reshape", part); return; }

            // prepare for building geometry
            if (circleSegments < 3) circleSegments = 3;
            if (heightSegments < 1) heightSegments = 1;

            int sideVerts = (circleSegments + 1) * (heightSegments + 1);
            int sideFaces = circleSegments * heightSegments * 2;

            int capVerts = circleSegments * 2;
            int capFaces = (circleSegments - 1) * 2;

            var dirs = new Vector3[circleSegments + 1];
            for (int i = 0; i <= circleSegments; ++i)
            {
                float a = Mathf.PI * 2 * i / circleSegments;
                dirs[i] = new Vector3(Mathf.Cos(a), -Mathf.Sin(a), 0);
            }

            float baseRad = radialFactor * 1.25f;
            float topRad = topFactor * 1.25f;
            float height = stretchFactor * 1.875f;

            var slope = new BezierSlope(coneShape);

            var shape = new Vector3[heightSegments + 1];
            for (int i = 0; i <= heightSegments; ++i)
            {
                float v = (float)i / heightSegments;

                Vector2 p;
                if (baseRad <= topRad)
                    p = slope.interp(v);
                else
                {
                    p = slope.interp(1 - v);
                    p.y = 1 - p.y;
                }

                float y = (p.y - 0.5f) * height;
                float r = Mathf.Abs(baseRad - topRad) * p.x + Mathf.Min(baseRad, topRad);
                shape[i] = new Vector3(r, y, p.y);
            }

            // build side surface mesh
            m.Clear();

            var verts = new Vector3[sideVerts];
            var uv = new Vector2[sideVerts];
            var norm = new Vector3[sideVerts];
            var tang = new Vector4[sideVerts];

            for (int i = 0, vi = 0; i <= heightSegments; ++i)
            {
                var p = shape[i];

                Vector2 n;
                if (i == 0) n = shape[1] - shape[0];
                else if (i == shape.Length - 1) n = shape[i] - shape[i - 1];
                else n = shape[i + 1] - shape[i - 1];
                n.Set(n.y, -n.x);
                n.Normalize();

                for (int j = 0; j <= circleSegments; ++j, ++vi)
                {
                    var d = dirs[j];
                    verts[vi] = d * p.x + Vector3.forward * p.y;
                    norm[vi] = d * n.x + Vector3.forward * n.y;
                    tang[vi].Set(-d.y, d.x, 0, 1);
                    uv[vi].Set((float)j / circleSegments, p.z);
                }
            }

            // set vertex data to mesh
            m.vertices = verts;
            m.uv = uv;
            m.normals = norm;
            m.tangents = tang;

            m.uv2 = null;
            m.colors32 = null;

            var tri = new int[sideFaces * 3];

            for (int i = 0, vi = 0, ti = 0; i < heightSegments; ++i, ++vi)
                for (int j = 0; j < circleSegments; ++j, ++vi)
                {
                    int nv = vi + 1;

                    tri[ti++] = vi;
                    tri[ti++] = nv + circleSegments + 1;
                    tri[ti++] = nv;

                    tri[ti++] = vi;
                    tri[ti++] = vi + circleSegments + 1;
                    tri[ti++] = nv + circleSegments + 1;
                }

            m.triangles = tri;

            if (!HighLogic.LoadedSceneIsEditor) m.Optimize();

            var collider = tr.GetComponent<MeshCollider>();
            collider.sharedMesh = null;
            collider.sharedMesh = m;

            // get cap mesh
            tr = tr.GetChild(0);

            mf = tr.GetComponent<MeshFilter>();
            if (!mf) { Debug.LogError("[StretchyConicTank] no model to reshape", part); return; }

            m = mf.mesh;
            if (!m) { Debug.LogError("[StretchyConicTank] no mesh to reshape", part); return; }

            // build cap mesh
            m.Clear();

            verts = new Vector3[capVerts];
            uv = new Vector2[capVerts];
            norm = new Vector3[capVerts];
            tang = new Vector4[capVerts];

            const float capMapScale = 0.47f;

            for (int i = 0; i < circleSegments; ++i)
            {
                var d = dirs[i];

                verts[i] = d * baseRad - Vector3.forward * height * 0.5f;
                norm[i] = -Vector3.forward;
                tang[i].Set(-1, 0, 0, 1);
                uv[i].Set(-d.x * capMapScale + 0.5f, d.y * capMapScale + 0.5f);

                verts[i + circleSegments] = d * topRad + Vector3.forward * height * 0.5f;
                norm[i + circleSegments] = Vector3.forward;
                tang[i + circleSegments].Set(1, 0, 0, 1);
                uv[i + circleSegments].Set(d.x * capMapScale + 0.5f, d.y * capMapScale + 0.5f);
            }

            // set vertex data to mesh
            m.vertices = verts;
            m.uv = uv;
            m.normals = norm;
            m.tangents = tang;

            m.uv2 = null;
            m.colors32 = null;

            tri = new int[capFaces * 3];

            for (int i = 1, ti = 0; i < circleSegments; ++i, ti += 3)
            {
                int nv = i + 1; if (nv == circleSegments) nv = 0;

                tri[ti] = 0;
                tri[ti + 1] = i;
                tri[ti + 2] = nv;

                tri[ti + (circleSegments - 1) * 3] = circleSegments;
                tri[ti + 1 + (circleSegments - 1) * 3] = circleSegments + nv;
                tri[ti + 2 + (circleSegments - 1) * 3] = circleSegments + i;
            }

            m.triangles = tri;

            if (!HighLogic.LoadedSceneIsEditor) m.Optimize();
        }