Example #1
0
        AttachNode [] getFairingParams()
        {
            if (part.GetComponent <KzNodeNumberTweaker>() is KzNodeNumberTweaker nnt &&
                part.FindAttachNodes("connect") is AttachNode[] attached)
            {
                if (!AllFairingSidesAttached())
                {
                    shape        = null;
                    sideFairing  = null;
                    boundCylY0   = boundCylY1 = boundCylRad = 0;
                    lookupCenter = Vector3.zero;
                    lookupRad    = 0;
                    return(null);
                }

                ProceduralFairingSide sf = attached[0].attachedPart.GetComponent <ProceduralFairingSide>();
                sideFairing = sf;

                //  Get the polyline shape.
                shape = (sf.inlineHeight <= 0) ?
                        ProceduralFairingBase.buildFairingShape(sf.baseRad, sf.maxRad, sf.cylStart, sf.cylEnd, sf.noseHeightRatio, sf.baseConeShape, sf.noseConeShape, (int)sf.baseConeSegments, (int)sf.noseConeSegments, sf.vertMapping, sf.mappingScale.y) :
                        ProceduralFairingBase.buildInlineFairingShape(sf.baseRad, sf.maxRad, sf.topRad, sf.cylStart, sf.cylEnd, sf.inlineHeight, sf.baseConeShape, (int)sf.baseConeSegments, sf.vertMapping, sf.mappingScale.y);

                //  Offset shape by thickness.

                for (int i = 0; i < shape.Length; ++i)
                {
                    if (i == 0 || i == shape.Length - 1)
                    {
                        shape[i] += new Vector3(sf.sideThickness, 0, 0);
                    }
                    else
                    {
                        Vector2 n = shape[i + 1] - shape[i - 1];
                        n.Set(n.y, -n.x);
                        n.Normalize();
                        shape[i] += new Vector3(n.x, n.y, 0) * sf.sideThickness;
                    }
                }

                //  Compute the bounds.

                boundCylRad = shape[0].x;
                boundCylY0  = shape[0].y;
                boundCylY1  = shape[0].y;

                foreach (Vector3 p in shape)
                {
                    boundCylRad = Math.Max(boundCylRad, p.x);
                    boundCylY0  = Math.Min(boundCylY0, p.y);
                    boundCylY1  = Math.Max(boundCylY1, p.y);
                }

                lookupCenter = new Vector3(0, (boundCylY0 + boundCylY1) / 2, 0);
                lookupRad    = new Vector2(boundCylRad, (boundCylY1 - boundCylY0) / 2).magnitude;

                return(attached);
            }
            return(null);
        }
        AttachNode [] getFairingParams()
        {
            var nnt = part.GetComponent <KzNodeNumberTweaker>();

            //  Check for attached side parts and get their parameters.

            var attached = part.FindAttachNodes("connect");

            ProceduralFairingSide sf = null;

            for (int i = 0; i < nnt.numNodes; ++i)
            {
                var n = attached [i];

                if (!n.attachedPart)
                {
                    sf = null;

                    break;
                }

                sf = n.attachedPart.GetComponent <ProceduralFairingSide>();

                if (!sf)
                {
                    break;
                }
            }

            sideFairing = sf;

            if (!sf)
            {
                shape        = null;
                boundCylY0   = boundCylY1 = boundCylRad = 0;
                lookupCenter = Vector3.zero;
                lookupRad    = 0;

                return(null);
            }

            //  Get the polyline shape.

            if (sf.inlineHeight <= 0)
            {
                shape = ProceduralFairingBase.buildFairingShape(sf.baseRad, sf.maxRad, sf.cylStart, sf.cylEnd, sf.noseHeightRatio, sf.baseConeShape, sf.noseConeShape, (int)sf.baseConeSegments, (int)sf.noseConeSegments, sf.vertMapping, sf.mappingScale.y);
            }
            else
            {
                shape = ProceduralFairingBase.buildInlineFairingShape(sf.baseRad, sf.maxRad, sf.topRad, sf.cylStart, sf.cylEnd, sf.inlineHeight, sf.baseConeShape, (int)sf.baseConeSegments, sf.vertMapping, sf.mappingScale.y);
            }

            //  Offset shape by thickness.

            for (int i = 0; i < shape.Length; ++i)
            {
                if (i == 0 || i == shape.Length - 1)
                {
                    shape [i] += new Vector3(sf.sideThickness, 0, 0);
                }
                else
                {
                    Vector2 n = shape [i + 1] - shape [i - 1];

                    n.Set(n.y, -n.x);

                    n.Normalize();

                    shape [i] += new Vector3(n.x, n.y, 0) * sf.sideThickness;
                }
            }

            //  Compute the bounds.

            float y0, y1, mr;

            y0 = y1 = shape [0].y;
            mr = shape [0].x;

            for (int i = 0; i < shape.Length; ++i)
            {
                var p = shape [i];

                if (p.x > mr)
                {
                    mr = p.x;
                }

                if (p.y < y0)
                {
                    y0 = p.y;
                }
                else if (p.y > y1)
                {
                    y1 = p.y;
                }
            }

            boundCylY0  = y0;
            boundCylY1  = y1;
            boundCylRad = mr;

            lookupCenter = new Vector3(0, (y0 + y1) * 0.5f, 0);
            lookupRad    = new Vector2(mr, (y1 - y0) * 0.5f).magnitude;

            return(attached);
        }
