Line2D texture should be continuous


Why is this texture symmetrical rather than continuous?

Hi @hisoka.xiang and welcome to the community.

Because the standardUV option has been set to false.

See Draw a Line With a Set Width | Babylon.js Documentation

thanks!

Hi, JohnK
I’m using this picture as a texture,
image
But I got final texture like this :


Below is my code , I think I must be doing something wrong
function createLines(scene: Scene, camera: ArcRotateCamera) {

  var line2D = function (name: string, options: any, scene: Scene) {

    //Arrays for vertex positions and indices

    var positions = [];

    var indices = [];

    var normals: any[] = [];

    var width = options.width || 1;

    var path = options.path;

    var closed = options.closed || false;

    if (options.standardUV === undefined) {

      standardUV = true;

    } else {

      standardUV = options.standardUV;

    }

    var interiorIndex;

    //Arrays to hold wall corner data

    var innerBaseCorners = [];

    var outerBaseCorners = [];

    var outerData = [];

    var innerData = [];

    var angle = 0;

    var nbPoints = path.length;

    var line = Vector3.Zero();

    var nextLine = Vector3.Zero();

    path[1].subtractToRef(path[0], line);

    var direction, lineNormal;

    if (nbPoints > 2 && closed) {

      path[2].subtractToRef(path[1], nextLine);

      for (var p = 0; p < nbPoints; p++) {

        angle =

          Math.PI -

          Math.acos(

            Vector3.Dot(line, nextLine) /

              (line.length() * nextLine.length())

          );

        direction = Vector3.Cross(line, nextLine).normalize().y;

        lineNormal = new Vector3(-line.z, 0, 1 * line.x).normalize();

        line.normalize();

        innerData[(p + 1) % nbPoints] = path[(p + 1) % nbPoints];

        outerData[(p + 1) % nbPoints] = path[(p + 1) % nbPoints]

          .add(lineNormal.scale(width))

          .add(line.scale((direction * width) / Math.tan(angle / 2)));

        line = nextLine.clone();

        path[(p + 3) % nbPoints].subtractToRef(

          path[(p + 2) % nbPoints],

          nextLine

        );

      }

    } else {

      lineNormal = new Vector3(-line.z, 0, 1 * line.x).normalize();

      line.normalize();

      innerData[0] = path[0];

      outerData[0] = path[0].add(lineNormal.scale(width));

      for (var p = 0; p < nbPoints - 2; p++) {

        path[p + 2].subtractToRef(path[p + 1], nextLine);

        angle =

          Math.PI -

          Math.acos(

            Vector3.Dot(line, nextLine) /

              (line.length() * nextLine.length())

          );

        direction = Vector3.Cross(line, nextLine).normalize().y;

        lineNormal = new Vector3(-line.z, 0, 1 * line.x).normalize();

        line.normalize();

        innerData[p + 1] = path[p + 1];

        outerData[p + 1] = path[p + 1]

          .add(lineNormal.scale(width))

          .add(line.scale((direction * width) / Math.tan(angle / 2)));

        line = nextLine.clone();

      }

      if (nbPoints > 2) {

        path[nbPoints - 1].subtractToRef(path[nbPoints - 2], line);

        lineNormal = new Vector3(-line.z, 0, 1 * line.x).normalize();

        line.normalize();

        innerData[nbPoints - 1] = path[nbPoints - 1];

        outerData[nbPoints - 1] = path[nbPoints - 1].add(

          lineNormal.scale(width)

        );

      } else {

        innerData[1] = path[1];

        outerData[1] = path[1].add(lineNormal.scale(width));

      }

    }

    var maxX = Number.MIN_VALUE;

    var minX = Number.MAX_VALUE;

    var maxZ = Number.MIN_VALUE;

    var minZ = Number.MAX_VALUE;

    for (var p = 0; p < nbPoints; p++) {

      positions.push(innerData[p].x, innerData[p].y, innerData[p].z);

      maxX = Math.max(innerData[p].x, maxX);

      minX = Math.min(innerData[p].x, minX);

      maxZ = Math.max(innerData[p].z, maxZ);

      minZ = Math.min(innerData[p].z, minZ);

    }

    for (var p = 0; p < nbPoints; p++) {

      positions.push(outerData[p].x, outerData[p].y, outerData[p].z);

      maxX = Math.max(innerData[p].x, maxX);

      minX = Math.min(innerData[p].x, minX);

      maxZ = Math.max(innerData[p].z, maxZ);

      minZ = Math.min(innerData[p].z, minZ);

    }

    for (var i = 0; i < nbPoints - 1; i++) {

      indices.push(i, i + 1, nbPoints + i + 1);

      indices.push(i, nbPoints + i + 1, nbPoints + i);

    }

    if (nbPoints > 2 && closed) {

      indices.push(nbPoints - 1, 0, nbPoints);

      indices.push(nbPoints - 1, nbPoints, 2 * nbPoints - 1);

    }

    var normals = [];

    var uvs = [];

    var standardUV;

    if (standardUV) {

      for (var p = 0; p < positions.length; p += 3) {

        uvs.push(

          (positions[p] - minX) / (maxX - minX),

          (positions[p + 2] - minZ) / (maxZ - minZ)

        );

      }

    } else {

      var flip = 0;

      var p1 = 0;

      var p2 = 0;

      var p3 = 0;

      var v0 = innerData[0];

      var v1 = innerData[1].subtract(v0);

      var v2 = outerData[0].subtract(v0);

      var v3 = outerData[1].subtract(v0);

      var axis = v1.clone();

      axis.normalize();

      p1 = Vector3.Dot(axis, v1);

      p2 = Vector3.Dot(axis, v2);

      p3 = Vector3.Dot(axis, v3);

      var minX = Math.min(0, p1, p2, p3);

      var maxX = Math.max(0, p1, p2, p3);

      uvs[2 * indices[0]] = -minX / (maxX - minX);

      uvs[2 * indices[0] + 1] = 1;

      uvs[2 * indices[5]] = (p2 - minX) / (maxX - minX);

      uvs[2 * indices[5] + 1] = 0;

      uvs[2 * indices[1]] = (p1 - minX) / (maxX - minX);

      uvs[2 * indices[1] + 1] = 1;

      uvs[2 * indices[4]] = (p3 - minX) / (maxX - minX);

      uvs[2 * indices[4] + 1] = 0;

      for (var i = 6; i < indices.length; i += 6) {

        flip = (flip + 1) % 2;

        v0 = innerData[0];

        v1 = innerData[1].subtract(v0);

        v2 = outerData[0].subtract(v0);

        v3 = outerData[1].subtract(v0);

        axis = v1.clone();

        axis.normalize();

        p1 = Vector3.Dot(axis, v1);

        p2 = Vector3.Dot(axis, v2);

        p3 = Vector3.Dot(axis, v3);

        var minX = Math.min(0, p1, p2, p3);

        var maxX = Math.max(0, p1, p2, p3);

        uvs[2 * indices[i + 1]] =

          flip + (Math.cos(flip * Math.PI) * (p1 - minX)) / (maxX - minX);

        uvs[2 * indices[i + 1] + 1] = 1;

        uvs[2 * indices[i + 4]] =

          flip + (Math.cos(flip * Math.PI) * (p3 - minX)) / (maxX - minX);

        uvs[2 * indices[i + 4] + 1] = 0;

      }

    }

    VertexData.ComputeNormals(positions, indices, normals);

    VertexData._ComputeSides(

      Mesh.DOUBLESIDE,

      positions,

      indices,

      normals,

      uvs

    );

    console.log(uvs);

    //Create a custom mesh

    var customMesh = new Mesh("custom", scene);

    //Create a vertexData object

    var vertexData = new VertexData();

    //Assign positions and indices to vertexData

    vertexData.positions = positions;

    vertexData.indices = indices;

    vertexData.normals = normals;

    vertexData.uvs = uvs;

    //Apply vertexData to custom mesh

    vertexData.applyToMesh(customMesh);

    return customMesh;

  };

  var path = [

    new Vector3(-20, 0, 0),

    new Vector3(-10, 0, 10),

    new Vector3(0, 0, 0),

    new Vector3(10, 0, 10),

    new Vector3(20, 0, 0),

    new Vector3(10, 0, -10),

  ];

  var line = line2D(

    "line",

    { path: path, width: 0.6, standardUV: true },

    scene

  );

  line.material = new StandardMaterial("", scene);

  const mat = new StandardMaterial("line-uv", scene);

  line.material = mat;

  const tt = new Texture("./textures/right.png", scene);

  mat.diffuseTexture = tt;

  tt.hasAlpha = true;

  tt.uScale = 20;

  tt.vScale = 1;

  //tt.uAng = -Math.PI/2;

  //tt.uAng = -Math.PI/2;

  line.position.y = 5;

  //line.rotation.x = -Math.PI / 2;

  // scene.beforeRender = function () {

  //   // txtTiles[0].material.diffuseTexture.wAng = -camera.alpha - Math.PI/2;

  //   tt.wAng = -camera.alpha - Math.PI / 2;

  // };

}

