예제 #1
0
        private static void SetupBones(Transform parent, MeshData md, Parachute p, ParachuteMeshConfig cf)
        {
            var c = p.Config;

            float spanStep = c.Span / c.NumCells;

            p.Bones = new Transform[c.NumCells];

            for (int i = 0; i < c.NumCells; i++)
            {
                var go = new GameObject("Cell_" + i);
                var t  = go.transform;

                t.position = Vector3.right * (0.5f * spanStep) + Vector3.right * (spanStep * i);
                t.rotation = Quaternion.Euler(-0.5f, 0f, 0f); // Todo: align with median chord
                t.parent   = parent;

                var b = t.worldToLocalMatrix * parent.localToWorldMatrix;

                md.Bones.Add(t);
                md.BindPoses.Add(b);

                p.Bones[i] = t;
            }
        }
예제 #2
0
        public static void CreateSkinnedMesh(Parachute p, ParachuteMeshConfig cf, Material mat)
        {
            if (_meshData == null)
            {
                throw new Exception("UnityParachuteMeshFactory needs to be initialized before use!");
            }

            Clear();

            // Todo: Reuse mesh, game objects, as much as possible. Create pool of cells.

            Profiler.BeginSample("GOCreation");
            GameObject mo = new GameObject("ParachuteMesh");

            mo.transform.parent = p.Root;
            SkinnedMeshRenderer r = mo.AddComponent <SkinnedMeshRenderer>();

            r.updateWhenOffscreen        = true; // Todo: This is not great
            r.skinnedMotionVectors       = true;
            r.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
            Profiler.EndSample();

            Profiler.BeginSample("SetupBones");
            SetupBones(mo.transform, _meshData, p, cf);
            Profiler.EndSample();

            Profiler.BeginSample("EdgeLoops");
            CreateCellLoops(_meshData, _edgeLoops, p.Config, cf);
            Profiler.EndSample();

            Profiler.BeginSample("Caps");
            CreateCap(_edgeLoops[0], _meshData, cf, 0, -0.33f);
            int startIndex = _meshData.Indices.Count;

            CreateCap(_edgeLoops[_edgeLoops.Count - 1], _meshData, cf, p.Config.NumCells - 1, 0.33f);
            int endIndex = _meshData.Indices.Count;

            InvertFaces(_meshData, startIndex, endIndex);
            Profiler.EndSample();

            Profiler.BeginSample("CreateMesh");
            Mesh m = MeshData.CreateMesh(_meshData);

            Profiler.EndSample();

            Profiler.BeginSample("Finalize");
            mat.color    = p.Config.Color;
            r.bones      = _meshData.Bones.ToArray();
            r.sharedMesh = m;
            r.material   = mat;
            p.CanopyMesh = r;
            Profiler.EndSample();
        }
예제 #3
0
        public static void Initialize(ParachuteMeshConfig cf)
        {
            _meshData = new MeshData();

            const int     maxLoops = 256;
            Queue <int[]> q        = new Queue <int[]>(maxLoops);

            for (int i = 0; i < maxLoops; i++)
            {
                int[] loop = new int[cf.CellChordLoops + cf.CellChordLoops - 2]; // Todo: Make more straightforward
                q.Enqueue(loop);
            }
            _loopPool = new Pool <int[]>(q, ClearLoop);

            _edgeLoops = new List <int[]>(maxLoops);
        }
