Beispiel #1
0
        private void AddRibbonSegmentIndices(RibbonSegment ribbonSegment, int firstSegmentVertIdx, List <int> indices)
        {
            int v = firstSegmentVertIdx;

            // Startcap
            if (ribbonSegment.hasStartCap)
            {
                indices.Add(v + 0);
                indices.Add(v + 1);
                indices.Add(v + 2);

                indices.Add(v + 0);
                indices.Add(v + 2);
                indices.Add(v + 3);

                v += 4; // having a startcap offsets the expected vertex index for this segment

                // Side up
                indices.Add(v + 0);
                indices.Add(v + 1);
                indices.Add(v + 9);

                indices.Add(v + 0);
                indices.Add(v + 9);
                indices.Add(v + 8);

                // Side right
                indices.Add(v + 2);
                indices.Add(v + 3);
                indices.Add(v + 11);

                indices.Add(v + 2);
                indices.Add(v + 11);
                indices.Add(v + 10);

                // Side down
                indices.Add(v + 4);
                indices.Add(v + 5);
                indices.Add(v + 13);

                indices.Add(v + 4);
                indices.Add(v + 13);
                indices.Add(v + 12);

                // Side left
                indices.Add(v + 6);
                indices.Add(v + 7);
                indices.Add(v + 15);

                indices.Add(v + 6);
                indices.Add(v + 15);
                indices.Add(v + 14);
            }
            else
            {
                // With no startcap, side tris connect to previous segment's verts.

                // Side up
                indices.Add(v + 0);
                indices.Add(v - 8);
                indices.Add(v + 1);

                indices.Add(v + 1);
                indices.Add(v - 8);
                indices.Add(v - 7);

                // Side right
                indices.Add(v + 2);
                indices.Add(v - 6);
                indices.Add(v + 3);

                indices.Add(v + 3);
                indices.Add(v - 6);
                indices.Add(v - 5);

                // Side down
                indices.Add(v + 4);
                indices.Add(v - 4);
                indices.Add(v + 5);

                indices.Add(v + 5);
                indices.Add(v - 4);
                indices.Add(v - 3);

                // Side left
                indices.Add(v + 6);
                indices.Add(v - 2);
                indices.Add(v + 7);

                indices.Add(v + 7);
                indices.Add(v - 2);
                indices.Add(v - 1);
            }

            // Endcap
            if (ribbonSegment.hasEndCap)
            {
                if (ribbonSegment.hasStartCap)
                {
                    v += 16;
                }
                else
                {
                    v += 8;
                }

                indices.Add(v + 0);
                indices.Add(v + 1);
                indices.Add(v + 2);

                indices.Add(v + 0);
                indices.Add(v + 2);
                indices.Add(v + 3);
            }
        }