Example #3
0
        public void rebuildMesh()
        {
            var mf = part.FindModelComponent <MeshFilter>("model");

            if (!mf)
            {
                Debug.LogError("[PF]: No model for side fairing!", part);

                return;
            }

            Mesh m = mf.mesh;

            if (!m)
            {
                Debug.LogError("[PF]: No mesh in side fairing model!", part);

                return;
            }

            mf.transform.localPosition = meshPos;
            mf.transform.localRotation = meshRot;

            updateNodeSize();

            //  Build the fairing shape line.

            float tip = maxRad * noseHeightRatio;

            Vector3 [] shape;

            baseConeShape = new Vector4(baseCurveStartX, baseCurveStartY, baseCurveEndX, baseCurveEndY);
            noseConeShape = new Vector4(noseCurveStartX, noseCurveStartY, noseCurveEndX, noseCurveEndY);

            if (inlineHeight <= 0)
            {
                shape = ProceduralFairingBase.buildFairingShape(baseRad, maxRad, cylStart, cylEnd, noseHeightRatio, baseConeShape, noseConeShape, (int)baseConeSegments, (int)noseConeSegments, vertMapping, mappingScale.y);
            }
            else
            {
                shape = ProceduralFairingBase.buildInlineFairingShape(baseRad, maxRad, topRad, cylStart, cylEnd, inlineHeight, baseConeShape, (int)baseConeSegments, vertMapping, mappingScale.y);
            }

            //  Set up parameters.

            var dirs = new Vector3 [numSegs + 1];

            for (int i = 0; i <= numSegs; ++i)
            {
                float a = Mathf.PI * 2 * (i - numSegs * 0.5f) / (numSideParts * numSegs);

                dirs [i] = new Vector3(Mathf.Cos(a), 0, Mathf.Sin(a));
            }

            float segOMappingScale = (horMapping.y - horMapping.x) / (mappingScale.x * numSegs);
            float segIMappingScale = (horMapping.w - horMapping.z) / (mappingScale.x * numSegs);
            float segOMappingOfs   = horMapping.x / mappingScale.x;
            float segIMappingOfs   = horMapping.z / mappingScale.x;

            if (numSideParts > 2)
            {
                segOMappingOfs   += segOMappingScale * numSegs * (0.5f - 1f / numSideParts);
                segOMappingScale *= 2f / numSideParts;

                segIMappingOfs   += segIMappingScale * numSegs * (0.5f - 1f / numSideParts);
                segIMappingScale *= 2f / numSideParts;
            }

            float stripU0 = stripMapping.x / mappingScale.x;
            float stripU1 = stripMapping.y / mappingScale.x;

            float ringSegLen    = baseRad * Mathf.PI * 2 / (numSegs * numSideParts);
            float topRingSegLen = topRad * Mathf.PI * 2 / (numSegs * numSideParts);

            float collWidth = maxRad * Mathf.PI * 2 / (numSideParts * 3);

            int numMainVerts = (numSegs + 1) * (shape.Length - 1) + 1;
            int numMainFaces = numSegs * ((shape.Length - 2) * 2 + 1);

            int numSideVerts = shape.Length * 2;
            int numSideFaces = (shape.Length - 1) * 2;

            int numRingVerts = (numSegs + 1) * 2;
            int numRingFaces = numSegs * 2;

            if (inlineHeight > 0)
            {
                numMainVerts = (numSegs + 1) * shape.Length;
                numMainFaces = numSegs * (shape.Length - 1) * 2;
            }

            int totalVerts = numMainVerts * 2 + numSideVerts * 2 + numRingVerts;
            int totalFaces = numMainFaces * 2 + numSideFaces * 2 + numRingFaces;

            if (inlineHeight > 0)
            {
                totalVerts += numRingVerts;
                totalFaces += numRingFaces;
            }

            var p = shape [shape.Length - 1];

            float topY = p.y, topV = p.z;

            float collCenter = (cylStart + cylEnd) / 2;
            float collHeight = cylEnd - cylStart;

            if (collHeight <= 0)
            {
                collHeight = Mathf.Min(topY - cylEnd, cylStart) / 2;
            }

            //  Compute the area.

            double area = 0;

            for (int i = 1; i < shape.Length; ++i)
            {
                area += (shape [i - 1].x + shape [i].x) * (shape [i].y - shape [i - 1].y) * Mathf.PI / numSideParts;
            }

            //  Set the parameters based on volume.

            float volume = (float)(area * sideThickness);

            part.mass           = totalMass = volume * density;
            part.breakingForce  = part.mass * specificBreakingForce;
            part.breakingTorque = part.mass * specificBreakingTorque;

            var offset = new Vector3(maxRad * 0.7f, topY * 0.5f, 0);

            part.CoMOffset = part.transform.InverseTransformPoint(mf.transform.TransformPoint(offset));

            //  Remove any old colliders.

            var colls = part.FindModelComponents <Collider>();

            for (int i = 0; i < colls.Count; i++)
            {
                var c = colls [i];

                UnityEngine.Object.Destroy(c.gameObject);
            }

            //  Add the new colliders.

            for (int i = -1; i <= 1; ++i)
            {
                var obj = new GameObject("collider");

                obj.transform.parent        = mf.transform;
                obj.transform.localPosition = Vector3.zero;
                obj.transform.localRotation = Quaternion.AngleAxis(90f * i / numSideParts, Vector3.up);

                var coll = obj.AddComponent <BoxCollider>();

                coll.center = new Vector3(maxRad + sideThickness * 0.5f, collCenter, 0);
                coll.size   = new Vector3(sideThickness, collHeight, collWidth);
            }
            {
                //  Nose collider.

                float r = maxRad * 0.2f;

                var obj = new GameObject("nose_collider");

                obj.transform.parent        = mf.transform;
                obj.transform.localPosition = new Vector3(r, cylEnd + tip - r * 1.2f, 0);
                obj.transform.localRotation = Quaternion.identity;

                if (inlineHeight > 0)
                {
                    r = sideThickness * 0.5f;

                    obj.transform.localPosition = new Vector3(maxRad + r, collCenter, 0);
                }

                var coll = obj.AddComponent <SphereCollider>();

                coll.center = Vector3.zero;
                coll.radius = r;
            }

            //  Build the fairing mesh.

            m.Clear();

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

            if (inlineHeight <= 0)
            {
                //  Tip vertex.

                verts [numMainVerts - 1].Set(0, topY + sideThickness, 0);       //  Outside.
                verts [numMainVerts * 2 - 1].Set(0, topY, 0);                   //  Inside.

                uv [numMainVerts - 1].Set(segOMappingScale * 0.5f * numSegs + segOMappingOfs, topV);
                uv [numMainVerts * 2 - 1].Set(segIMappingScale * 0.5f * numSegs + segIMappingOfs, topV);

                norm [numMainVerts - 1]     = Vector3.up;
                norm [numMainVerts * 2 - 1] = -Vector3.up;

                tang [numMainVerts - 1]     = Vector3.zero;
                tang [numMainVerts * 2 - 1] = Vector3.zero;
            }

            //  Main vertices.

            float noseV0     = vertMapping.z / mappingScale.y;
            float noseV1     = vertMapping.w / mappingScale.y;
            float noseVScale = 1f / (noseV1 - noseV0);
            float oCenter    = (horMapping.x + horMapping.y) / (mappingScale.x * 2);
            float iCenter    = (horMapping.z + horMapping.w) / (mappingScale.x * 2);

            int vi = 0;

            for (int i = 0; i < shape.Length - (inlineHeight <= 0 ? 1 : 0); ++i)
            {
                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 <= numSegs; ++j, ++vi)
                {
                    var d = dirs [j];

                    var dp = d * p.x + Vector3.up * p.y;
                    var dn = d * n.x + Vector3.up * n.y;

                    if (i == 0 || i == shape.Length - 1)
                    {
                        verts [vi] = dp + d * sideThickness;
                    }
                    else
                    {
                        verts [vi] = dp + dn * sideThickness;
                    }

                    verts[vi + numMainVerts] = dp;

                    float v  = (p.z - noseV0) * noseVScale;
                    float uo = j * segOMappingScale + segOMappingOfs;
                    float ui = (numSegs - j) * segIMappingScale + segIMappingOfs;

                    if (v > 0 && v < 1)
                    {
                        float us = 1 - v;

                        uo = (uo - oCenter) * us + oCenter;
                        ui = (ui - iCenter) * us + iCenter;
                    }

                    uv [vi].Set(uo, p.z);

                    uv [vi + numMainVerts].Set(ui, p.z);

                    norm [vi] = dn;
                    norm [vi + numMainVerts] = -dn;

                    tang [vi].Set(-d.z, 0, d.x, 0);
                    tang [vi + numMainVerts].Set(d.z, 0, -d.x, 0);
                }
            }

            //  Side strip vertices.

            float stripScale = Mathf.Abs(stripMapping.y - stripMapping.x) / (sideThickness * mappingScale.y);

            vi = numMainVerts * 2;

            float o = 0;

            for (int i = 0; i < shape.Length; ++i, vi += 2)
            {
                int si = i * (numSegs + 1);

                var d = dirs [0];

                verts [vi] = verts [si];

                uv [vi].Set(stripU0, o);
                norm [vi].Set(d.z, 0, -d.x);

                verts [vi + 1] = verts [si + numMainVerts];
                uv [vi + 1].Set(stripU1, o);
                norm [vi + 1] = norm[vi];
                tang [vi]     = tang [vi + 1] = (verts [vi + 1] - verts [vi]).normalized;

                if (i + 1 < shape.Length)
                {
                    o += ((Vector2)shape [i + 1] - (Vector2)shape [i]).magnitude * stripScale;
                }
            }

            vi += numSideVerts - 2;

            for (int i = shape.Length - 1; i >= 0; --i, vi -= 2)
            {
                int si = i * (numSegs + 1) + numSegs;

                if (i == shape.Length - 1 && inlineHeight <= 0)
                {
                    si = numMainVerts - 1;
                }

                var d = dirs [numSegs];

                verts [vi] = verts [si];
                uv [vi].Set(stripU0, o);
                norm [vi].Set(-d.z, 0, d.x);

                verts [vi + 1] = verts [si + numMainVerts];
                uv [vi + 1].Set(stripU1, o);
                norm [vi + 1] = norm [vi];
                tang [vi]     = tang [vi + 1] = (verts [vi + 1] - verts [vi]).normalized;

                if (i > 0)
                {
                    o += ((Vector2)shape [i] - (Vector2)shape [i - 1]).magnitude * stripScale;
                }
            }

            //  Ring vertices.

            vi = numMainVerts * 2 + numSideVerts * 2;

            o = 0;

            for (int j = numSegs; j >= 0; --j, vi += 2, o += ringSegLen * stripScale)
            {
                verts [vi] = verts [j];
                uv [vi].Set(stripU0, o);
                norm [vi] = -Vector3.up;

                verts [vi + 1] = verts [j + numMainVerts];
                uv [vi + 1].Set(stripU1, o);
                norm [vi + 1] = -Vector3.up;
                tang [vi]     = tang [vi + 1] = (verts [vi + 1] - verts [vi]).normalized;
            }

            if (inlineHeight > 0)
            {
                //  Top ring vertices.

                o = 0;

                int si = (shape.Length - 1) * (numSegs + 1);

                for (int j = 0; j <= numSegs; ++j, vi += 2, o += topRingSegLen * stripScale)
                {
                    verts [vi] = verts [si + j];
                    uv [vi].Set(stripU0, o);
                    norm [vi] = Vector3.up;

                    verts [vi + 1] = verts [si + j + numMainVerts];
                    uv [vi + 1].Set(stripU1, o);
                    norm [vi + 1] = Vector3.up;
                    tang [vi]     = tang [vi + 1] = (verts [vi + 1] - verts [vi]).normalized;
                }
            }

            //  Set vertex data to mesh.

            for (int i = 0; i < totalVerts; ++i)
            {
                tang [i].w = 1;
            }

            m.vertices = verts;
            m.uv       = uv;
            m.normals  = norm;
            m.tangents = tang;

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

            var tri = new int [totalFaces * 3];

            //  Main faces.

            vi = 0;

            int ti1 = 0, ti2 = numMainFaces * 3;

            for (int i = 0; i < shape.Length - (inlineHeight <= 0 ? 2 : 1); ++i, ++vi)
            {
                p = shape [i];

                for (int j = 0; j < numSegs; ++j, ++vi)
                {
                    tri [ti1++] = vi;
                    tri [ti1++] = vi + 1 + numSegs + 1;
                    tri [ti1++] = vi + 1;

                    tri [ti1++] = vi;
                    tri [ti1++] = vi + numSegs + 1;
                    tri [ti1++] = vi + 1 + numSegs + 1;

                    tri [ti2++] = numMainVerts + vi;
                    tri [ti2++] = numMainVerts + vi + 1;
                    tri [ti2++] = numMainVerts + vi + 1 + numSegs + 1;

                    tri [ti2++] = numMainVerts + vi;
                    tri [ti2++] = numMainVerts + vi + 1 + numSegs + 1;
                    tri [ti2++] = numMainVerts + vi + numSegs + 1;
                }
            }

            if (inlineHeight <= 0)
            {
                //  Main tip faces.

                for (int j = 0; j < numSegs; ++j, ++vi)
                {
                    tri [ti1++] = vi;
                    tri [ti1++] = numMainVerts - 1;
                    tri [ti1++] = vi + 1;

                    tri [ti2++] = numMainVerts + vi;
                    tri [ti2++] = numMainVerts + vi + 1;
                    tri [ti2++] = numMainVerts + numMainVerts - 1;
                }
            }

            //  Side strip faces.

            vi  = numMainVerts * 2;
            ti1 = numMainFaces * 2 * 3;
            ti2 = ti1 + numSideFaces * 3;

            for (int i = 0; i < shape.Length - 1; ++i, vi += 2)
            {
                tri [ti1++] = vi;
                tri [ti1++] = vi + 1;
                tri [ti1++] = vi + 3;

                tri [ti1++] = vi;
                tri [ti1++] = vi + 3;
                tri [ti1++] = vi + 2;

                tri [ti2++] = numSideVerts + vi;
                tri [ti2++] = numSideVerts + vi + 3;
                tri [ti2++] = numSideVerts + vi + 1;

                tri [ti2++] = numSideVerts + vi;
                tri [ti2++] = numSideVerts + vi + 2;
                tri [ti2++] = numSideVerts + vi + 3;
            }

            //  Ring faces.

            vi  = numMainVerts * 2 + numSideVerts * 2;
            ti1 = (numMainFaces + numSideFaces) * 2 * 3;

            for (int j = 0; j < numSegs; ++j, vi += 2)
            {
                tri [ti1++] = vi;
                tri [ti1++] = vi + 1;
                tri [ti1++] = vi + 3;

                tri [ti1++] = vi;
                tri [ti1++] = vi + 3;
                tri [ti1++] = vi + 2;
            }

            if (inlineHeight > 0)
            {
                //  Top ring faces.

                vi += 2;

                for (int j = 0; j < numSegs; ++j, vi += 2)
                {
                    tri [ti1++] = vi;
                    tri [ti1++] = vi + 1;
                    tri [ti1++] = vi + 3;

                    tri [ti1++] = vi;
                    tri [ti1++] = vi + 3;
                    tri [ti1++] = vi + 2;
                }
            }

            m.triangles = tri;

            StartCoroutine(PFUtils.updateDragCubeCoroutine(part, 1));
        }