Ejemplo n.º 1
0
    private void CalStrokeUpperAndLowerPoint(StrokePoint[] spAry)
    {
        Vector3 widthVec = new Vector3(0.0f, 0.0f, 1.0f);
        Vector3 forward  = new Vector3(1.0f, 0.0f, 0.0f);
        Vector3 upward   = new Vector3(0.0f, 1.0f, 0.0f);

        // The first of the point
        forward             = spAry[1].centerPoint - spAry[0].centerPoint;
        widthVec            = Vector3.Cross(upward, forward).normalized;
        spAry[0].upperPoint = spAry[0].centerPoint - spAry[0].weight * widthVec;
        spAry[0].lowerPoint = spAry[0].centerPoint + spAry[0].weight * widthVec;

        for (int i = 1; i < spAry.Length - 1; i++)
        {
            StrokePoint prevPoint = spAry[i - 1];
            StrokePoint currPoint = spAry[i];
            StrokePoint nextPoint = spAry[i + 1];
            forward = nextPoint.centerPoint - prevPoint.centerPoint;

            widthVec            = Vector3.Cross(upward, forward).normalized;
            spAry[i].upperPoint = currPoint.centerPoint - currPoint.weight * widthVec;
            spAry[i].lowerPoint = currPoint.centerPoint + currPoint.weight * widthVec;
        }

        // The last of the point
        spAry[spAry.Length - 1].upperPoint = spAry[spAry.Length - 1].centerPoint - spAry[spAry.Length - 1].weight * widthVec;
        spAry[spAry.Length - 1].lowerPoint = spAry[spAry.Length - 1].centerPoint + spAry[spAry.Length - 1].weight * widthVec;
    }
Ejemplo n.º 2
0
    public void AddSkeletonVertex(Vector3 _targetPoint, float _weight)
    {
        StrokePoint sp = new StrokePoint();

        sp.centerPoint = _targetPoint;
        sp.weight      = _weight;
        m_StrokeSkeletonPointList.Add(sp);
    }