Beispiel #2
0
        public void UpdateRenderer(List <StrokePoint> stroke, int maxChangedFromEnd)
        {
            if (stroke.Count <= 1 || maxChangedFromEnd == 0)
            {
                return;
            }

            if (OnUpdateRenderer != null)
            {
                OnUpdateRenderer(stroke, maxChangedFromEnd);
            }

            int startIdx = Mathf.Max(0, (stroke.Count - 1) - maxChangedFromEnd - 1);
            int endIdx   = stroke.Count - 1;

            // Lop off outdated vertices and indices.

            int expectedNewNumRibbons     = stroke.Count - 1;
            int firstChangedRibbonIndex   = expectedNewNumRibbons - 1 - maxChangedFromEnd;
            int numRibbonSegmentsOutdated = _ribbonSegments.Count - firstChangedRibbonIndex;
            int numVertsOutdated          = 0;
            int numRibbonVertsAccountFor  = 0;
            int numIndicesOutdated        = 0;

            for (int i = 0; i < numRibbonSegmentsOutdated; i++)
            {
                if (i >= 0 && i < _ribbonSegments.Count)
                {
                    numVertsOutdated += _ribbonSegments[_ribbonSegments.Count - 1 - i].NumVerts();
                    numRibbonVertsAccountFor++;
                    numIndicesOutdated += _ribbonSegments[_ribbonSegments.Count - 1 - i].NumIndices();
                }
            }
            for (int i = 0; i < numVertsOutdated; i++)
            {
                if (_verts.Count > 0)
                {
                    _verts.RemoveAt(_verts.Count - 1);
                    _colors.RemoveAt(_colors.Count - 1);
                    _normals.RemoveAt(_normals.Count - 1);
                }
            }
            for (int i = 0; i < numIndicesOutdated; i++)
            {
                if (_indices.Count > 0)
                {
                    _indices.RemoveAt(_indices.Count - 1);
                }
            }

            // Update Ribbon Segment representation.
            for (int i = startIdx; i < endIdx; i++)
            {
                // Define the current ribbon segment.
                StrokePoint curPoint            = stroke[i];
                StrokePoint nextPoint           = stroke[i + 1];
                Vector3     curSegmentDirection = (nextPoint.position - curPoint.position).normalized;

                Vector3 prevSegmentDirection = curSegmentDirection;
                bool    hasPrevSegment       = (i > 0);
                if (hasPrevSegment)
                {
                    prevSegmentDirection = (stroke[i].position - stroke[i - 1].position).normalized;
                }

                Vector3 nextSegmentDirection = curSegmentDirection;
                bool    hasNextSegment       = (i < endIdx - 1);
                if (hasNextSegment)
                {
                    nextSegmentDirection = (stroke[i + 2].position - stroke[i + 1].position).normalized;
                }

                bool curSegmentHasStartCap = i == 0;
                if (hasPrevSegment)
                {
                    curSegmentHasStartCap = (Vector3.Dot(prevSegmentDirection, curSegmentDirection) < -0.8F);
                }
                Vector3 startFacing, startNormal;
                if (curSegmentHasStartCap)
                {
                    startFacing = -curSegmentDirection;
                    startNormal = curPoint.normal;
                }
                else
                {
                    startFacing = -(prevSegmentDirection + curSegmentDirection).normalized;
                    startNormal = (stroke[i - 1].normal + curPoint.normal).normalized;
                }

                bool curSegmentHasEndCap = i == stroke.Count - 2;
                if (hasNextSegment)
                {
                    curSegmentHasEndCap = (Vector3.Dot(curSegmentDirection, nextSegmentDirection) < -0.8F);
                }
                Vector3 endFacing, endNormal;
                if (curSegmentHasEndCap)
                {
                    endFacing = curSegmentDirection;
                    endNormal = curPoint.normal;
                }
                else
                {
                    endFacing = (curSegmentDirection + nextSegmentDirection).normalized;
                    endNormal = (curPoint.normal + nextPoint.normal).normalized;
                }

                RibbonSegment curRibbonSegment = new RibbonSegment(
                    curPoint.position,
                    startFacing,
                    startNormal,
                    curPoint.thickness,
                    nextPoint.position,
                    endFacing,
                    endNormal,
                    nextPoint.thickness,
                    curSegmentHasStartCap,
                    curSegmentHasEndCap
                    );

                // Add or modify the constructed ribbon segment
                if (i > _ribbonSegments.Count - 1)
                {
                    // Add a new ribbon segment definition.
                    _ribbonSegments.Add(curRibbonSegment);
                }
                else
                {
                    // Modify an existing ribbon segment definition.
                    _ribbonSegments[i] = curRibbonSegment;
                }
            }

            // Construct and add new vertices and indices per RibbonSegment.
            for (int i = startIdx; i < endIdx; i++)
            {
                AddRibbonSegmentIndices(_ribbonSegments[i], _verts.Count, _indices);
                AddRibbonSegmentVerts(_ribbonSegments[i], _verts, _normals);
                for (int j = 0; j < _ribbonSegments[i].NumVerts(); j++) // color vertices
                {
                    _colors.Add(stroke[i].color);
                }
            }

            _mesh.Clear();
            _mesh.SetVertices(_verts);
            _mesh.SetTriangles(_indices, 0);
            _mesh.SetNormals(_normals);
            _mesh.SetColors(_colors);
            _mesh.RecalculateBounds();
            _mesh.RecalculateNormals();
            _mesh.UploadMeshData(false);

            _cachedStrokeRenderered = stroke;
        }
