Dayner Kurdi
Dayner Kurdi

Reputation: 13

Unity: procedural generated mesh vertices's position are wrong/off

I'm generating points and mesh on run-time, the problem is, the generated mesh vertices appeared in the wrong position, even if I pass on the point's global position.

the mesh generating part is made in MakeMeshData();

I tired calculating with all my points with position instead of localPosition, as well as commenting out the parenting, still the same result .

https://i.sstatic.net/pXTZi.jpg

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class NPG03_Corridor : MonoBehaviour
{
    public Transform centerPoint;
    public Transform startPoint;
    public Transform endPoint;

    public enum CORRIDORTYPE
    {
        LinearBezierCurves,

        QuadraticBezierCurves,

        CubicBezierCurve
    }

    public CORRIDORTYPE corridorType;

    public List<Transform> centerLinePoints = new List<Transform>();
    public List<Transform> corridorAllPoint = new List<Transform>();
    List<Transform> rightPoints = new List<Transform>();
    List<Transform> leftPoints = new List<Transform>();

    public List<GameObject> listOfCorridorFloor = new List<GameObject>();

    public Vector3[] corridorVertices;

    public int[] corridorTrangle;

    public float StartEndDistanceFromCenter = 15;
    public float minStartEndDistanceFromCenter = 10;
    public float maxStartEndDistanceFromCenter = 20;

    public int controlDirection = 1;
    public float minControlDistanceFromCenter = 10;
    public float maxControlDistanceFromCenter = 30;

    public int numberOfLinePoint = 15;
    public int numberOfMesh;

    public Vector3[] testVec = new Vector3[3];
    int[] textInt = new int[3];

    private void Start()
    {
        BasiceSetup();

        PointsSetups();

        MakeMeshData();

    }
    private void BasiceSetup()
    {
        numberOfMesh = (numberOfLinePoint - 1);

        GameObject pointHolderObject = new GameObject();
        GameObject centerPointObject = new GameObject();
        GameObject startPointObject = new GameObject();
        GameObject endPostionObject = new GameObject();

        centerPoint = centerPointObject.transform;
        startPoint = startPointObject.transform;
        endPoint = endPostionObject.transform;

        pointHolderObject.name = "Point Holder";
        centerPointObject.name = "Center Point";
        startPointObject.name = "Start Point";
        endPostionObject.name = "End Point";

        pointHolderObject.transform.parent = transform;
        centerPointObject.transform.parent = pointHolderObject.transform;
        startPointObject.transform.parent = pointHolderObject.transform;
        endPostionObject.transform.parent = pointHolderObject.transform;

        pointHolderObject.transform.localPosition = Vector3.zero;
        pointHolderObject.transform.localRotation = Quaternion.Euler(Vector3.zero);
        centerPointObject.transform.localPosition = Vector3.zero;
        centerPointObject.transform.localRotation = Quaternion.Euler(Vector3.zero);

        startPointObject.transform.localPosition = Vector3.zero;
        startPointObject.transform.localRotation = Quaternion.Euler(new Vector3(0, 180, 0));
        endPostionObject.transform.localPosition = Vector3.zero;
        endPostionObject.transform.localRotation = Quaternion.Euler(Vector3.zero);

        Vector3 newStartExitPostion = Vector3.forward * (Random.Range(minStartEndDistanceFromCenter, maxStartEndDistanceFromCenter));

        startPointObject.transform.localPosition = -1 * newStartExitPostion;
        endPostionObject.transform.localPosition = newStartExitPostion;

        NPG01_ModulePoint centerPointScript = centerPointObject.AddComponent<NPG01_ModulePoint>();
        NPG01_ModulePoint startPointScript = startPointObject.AddComponent<NPG01_ModulePoint>();
        NPG01_ModulePoint endPointScript = endPostionObject.AddComponent<NPG01_ModulePoint>();

        centerPointScript.updatePoint(NPG01_ModulePoint.POINTSTATE.CENTER);
        startPointScript.updatePoint(NPG01_ModulePoint.POINTSTATE.CONNECTION);
        endPointScript.updatePoint(NPG01_ModulePoint.POINTSTATE.CONNECTION);
    }

    private void PointsSetups()
    {
        GameObject curveHolder = new GameObject();
        curveHolder.transform.parent = transform;
        curveHolder.name = "Curve Holder";
        curveHolder.transform.localPosition = Vector3.zero;
        curveHolder.transform.localRotation = Quaternion.Euler(Vector3.zero);

        switch (corridorType)
        {
            case CORRIDORTYPE.LinearBezierCurves:

            for (int i = 0; i < numberOfLinePoint; i++)
            {
                GameObject point = new GameObject();
                point.name = "Curve Point " + i.ToString();
                point.transform.parent = curveHolder.transform;
                point.transform.localPosition = Vector3.zero;
                point.transform.localRotation = Quaternion.Euler(Vector3.zero);
                NPG01_ModulePoint pointScript = point.AddComponent<NPG01_ModulePoint>();
                pointScript.updatePoint(NPG01_ModulePoint.POINTSTATE.BEZIERCURVES);

                centerLinePoints.Add(point.transform);
            }

            for (int i = 0; i < numberOfLinePoint; i++)
            {
                float t = (float)i / ((float)numberOfLinePoint - 1);

                centerLinePoints[i].localPosition = LinearBezierCurves(startPoint.localPosition, endPoint.localPosition, t);

                GameObject rightPoint = new GameObject();
                GameObject leftPoint = new GameObject();

                rightPoint.transform.parent = curveHolder.transform;
                rightPoint.name = "Right " + i;
                rightPoint.transform.localRotation = Quaternion.Euler(Vector3.zero);
                rightPoint.transform.localPosition = centerLinePoints[i].localPosition + (Vector3.right * 3);
                NPG01_ModulePoint rightPointScript = rightPoint.AddComponent<NPG01_ModulePoint>();
                rightPointScript.updatePoint(NPG01_ModulePoint.POINTSTATE.BEZIERCURVES);

                leftPoint.transform.parent = curveHolder.transform;
                leftPoint.name = "Left " + i;
                leftPoint.transform.localRotation = Quaternion.Euler(Vector3.zero);
                leftPoint.transform.localPosition = centerLinePoints[i].localPosition + (-Vector3.right * 3);
                NPG01_ModulePoint leftPointScript = leftPoint.AddComponent<NPG01_ModulePoint>();
                leftPointScript.updatePoint(NPG01_ModulePoint.POINTSTATE.BEZIERCURVES);

                rightPoints.Add(rightPoint.transform);
                leftPoints.Add(leftPoint.transform);
            }

            for (int i = 0; i < numberOfLinePoint; i++)
            {
                corridorAllPoint.Add(centerLinePoints[i]);
                corridorAllPoint.Add(leftPoints[i]);
                corridorAllPoint.Add(rightPoints[i]);
            }

            break;
            case CORRIDORTYPE.QuadraticBezierCurves:

            int controlPointDirction = Random.Range(0, 9);
            if (controlPointDirction % 2 == 0)
            {
                controlDirection = 1;
            }
            else
            {
                controlDirection = -1;
            }

            GameObject controlPointObject = new GameObject();
            controlPointObject.name = "Control Point";
            controlPointObject.transform.parent = curveHolder.transform;

            controlPointObject.transform.localPosition = Vector3.right * (20 * controlDirection);
            controlPointObject.transform.localPosition = new Vector3(controlPointObject.transform.localPosition.x,
                                                                     controlPointObject.transform.localPosition.y,
                                                                     0);

            NPG01_ModulePoint controlPointScript = controlPointObject.AddComponent<NPG01_ModulePoint>();
            controlPointScript.updatePoint(NPG01_ModulePoint.POINTSTATE.BEZIERCONTROLE);
            for (int i = 0; i < numberOfLinePoint; i++)
            {
                GameObject point = new GameObject();
                point.name = "Curve Point " + i.ToString();
                point.transform.parent = curveHolder.transform;
                point.transform.position = Vector3.zero;
                point.transform.localPosition = Vector3.zero;
                point.transform.localRotation = Quaternion.Euler(Vector3.zero);
                centerLinePoints.Add(point.transform);
                NPG01_ModulePoint pointScript = point.AddComponent<NPG01_ModulePoint>();
                pointScript.updatePoint(NPG01_ModulePoint.POINTSTATE.BEZIERCURVES);
            }

            for (int i = 0; i < numberOfLinePoint; i++)
            {
                float t = (float)i / ((float)numberOfLinePoint - 1);

                centerLinePoints[i].localPosition = QuadraticBezierCurves(startPoint.localPosition, endPoint.localPosition, controlPointObject.transform.localPosition, t);

                GameObject rightPoint = new GameObject();
                GameObject leftPoint = new GameObject();

                rightPoint.transform.parent = curveHolder.transform;
                rightPoint.name = "Right " + i;
                rightPoint.transform.localPosition = centerLinePoints[i].localPosition + (Vector3.right * 3);
                NPG01_ModulePoint rightPointScript = rightPoint.AddComponent<NPG01_ModulePoint>();
                rightPointScript.updatePoint(NPG01_ModulePoint.POINTSTATE.BEZIERCURVES);

                leftPoint.transform.parent = curveHolder.transform;
                leftPoint.name = "Left " + i;
                leftPoint.transform.position = Vector3.zero;
                leftPoint.transform.localPosition = Vector3.zero;
                leftPoint.transform.localPosition = centerLinePoints[i].localPosition + (-Vector3.right * 3);
                NPG01_ModulePoint leftPointScript = leftPoint.AddComponent<NPG01_ModulePoint>();
                leftPointScript.updatePoint(NPG01_ModulePoint.POINTSTATE.BEZIERCURVES);
            }

            for (int i = 0; i < numberOfLinePoint; i++)
            {
                corridorAllPoint.Add(centerLinePoints[i]);
                corridorAllPoint.Add(leftPoints[i]);
                corridorAllPoint.Add(rightPoints[i]);
            }
            break;
            case CORRIDORTYPE.CubicBezierCurve:
            break;
        }
    }

    private void MakeMeshData()
    {
        //mr = GetComponent<MeshRenderer>();
        //mf = GetComponent<MeshFilter>();

        GameObject meshHolder = new GameObject();
        meshHolder.name = "Mesh Holder";
        meshHolder.transform.parent = transform;

        meshHolder.transform.localPosition = Vector3.zero;
        meshHolder.transform.localRotation = Quaternion.Euler(Vector3.zero);


        for (int i = 0; i < numberOfLinePoint - 1; i++)
        {
            GameObject leftFloorPanel = new GameObject();
            GameObject rightFloorPanel = new GameObject();

            leftFloorPanel.name = "Left Floor " + i.ToString();
            rightFloorPanel.name = "Right Floor " + i.ToString();

            leftFloorPanel.transform.parent = meshHolder.transform;
            leftFloorPanel.transform.position = Vector3.zero;
            leftFloorPanel.transform.localPosition = Vector3.zero;
            leftFloorPanel.transform.localRotation = Quaternion.Euler(Vector3.zero);

            Vector3 leftFloorPanelPostion = centerLinePoints[i].localPosition;
            leftFloorPanelPostion.x = (leftPoints[i].localPosition.x + centerLinePoints[i].localPosition.x) / 2;
            leftFloorPanelPostion.z = (centerLinePoints[i + 1].localPosition.z + centerLinePoints[i].localPosition.z) / 2;

            leftFloorPanel.transform.localPosition = leftFloorPanelPostion;

            rightFloorPanel.transform.parent = meshHolder.transform;
            rightFloorPanel.transform.localPosition = Vector3.zero;
            rightFloorPanel.transform.localRotation = Quaternion.Euler(Vector3.zero);

            Vector3 rightFloorPanelPostion = centerLinePoints[i].localPosition;
            rightFloorPanelPostion.x = (rightPoints[i].localPosition.x + centerLinePoints[i].localPosition.x) / 2;
            rightFloorPanelPostion.z = (centerLinePoints[i + 1].localPosition.z + centerLinePoints[i].localPosition.z) / 2;

            rightFloorPanel.transform.localPosition = rightFloorPanelPostion;

            listOfCorridorFloor.Add(leftFloorPanel);
            listOfCorridorFloor.Add(rightFloorPanel);

            // Debug.Log(leftFloorPanel.transform.position + "     " + leftFloorPanel.transform.localPosition);
        }

        corridorVertices = new Vector3[listOfCorridorFloor.Count * 3];
        corridorTrangle = new int[listOfCorridorFloor.Count * 3];

        //listOfCorridorFloor[0].transform.parent = null;
        //centerLinePoints[0].transform.parent = null;
        //leftPoints[0].transform.parent = null;
        //leftPoints[1].transform.parent = null;

        testVec[0] = centerLinePoints[0].transform.position;
        testVec[1] = leftPoints[0].transform.position;
        testVec[2] = leftPoints[1].transform.position;

        //testVec[3] = leftPoints[1].transform.position;
        //testVec[4] = centerLinePoints[1].position;
        //testVec[5] = centerLinePoints[0].position;

        textInt[0] = 0;
        textInt[1] = 1;
        textInt[2] = 2;

        //textInt[3] = 3;
        //textInt[4] = 4;
        //textInt[5] = 5;

        listOfCorridorFloor[0].AddComponent<MeshFilter>();
        listOfCorridorFloor[0].AddComponent<MeshRenderer>();
    }

    private void Update()
    {
        Mesh testmesh = listOfCorridorFloor[0].GetComponent<MeshFilter>().mesh;

        testVec[0] = centerLinePoints[0].transform.position;
        testVec[1] = leftPoints[0].transform.position;
        testVec[2] = leftPoints[1].transform.position;

        textInt[0] = 0;
        textInt[1] = 1;
        textInt[2] = 2;

        //Debug.Log("point local: " + centerLinePoints[0].transform.localPosition);
        //Debug.Log("point global : " + centerLinePoints[0].transform.position);
        //Debug.Log("vertice " + testVec[0]);

        testmesh.Clear();

        testmesh.vertices = testVec;
        testmesh.triangles = textInt;
    }

    Vector3 LinearBezierCurves(Vector3 _pointStart, Vector3 _pointEnd, float t)
    {//                                   P0               P1                                 

        //P(t) = P0 + t * (P1 – P0) = (1 - t) P0 + t * P1                    , 0 < t < 1


        Vector3 p = Vector3.zero;

        p = _pointStart + t * (_pointEnd - _pointStart);

        return p;
    }

    Vector3 QuadraticBezierCurves(Vector3 _pointStart, Vector3 _pointEnd, Vector3 _pointControl, float t)
    {   //                                   P0               P1                      P2

        // P(t) = (1-t)^2 * P0     + 2(1-t) t * P2       + t^2 * P1          , 0 < t < 1
        //          uu                 u2                  tt  

        Vector3 p = Vector3.zero;

        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;
        float u2 = u * 2;

        p = uu * _pointStart;
        p += u2 * t * _pointControl;
        p += tt * _pointEnd;

        return p;
    }

    Vector3 CubicBezierCurve(Vector3 _pointStart, Vector3 _pointEnd, Vector3 _pointControlOne, Vector3 _pointControlTwo, float t)
    {   //                              P0                 P1                   P2                         P3


        //P(t) = (1-t)^3 *  P0      + 3 (1-t)^2 * t * P2     +3(1-t) * t^2 * P3 +      t^3  * P1 ,              0 < t< 1
        //        uuu                     uu                     u

        Vector3 p = Vector3.zero;


        float u = 1 - t;
        float uu = u * u;
        float uuu = u * u * u;

        float tt = t * t;
        float ttt = t * t * t;

        return p;
    }

    private void MakeMeshData(Vector3 meshPointOne, Vector3 meshPointTwo, Vector3 meshPointThree, int index)
    {
        corridorVertices[index - 3] = meshPointOne;
        corridorVertices[index - 2] = meshPointTwo;
        corridorVertices[index - 1] = meshPointThree;

        corridorTrangle[index - 3] = index - 3;
        corridorTrangle[index - 2] = index - 2;
        corridorTrangle[index - 1] = index - 1;
    }

    //private void CreateMesh()
    //{
    //    roomMesh.Clear();

    //    roomMesh.vertices = roomVertices;
    //    roomMesh.triangles = roomTrangle;

    //}
}

Upvotes: 0

Views: 1010

Answers (1)

zambari
zambari

Reputation: 5035

The mesh is always expressed in relation to its root transform. In order to use global positions use Transform.TransformPoint (or transform.InverseTransformPoint) to convert them to local space, i.e. all points must be expressed relative to the center of the gameobejct that will be displaying the mesh.

Upvotes: 1

Related Questions