Ejemplo n.º 3
0
    /// <summary>
    /// Called once per rendered frame.
    /// </summary>
    ///
    void Update()
    {
        if (actionSave.IsActivated())
        {
            // save to file
            string baseFilename = "StrokeExport_" + System.DateTime.Now.ToString("yyyyMMdd_HHmmss");
            SaveStrokeData(baseFilename);
            Debug.Log("Exported strokes to " + baseFilename);
        }

        if (actionReset.IsActivated())
        {
            // clear all strokes
            ClearStrokes();
        }

        if ((strokeMesh == null) && actionUndo.IsActivated())
        {
            // only allow undo when not painting
            UndoLastStroke();
        }

        // read size/colour buttons
        float sizeChange   = actionSize.GetValue();
        float colourChange = actionColour.GetValue();

        // only allow one of the actions
        if (Mathf.Abs(sizeChange) > Mathf.Abs(colourChange))
        {
            colourChange = 0;
        }
        else
        {
            sizeChange = 0;
        }

        // process changing colour
        if (colourChange != 0)
        {
            strokeColourIdx += colourChange * Time.deltaTime * colourChangeSpeed;
            strokeColourIdx  = Mathf.Repeat(strokeColourIdx, 1);
            // force creation of new material
            strokeMaterials = null;
            if (colourIndicator != null)
            {
                colourIndicator.gameObject.SetActive(true);
                Quaternion q = Quaternion.AngleAxis(-strokeColourIdx * 360, Vector3.forward);
                colourIndicator.localRotation = q;
                strokeIndicatorTimer          = Time.time + 1;        // hide indicator 1s from now
            }
        }
        else
        {
            // hide colour indicator after timeout
            if ((colourIndicator != null) && (Time.time > strokeIndicatorTimer))
            {
                colourIndicator.gameObject.SetActive(false);
            }
        }
        strokeColour = colourPalette.GetPixelBilinear(strokeColourIdx, 0.5f);

        // process size change
        if (sizeChange != 0)
        {
            // change brush size
            sizeFactor += sizeChange * Time.deltaTime;
            sizeFactor  = Mathf.Clamp(sizeFactor, 0, 1);
        }
        strokeWidth = Mathf.Lerp(strokeWidthMinimum, strokeWidthMaximum, sizeFactor);

        if (trailRenderer != null)
        {
            trailRenderer.startWidth = strokeWidth;
            foreach (Material m in trailRenderer.materials)
            {
                m.SetColor("_Color", strokeColour);
                m.SetColor("_TintColor", strokeColour);
                m.SetColor("_EmissionColor", strokeColour);
            }
        }
        if (colourIndicatorMesh != null)
        {
            // is there a mesh rendering the active colour?
            colourIndicatorMesh.material.color = strokeColour;
        }

        if (brushObject != null)
        {
            brushObject.localScale = new Vector3(brushObject.localScale.x, strokeWidth, brushObject.localScale.z);
            Renderer renderer = brushObject.GetComponent <Renderer>();
            foreach (Material m in renderer.materials)
            {
                m.SetColor("_Color", strokeColour);
                m.SetColor("_TintColor", strokeColour);
                m.SetColor("_EmissionColor", strokeColour);
            }
        }

        // handle paint button
        bool painting = actionPaint.IsActive();

        if (painting && (strokeMesh == null))
        {
            // start data structure
            activeStroke           = new Stroke();
            activeStroke.startTime = Time.time;

            // start new mesh for the stroke and add to common container
            activeStroke.gameObject                  = new GameObject();
            activeStroke.gameObject.name             = string.Format("Stroke_{0:D3}", strokeIndex);
            activeStroke.gameObject.transform.parent = strokeContainer.transform;

            // create new material?
            if (strokeMaterials == null)
            {
                Material mat = Instantiate <Material>(strokeBaseMaterial);
                mat.name           = string.Format("StrokeMaterial_{0:D3}", strokeMaterialIndex);
                mat.color          = strokeColour;
                strokeMaterials    = new Material[2];
                strokeMaterials[0] = mat;
                strokeMaterials[1] = mat;
                strokeMaterialIndex++;
            }

            // create renderer
            MeshRenderer renderer = activeStroke.gameObject.AddComponent <MeshRenderer>();
            renderer.receiveShadows    = true;
            renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided;
            renderer.materials         = strokeMaterials;

            // create mesh
            strokeMesh = activeStroke.gameObject.AddComponent <MeshFilter>().mesh;
            strokeMesh.MarkDynamic();             // this is going to change a lot
            strokeMesh.subMeshCount = 2;
            strokePoints            = new List <Vector3>();
            vertices = new List <Vector3>();
            normals  = new List <Vector3>();
            //uvCoords     = new List<Vector2>();
            topology     = new List <int>();
            topologyBack = new List <int>();

            lastPoint = new Vector3();
            strokeIndex++;

            if (spraySound != null)
            {
                spraySound.loop = true;
                spraySound.Play();
            }
        }
        else if (!painting && (strokeMesh != null))
        {
            // stop painting
            strokeMesh = null;

            // save last stroke
            activeStroke.endTime = Time.time;
            strokeList.Add(activeStroke);
            activeStroke = null;

            if (spraySound != null)
            {
                spraySound.Stop();
            }
        }

        // stroke is being constructed: handle last point
        if (strokeMesh != null)
        {
            Vector3 tipPos = this.transform.position;
            if (Vector3.Distance(lastPoint, tipPos) > minimumSegmentSize)
            {
                AddPoint(tipPos, this.transform.up);
                lastPoint = tipPos;
            }
            else
            {
                SetLastPoint(tipPos, this.transform.up);
            }
        }

        // record stroke data
        if (activeStroke != null)
        {
            StrokePoint p = new StrokePoint();
            p.position     = this.transform.position;
            p.orientation  = this.transform.rotation;
            p.strokeSize   = strokeWidth;
            p.strokeColour = strokeColour;
            p.timestamp    = Time.time;
            activeStroke.points.Add(p);
        }
    }
