Пример #1
0
        public void UpdateRenderer(List <StrokePoint> stroke, int maxChangedFromEnd)
        {
            int startIdx = Mathf.Max(0, stroke.Count - 1 - maxChangedFromEnd);
            int endIdx   = stroke.Count - 1;

            for (int i = startIdx; i <= endIdx; i++)
            {
                StrokePoint strokePoint = stroke[i];

                MeshPoint point = new MeshPoint(strokePoint.position);
                point.Normal = strokePoint.normal;
                point.Color  = strokePoint.color;

                if (i > _ribbon.Points.Count - 1)
                {
                    _ribbon.Add(point, strokePoint.thickness);
                }
                else
                {
                    _ribbon.Points[i] = point;
                    _ribbon.Radii[i]  = strokePoint.thickness;
                }
            }

            _stroke = stroke;
            SetMeshDataFromRibbon(_mesh, _ribbon);
        }
Пример #2
0
        private void RefreshRenderTrail()
        {
            Vector3 endPosition = _lastStrokeBuffer.GetLatest().position;

            for (int i = 0; i < _lastStrokeBuffer.Count; i++)
            {
                StrokePoint strokePoint = _lastStrokeBuffer.Get(i);

                MeshPoint point = new MeshPoint(strokePoint.position);
                point.Normal = strokePoint.normal;
                point.Color  = strokePoint.color;

                if (i > _ribbon.Points.Count - 1)
                {
                    _ribbon.Add(point, strokePoint.thickness);
                }
                else
                {
                    // Offset from most recent + decay
                    Vector3 offsetFromEndPosition = endPosition - point.Position;
                    Vector3 targetOffset          = (offsetFromEndPosition * (1 - _thicknessDecayMultiplier));
                    if (i > _prevDrawOffsets.Count - 1)
                    {
                        _prevDrawOffsets.Add(targetOffset);
                    }
                    point.Position      = point.Position + Vector3.Slerp(_prevDrawOffsets[i], targetOffset, 0.1F);
                    _prevDrawOffsets[i] = Vector3.Slerp(_prevDrawOffsets[i], targetOffset, 0.1F);
                    _ribbon.Points[i]   = point;

                    // Thickness + decay
                    int maxBufferSize = 16;
                    //int effBufferSize = Mathf.Min(maxBufferSize, _lastStrokeBuffer.Size - 1);
                    float thicknessCurveEvalPos = Mathf.Min(1F, (float)(_lastStrokeBuffer.Count - 1 - i) / maxBufferSize); // ([0-16]) / 8 --> 0, 1/8, 2/8, ... 1, 1, 1
                    float targetThickness       = 0F;
                    if (_lastStrokeBuffer.Count > 1)
                    {
                        targetThickness = strokePoint.thickness * previewThicknessCurve.Evaluate(thicknessCurveEvalPos) * _thicknessDecayMultiplier;
                    }
                    if (i > _prevDrawRadii.Count - 1)
                    {
                        _prevDrawRadii.Add(targetThickness);
                    }
                    if (_lastStrokeBuffer.Count - 1 - i < maxBufferSize)
                    {
                        _ribbon.Radii[i] = Mathf.Lerp(_prevDrawRadii[i], targetThickness, 0.05F);
                    }
                    else
                    {
                        _ribbon.Radii[i] = 0F;
                    }
                    _prevDrawRadii[i] = _ribbon.Radii[i];
                }
            }

            SetMeshDataFromRibbon(_mesh, _ribbon);
        }
Пример #3
0
        // shouldUpdateRenderers provides an optimization for updating multiple stroke points at once,
        // where it's more efficient to do the updating without rendering and then refreshing renderers
        // at the end.
        private void UpdateStroke(StrokePoint strokePoint, bool shouldUpdateRenderers = true)
        {
            _strokeBuffer.Add(strokePoint);
            _actualizedStrokeIdxBuffer.Add(-1);

            // Apply all filters in order on current stroke buffer.
            for (int i = 0; i < _strokeFilters.Count; i++)
            {
                _strokeFilters[i].Process(_strokeBuffer, _actualizedStrokeIdxBuffer);
            }

            if (_isActualizingStroke)
            {
                _actualizedStrokeIdxBuffer.SetLatest(_actualizedStrokeIdx++);

                // Output points from the buffer to the actualized stroke output.
                int offset = Mathf.Min(_outputBufferEndOffset, _strokeBuffer.Count - 1);
                for (int i = 0; i <= offset; i++)
                {
                    int         outputIdx         = Mathf.Max(0, _outputBufferEndOffset - (_strokeBuffer.Count - 1)) + i;
                    StrokePoint bufferStrokePoint = _strokeBuffer.Get(_strokeBuffer.Count - 1 - (Mathf.Min(_strokeBuffer.Count - 1, _outputBufferEndOffset) - i));
                    if (outputIdx > _strokeOutput.Count - 1)
                    {
                        _strokeOutput.Add(bufferStrokePoint);
                    }
                    else
                    {
                        _strokeOutput[outputIdx] = bufferStrokePoint;
                    }
                }
                _outputBufferEndOffset += 1;

                // Refresh stroke renderers.
                if (shouldUpdateRenderers)
                {
                    UpdateStrokeRenderers();
                }
            }

            // Refresh stroke preview renderers.
            if (shouldUpdateRenderers)
            {
                UpdateStrokeBufferRenderers();
            }
        }
Пример #4
0
        private void ProcessAddStrokePoints(List <Vector3> points, List <float> effDeltaTimes)
        {
            if (points.Count != effDeltaTimes.Count)
            {
                Debug.LogError("[PinchStrokeProcessor] Points count must match effDeltaTimes count.");
                return;
            }

            _cachedStrokePoints.Clear();
            for (int i = 0; i < points.Count; i++)
            {
                Vector3 point        = points[i];
                float   effDeltaTime = effDeltaTimes[i];

                bool shouldAdd = !_firstStrokePointAdded ||
                                 Vector3.Distance(_lastStrokePointAdded, point)
                                 >= Mathf.Lerp(MIN_THICKNESS_MIN_SEGMENT_LENGTH, MAX_THICKNESS_MIN_SEGMENT_LENGTH, _thicknessFilter._lastNormalizedValue);

                _timeSinceLastAddition += effDeltaTime;

                if (shouldAdd)
                {
                    StrokePoint strokePoint = new StrokePoint();
                    strokePoint.position        = point;
                    strokePoint.rotation        = Quaternion.identity;
                    strokePoint.handOrientation = _paintCursor.Rotation * Quaternion.Euler((_paintCursor.Handedness == Chirality.Left ? leftHandEulerRotation : rightHandEulerRotation));
                    strokePoint.deltaTime       = _timeSinceLastAddition;

                    _cachedStrokePoints.Add(strokePoint);

                    _firstStrokePointAdded = true;
                    _lastStrokePointAdded  = strokePoint.position;
                    _timeSinceLastAddition = 0F;
                }
            }
            _strokeProcessor.UpdateStroke(_cachedStrokePoints);
        }
Пример #5
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;
        }
Пример #6
0
 public void UpdateStroke(StrokePoint strokePoint)
 {
     UpdateStroke(strokePoint, true);
 }