Hi, Everybody,
Who can help me!

You can see in this playground that the texture is set up to go across the mesh not to follow the line direction.

Got it, You mean I have to adjust myself according to the line direction?

Alterations to the code for positions, indices and uvs all need changing to do what you wish. I am having a look to see what I can do. Please feel free to have a go yourself.

Okey, Thanks a lot!
Can you give me a copy when you change the code? I’m not very good at math. :kissing_heart:

Will not be able to finish until tomorrow, but will post solution here.

I’m ok~ Thank you very much!

This version of Line2D is closer to what you need I believe.

Thank you very much. But when I look down from above, it’s like this
image
I hope it always faces me like this
image

Like this?

or this?

If these do not solve your issue we will need a simplified working playground showing the problem/

Hi, JohnK,
Thank you very much!
I found a duplicate in the document

Line in XoZ Plane Formed from Central Path

I wonder if the document has been written twice?

Not a duplicate - one draws the line in the horizontal plane XoZ and the other in the vertical plane XoY saves messing around with rotations.
The example I did for you with the textures following the line is only written for a Line2D in the vertical XoY plane, hence the need to rotate it if you want it in the horizontal plane XoZ

The following is what I generated with threejs,it’s right.

But now I generated as your code like this, It looks strange

We already have this example in XoY, Draw a Line With a Set Width | Babylon.js Documentation,
so where is this example in XoZ ? I can’t find it.

Originally in the documentation there were three Line2D examples none of which were duplicates.

Line in XoY Plane Formed from Central Path
Line in XoZ Plane Formed from Central Path
Line in XoZ Plane Formed from Inner Path

None of these treated the texture in the way you needed.

Following your request for the texture to follow the line directions I created a function for you and then I added it to the documentation.

Texture Follows Line in XoY Plane Formed from Central Path.

Based on the information you gave I chose to write the code for the XoY plane. I have not written nor am I going to write another example for Texture follows line in XoZ plane. As I said if you want it in the XoZ plane rotate it. If the example I provided is not sufficient for your needs there should now be enough information, using the examples on the Line2D documentation page, for you to write your own.

Also your three example shows a smooth curve not lines with sharp angles, things do improve somewhat with a smooth curve.

2 Likes

I really appreciate that you have been taking the time to help me solve my problems and pay the highest tribute to you :smiling_face: :smiling_face:

2 Likes