Ejemplo n.º 4
0
    public MeshRenderer CreateStrokeMesh(ref Stroke stroke, ref GameObject go, int stepSize)
    {
        // create renderer
        MeshRenderer renderer = go.AddComponent <MeshRenderer>();

        // create mesh
        Mesh strokeMesh = go.AddComponent <MeshFilter>().mesh;

        strokeMesh.subMeshCount = 2;
        List <Vector3> vertices = new List <Vector3>();
        List <Vector3> normals  = new List <Vector3>();
        //uvCoords     = new List<Vector2>();
        List <int> topology     = new List <int>();
        List <int> topologyBack = new List <int>();

        int     length  = stroke.points.Count;
        int     lIdx    = 0;
        Vector3 lastPos = Vector3.zero;

        for (int pIdx = 0; pIdx < length + stepSize; pIdx += stepSize)
        {
            StrokePoint p   = stroke.points[Mathf.Min(pIdx, length - 1)];
            Vector3     pos = p.position;

            // avoid very short (or zero length) segments
            if (stepSize == 1)
            {
                Vector3 delta = pos - lastPos;
                if (delta.magnitude < minimumSegmentSize)
                {
                    continue;
                }
                lastPos = pos;
            }

            // clauclate normal
            Vector3 up  = p.orientation * Vector3.up;
            Vector3 dir = (pIdx > 0) ? (pos - stroke.points[pIdx - stepSize].position) : pos;
            dir.Normalize();
            Vector3 normal = Vector3.Cross(up, dir);

            // add top/bottom vertices for front/back
            up *= p.strokeSize * 0.5f;
            vertices.Add(pos + up);
            vertices.Add(pos + up);
            vertices.Add(pos - up);
            vertices.Add(pos - up);

            // add two normals each for front/back (but not for first point)
            normals.Add(normal);
            normals.Add(-normal);
            normals.Add(normal);
            normals.Add(-normal);

            if (lIdx == 1)
            {
                // add normals for first point = equal to second point
                normals[0] = normal;
                normals[1] = -normal;
                normals[2] = normal;
                normals[3] = -normal;
            }

            if (lIdx > 0)
            {
                // more than one point > start building topology
                // Front: 2  6    Back: 3  7
                //        x  x          x  x
                //        0  4          1  5
                int idx = (lIdx + 1) * 4;                                                        // two points > idx = 8
                topology.Add(idx - 8); topology.Add(idx - 4); topology.Add(idx - 6);             // 0 > 4 > 2
                topology.Add(idx - 6); topology.Add(idx - 4); topology.Add(idx - 2);             // 2 > 4 > 6
                // backface > reverse direction
                topologyBack.Add(idx - 7); topologyBack.Add(idx - 5); topologyBack.Add(idx - 3); // 1 > 3 > 5
                topologyBack.Add(idx - 5); topologyBack.Add(idx - 1); topologyBack.Add(idx - 3); // 3 > 7 > 5
            }
            lIdx++;
        }

        strokeMesh.SetVertices(vertices);
        strokeMesh.SetNormals(normals);
        strokeMesh.SetTriangles(topology, 0);
        strokeMesh.SetTriangles(topologyBack, 1);
        strokeMesh.RecalculateBounds();

        return(renderer);
    }
        private void updateMeshRepresentation()
        {
            // Index + Thumb points -> StrokePoints in a StrokeObject.
            if (_strokeObj == null)
            {
                _strokeObj = gameObject.AddComponent <StrokeObject>();
            }

            // Get color via Ucon wiring.
            var brushColor = colorChannelIn.Get();

            _strokeObj.Clear();
            for (int i = 1; i < indexPoints.Count; i++)
            {
                var avgPos     = (indexPoints[i] + thumbPoints[i]) * 0.5f;
                var prevAvgPos = (indexPoints[i - 1] + thumbPoints[i - 1]) * 0.5f;

                var right   = (indexPoints[i] - thumbPoints[i]).normalized;
                var forward = (avgPos - prevAvgPos).normalized;
                if ((avgPos - prevAvgPos).sqrMagnitude < 1e-7f)
                {
                    continue;
                }
                var up  = Vector3.Cross(right, forward).normalized;
                var rot = Quaternion.LookRotation(forward, up);

                var radius = (indexPoints[i] - thumbPoints[i]).magnitude * 0.3f;

                var strokePoint = new StrokePoint()
                {
                    pose          = new Pose(avgPos, rot),
                    color         = brushColor,
                    radius        = radius,
                    temp_refFrame = Matrix4x4.identity
                };

                _strokeObj.Add(strokePoint);
            }

            // StrokeObjects -> PolyMesh.
            fillPolyMeshObject.polyMesh.Clear();
            var positions   = Pool <List <Vector3> > .Spawn(); positions.Clear();
            var polygons    = Pool <List <Polygon> > .Spawn(); polygons.Clear();
            var smoothEdges = Pool <List <Edge> > .Spawn(); smoothEdges.Clear();
            var colors      = Pool <List <Color> > .Spawn(); colors.Clear();

            try {
                strokePolyMesher.FillPolyMeshData(_strokeObj,
                                                  positions, polygons, smoothEdges, colors);

                fillPolyMeshObject.polyMesh.Fill(positions, polygons, smoothEdges, colors);
            }
            finally {
                positions.Clear(); Pool <List <Vector3> > .Recycle(positions);

                polygons.Clear(); Pool <List <Polygon> > .Recycle(polygons);

                smoothEdges.Clear(); Pool <List <Edge> > .Recycle(smoothEdges);

                colors.Clear(); Pool <List <Color> > .Recycle(colors);
            }

            // Refresh the Unity mesh representation of the PolyMeshObject.
            fillPolyMeshObject.RefreshUnityMesh();
        }