Beispiel #3
0
        private void AddRibbonSegmentVerts(RibbonSegment ribbonSegment, List <Vector3> verts, List <Vector3> normals)
        {
            // Vertex order:
            // Side up, right, down, left
            // Startcap (if any)
            // Endcap (if any)
            Vector3 startPos         = ribbonSegment.startPos;
            Vector3 startFaceLeftDir = Vector3.Cross(ribbonSegment.startFacing, ribbonSegment.startNormal).normalized;
            Vector3 startFaceUpDir   = ribbonSegment.startNormal;
            float   startXThickness  = ribbonSegment.startThickness;
            float   startYThickness  = ribbonSegment.startThickness * VERTICAL_THICKNESS_MULTIPLIER;
            Vector3 endPos           = ribbonSegment.endPos;
            Vector3 endFaceLeftDir   = Vector3.Cross(ribbonSegment.endNormal, ribbonSegment.endFacing).normalized; // "left" looking at/through the start face
            Vector3 endFaceUpDir     = ribbonSegment.endNormal;
            float   endXThickness    = ribbonSegment.endThickness;
            float   endYThickness    = ribbonSegment.endThickness * VERTICAL_THICKNESS_MULTIPLIER;

            Vector3 startLeft  = startFaceLeftDir * startXThickness;
            Vector3 startRight = -startLeft;
            Vector3 startUp    = startFaceUpDir * startYThickness;
            Vector3 startDown  = -startUp;

            Vector3 endLeft  = endFaceLeftDir * endXThickness;
            Vector3 endRight = -endLeft;
            Vector3 endUp    = endFaceUpDir * endYThickness;
            Vector3 endDown  = -endUp;

            // Startcap
            if (ribbonSegment.hasStartCap)
            {
                verts.Add(startPos + startLeft + startDown);
                verts.Add(startPos + startRight + startDown);
                verts.Add(startPos + startRight + startUp);
                verts.Add(startPos + startLeft + startUp);
                normals.Add(ribbonSegment.startFacing);
                normals.Add(ribbonSegment.startFacing);
                normals.Add(ribbonSegment.startFacing);
                normals.Add(ribbonSegment.startFacing);

                // Start side up
                verts.Add(startPos + startLeft + startUp);
                verts.Add(startPos + startRight + startUp);
                normals.Add(startUp);
                normals.Add(startUp);

                // Start side right
                verts.Add(startPos + startRight + startUp);
                verts.Add(startPos + startRight + startDown);
                normals.Add(startRight);
                normals.Add(startRight);

                // Start side down
                verts.Add(startPos + startRight + startDown);
                verts.Add(startPos + startLeft + startDown);
                normals.Add(startDown);
                normals.Add(startDown);

                // Start side left
                verts.Add(startPos + startLeft + startDown);
                verts.Add(startPos + startLeft + startUp);
                normals.Add(startLeft);
                normals.Add(startLeft);
            }

            // End side up
            verts.Add(endPos + endLeft + endUp);
            verts.Add(endPos + endRight + endUp);
            normals.Add(endUp);
            normals.Add(endUp);

            // End side right
            verts.Add(endPos + endRight + endUp);
            verts.Add(endPos + endRight + endDown);
            normals.Add(endRight);
            normals.Add(endRight);

            // End side down
            verts.Add(endPos + endRight + endDown);
            verts.Add(endPos + endLeft + endDown);
            normals.Add(endDown);
            normals.Add(endDown);

            // End side left
            verts.Add(endPos + endLeft + endDown);
            verts.Add(endPos + endLeft + endUp);
            normals.Add(endLeft);
            normals.Add(endLeft);

            // Endcap
            if (ribbonSegment.hasEndCap)
            {
                verts.Add(endPos + endLeft + endUp);
                verts.Add(endPos + endRight + endUp);
                verts.Add(endPos + endRight + endDown);
                verts.Add(endPos + endLeft + endDown);
                normals.Add(ribbonSegment.endFacing);
                normals.Add(ribbonSegment.endFacing);
                normals.Add(ribbonSegment.endFacing);
                normals.Add(ribbonSegment.endFacing);
            }
        }