예제 #4
0
        private static void CreateCap(int[] loop, MeshData md, ParachuteMeshConfig cf, int cell, float bulge)
        {
            // Create a strip of verts through the middle of the foil.
            List <int> midVerts = new List <int>();

            midVerts.Add(loop[0]);
            for (int i = 1; i < loop.Length / 2; i++)
            {
                Vector3 a = md.Vertices[loop[i]];
                Vector3 b = md.Vertices[loop[loop.Length - i]];
                Vector3 v = Vector3.Lerp(a, b, 0.5f);

                v.x += cf.ChordUpperThickness.Evaluate(i / (loop.Length / 2f)) * bulge;

                md.Vertices.Add(v);

                var w = new BoneWeight()
                {
                    boneIndex0 = cell,
                    weight0    = 1f
                };
                md.Weights.Add(w);

                midVerts.Add(md.Vertices.Count - 1);
            }
            midVerts.Add(loop[loop.Length / 2]);

            // Apart from the front and aft points, this can all be quads
            for (int i = 1; i < midVerts.Count - 2; i++)
            {
                // Bot
                md.Indices.Add(midVerts[i + 0]);
                md.Indices.Add(loop[i + 1]);
                md.Indices.Add(loop[i + 0]);

                md.Indices.Add(midVerts[i + 0]);
                md.Indices.Add(midVerts[i + 1]);
                md.Indices.Add(loop[i + 1]);
                //
                // Top
                md.Indices.Add(loop[loop.Length - (i + 0)]);
                md.Indices.Add(loop[loop.Length - (i + 1)]);
                md.Indices.Add(midVerts[i + 0]);

                md.Indices.Add(loop[loop.Length - (i + 1)]);
                md.Indices.Add(midVerts[i + 1]);
                md.Indices.Add(midVerts[i + 0]);
            }

            // Now finish up by adding 4 missing corner triangles

            // Afttop
            md.Indices.Add(midVerts[0]);
            md.Indices.Add(midVerts[1]);
            md.Indices.Add(loop[1]);

            // Aftbot
            md.Indices.Add(midVerts[1]);
            md.Indices.Add(midVerts[0]);
            md.Indices.Add(loop[loop.Length - 1]);

            // FrontTop
            md.Indices.Add(midVerts[midVerts.Count - 2]);
            md.Indices.Add(midVerts[midVerts.Count - 1]);
            md.Indices.Add(loop[loop.Length / 2 - 1]);

            // FrontBot
            md.Indices.Add(midVerts[midVerts.Count - 1]);
            md.Indices.Add(midVerts[midVerts.Count - 2]);
            md.Indices.Add(loop[loop.Length / 2] + 1);
        }
예제 #5
0
        private static void CreateCellEdgeLoop(MeshData md, int[] loop, ParachuteConfig cfg, ParachuteMeshConfig cf, float spanPos, float scale)
        {
            // Note: top vertex row has the outermost chord tip verts. Bottom reuses those.

            int idx = 0;

            float zScale = (0.8f + scale * 0.2f);
            float zMin   = -0.5f * cfg.Chord * zScale;

            // Top
            for (int i = 0; i < cf.CellChordLoops; i++)
            {
                float chordLerp = i / (float)(cf.CellChordLoops - 1);
                float c         = cf.ChordLineCurvature.Evaluate(chordLerp);
                c += cf.ChordUpperThickness.Evaluate(chordLerp) * scale;
                Vector3 v = new Vector3(
                    spanPos,
                    c,
                    zMin + chordLerp * cfg.Chord * zScale
                    );
                md.Vertices.Add(v);
                BoneWeight w = GetBoneWeight(v, cfg);
                md.Weights.Add(w);
                loop[idx++] = md.Vertices.Count - 1;
            }

            // Bottom
            for (int i = 1; i < cf.CellChordLoops - 1; i++)
            {
                float chordLerp = 1f - i / (float)(cf.CellChordLoops - 1);
                float c         = cf.ChordLineCurvature.Evaluate(chordLerp);
                c += cf.ChordLowerThickness.Evaluate(chordLerp) * scale;
                Vector3 v = new Vector3(
                    spanPos,
                    c,
                    zMin + chordLerp * cfg.Chord * zScale
                    );
                md.Vertices.Add(v);
                BoneWeight w = GetBoneWeight(v, cfg);
                md.Weights.Add(w);
                loop[idx++] = md.Vertices.Count - 1;
            }
        }
예제 #6
0
        private static void CreateCellLoops(MeshData md, List <int[]> loops, ParachuteConfig cfg, ParachuteMeshConfig cf)
        {
            // Create the loops
            float spanStep = cfg.Span / cfg.NumCells / cf.CellSpanLoops;

            for (int i = 0; i < cfg.NumCells; i++)
            {
                for (int j = 0; j < cf.CellSpanLoops; j++)
                {
                    float z = spanStep * (i * cf.CellSpanLoops + j);
                    float s = cf.SpanCellCurvature.Evaluate(j / ((float)cf.CellSpanLoops));

                    var l = _loopPool.Take();
                    CreateCellEdgeLoop(md, l, cfg, cf, z, s);
                    loops.Add(l);
                }
            }

            // Create the last loop
            var ll = _loopPool.Take();

            CreateCellEdgeLoop(md, ll, cfg, cf, cfg.Span, cf.SpanCellCurvature.Evaluate(1f));
            loops.Add(ll);

            // Create the faces between the loops
            for (int i = 0; i < loops.Count - 1; i++)
            {
                CreateLoopFaces(loops[i], loops[i + 1], md);
            }
        }