Ejemplo n.º 6
0
    public bool LoadStrokeData(string baseFilename)
    {
        bool success = false;

        if (!baseFilename.Contains(".csv"))
        {
            baseFilename = baseFilename + ".csv";
        }

        using (StreamReader sr = new StreamReader(baseFilename))
        {
            // read header
            string header = sr.ReadLine();
            success = header.Equals("time,strokeIdx,pointIdx,posX,posY,posZ,rotX,rotY,rotZ,rotW,width,colR,colG,colB,colA");

            if (success)
            {
                int    strokeIdx = 0;
                string line;
                Stroke stroke = null;
                average = Vector3.zero;
                int pointCount = 0;
                this.Clear();

                while ((line = sr.ReadLine()) != null)
                {
                    string[] parts = line.Split(',');
                    // check stroke index
                    int sIdx = int.Parse(parts[1]);
                    if (sIdx != strokeIdx)
                    {
                        // new stroke starts
                        if (stroke != null)
                        {
                            stroke.startTime = stroke.points[0].timestamp;
                            stroke.endTime   = stroke.points[stroke.points.Count - 1].timestamp;
                            this.Add(stroke);
                        }
                        strokeIdx = sIdx;
                        stroke    = new Stroke();
                    }

                    // read point data
                    StrokePoint p = new StrokePoint();
                    p.timestamp = float.Parse(parts[0]);
                    // [1] stroke idx
                    // [2] point idx
                    p.position.x     = float.Parse(parts[3]);
                    p.position.y     = float.Parse(parts[4]);
                    p.position.z     = float.Parse(parts[5]);
                    p.orientation.x  = float.Parse(parts[6]);
                    p.orientation.y  = float.Parse(parts[7]);
                    p.orientation.z  = float.Parse(parts[8]);
                    p.orientation.w  = float.Parse(parts[9]);
                    p.strokeSize     = float.Parse(parts[10]);
                    p.strokeColour.r = float.Parse(parts[11]);
                    p.strokeColour.g = float.Parse(parts[12]);
                    p.strokeColour.b = float.Parse(parts[13]);
                    p.strokeColour.a = float.Parse(parts[14]);
                    stroke.points.Add(p);

                    bounds.Encapsulate(p.position);
                    average += p.position;
                    pointCount++;
                }

                // add last stroke
                if (stroke != null)
                {
                    stroke.startTime = stroke.points[0].timestamp;
                    stroke.endTime   = stroke.points[stroke.points.Count - 1].timestamp;
                    this.Add(stroke);
                }

                average /= pointCount;
            }
        }
        return(success);
    }
Ejemplo n.º 7
0
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            currentStroke = StartNewStroke();
            strokes.Add(currentStroke);

            GameObject goStrokeMesh = Instantiate(strokeMeshPrefab);
            Mesh strokeMesh = new Mesh();
            strokeMesh.MarkDynamic();
            goStrokeMesh.GetComponent<MeshFilter>().mesh = strokeMesh;
            strokeMeshes.Add(strokeMesh);
        }
        else if (Input.GetMouseButtonUp(0))
        {
            EndStroke();
            currentStroke = null;
        }

        if (Input.GetMouseButton(0) &&
            Input.mousePosition != prevMousePosition)
        {
            Vector3 screenPoint = Input.mousePosition;
            screenPoint.z = Camera.main.nearClipPlane;

            StrokePoint sp = new StrokePoint(Camera.main.ScreenToWorldPoint(screenPoint),
                                             Time.realtimeSinceStartup);
            currentStroke.AddPoint(sp);
            //Debug.Log (Input.mousePosition);
            //Debug.Log(Camera.main.ScreenToWorldPoint(screenPoint));

            // Rebuild mesh for this stroke.
            Mesh strokeMesh = (Mesh)strokeMeshes[strokeMeshes.Count - 1];
            strokeMesh.Clear ();

            Vector3[] vertices = new Vector3[currentStroke.CountPoints];
            Vector2[] uvs = new Vector2[currentStroke.CountPoints];
            int[] indices = new int[currentStroke.CountPoints];

            for (int i = 0; i < currentStroke.CountPoints; ++ i)
            {
                vertices[i] = currentStroke.getPoint(i);
                uvs[i] = Vector2.zero;
                indices[i] = i;
            }

            strokeMesh.vertices = vertices;
            strokeMesh.uv = uvs;
            strokeMesh.SetIndices(indices, MeshTopology.LineStrip, 0);
        }

        foreach (Stroke s in strokes)
        {
            for (int iSegment = 0; iSegment < s.CountSegments; ++iSegment)
            {
                Vector3 p0;
                Vector3 p1;

                s.getSegmentPoints(iSegment, out p0, out p1);
                //Debug.DrawLine(p0, p1, Color.black);
            }
        }

        prevMousePosition = Input.mousePosition;
    }
Ejemplo n.º 8
0
 public void AddPoint(StrokePoint sp)
 {
     points.Add(sp);
 }