Exception if material parameter set on LinesMesh

Hi

Bad news first: I cannot replicate this issue :frowning: Whatever I do in the playground, I cannot replicate it. As you can see here https://playground.babylonjs.com/#MZ7QRG#2267 I investigated issues with transparency, animations, bones, and overlapping meshes.

But since there is a good chance there might be a real bug (typecast issue?) I hope this code-only post is alright.

So, when I call

linesUnique.forEach((line, i)=>{
     this.scene.MeshBuilder.CreateLines("WalkableAreaBorderSegment"+i, {points: [line.a, line.b], material: this.material})
});

with the material parameter set, I get:

Uncaught TypeError: Cannot create property '_needNormals' on string '#define NUM_BONE_INFLUENCERS 0\n#define GLOW'

I was able to trace it to class StandardMaterial.isReadForSubmesh at the call to MaterialHelper.PrepareDefinesForLights.

It appears that subMesh.materialDefines, that normally is an object of properties, gets stringified somehow. In StandardMaterial.isReadForSubmesh, it comes in already as string but should be of Type “StandardMaterialDefines” as declared at the top of standardMaterial.ts.

Console.logging “subMesh.materialDefines” indicates that it mostly is undefined and gets assigned a new instance of type StandardMaterialDefines. Except in case of the error described where it comes in as string.

The error does not occur if I leave out the material parameter. All lines render just fine.

The error occurs right at the first lines mesh (i==0). It occurs the first time I run my code.

When the error occurs you briefly see a couple of lines rendered, and then the screen goes black’ish / dark blue’ish.

Included below is my code triggering the exception.

FYI: latest Babylon (just downloaded from NPM), latest Chrome.

Please let me know if you need any more information.

Best wishes
Joe

Appendix

// never mind it's dirty and unoptimised; not sure if I keep that feature in

import {ReachableTiles} from "../sceneControllers/PlayerPositionController.js";

type Line = {a:Vector3, b:Vector3}

export default class WalkableArea {
    private scene;

    private meshes = [];
    private material;

    public constructor(scene) {
        this.scene = scene;
        this.material = new this.scene.StandardMaterial("WalkableAreaTileMaterial");
        this.material.diffuseColor = this.scene.Color3.Blue();
        //this.material.alpha = 0.3;
        //this.material.alphaMode = 1;        
    }

    public show(tiles : ReachableTiles, tileSize = 1) {
        const included : Vector3[] = [];
        const temp = this.scene.Vector3.Zero();

        tiles.forEach((short)=>{
            included.push(new this.scene.Vector3(short[1], short[2]+0.05, short[3]))
        });

		function comparePoint(p1, p2) {
			return p1.x === p2.x && p1.z === p2.z;
		}

		function compareLines(l1, l2) {
			return (comparePoint(l1.a, l2.a) && comparePoint(l1.b, l2.b)) ||
					(comparePoint(l1.b, l2.a) && comparePoint(l1.a, l2.b));
		}


		const linesAll : Line[] = [];
		const linesUnique : Line[] = [];

		const tileHalf = 0.5;

		for(let i=0; i<included.length; i++) {
			const x = included[i].x;
			const y = included[i].z;			
			const h = included[i].y;

			const north = {
				a: temp.clone().set(x-tileHalf, h, y-tileHalf),
				b: temp.clone().set(x+tileHalf, h, y-tileHalf)
			};

			const south = {
				a: temp.clone().set(x-tileHalf, h, y+tileHalf),
				b: temp.clone().set(x+tileHalf, h, y+tileHalf)
			};

			const east = {
				a: temp.clone().set(x+tileHalf, h, y-tileHalf),
				b: temp.clone().set(x+tileHalf, h, y+tileHalf)
			};

			const west = {
				a: temp.clone().set(x-tileHalf, h, y-tileHalf),
				b: temp.clone().set(x-tileHalf, h, y+tileHalf)				
			};

			linesAll.push(north, east, south, west);
		}

		for(let i=0; i<linesAll.length; i++) {
			const testLine = linesAll[i];

			const count = linesAll.filter((line)=>(compareLines(testLine, line)));

			if(count.length === 1) {
				linesUnique.push(linesAll[i]);
			}
		}

		console.log({linesUnique})
		linesUnique.forEach((line, i)=>{
			//@ts-expect-error //no pun intended
			if( !(line.a instanceof BABYLON.Vector3) ) {
				throw new Error(i+" line.a");
			}
			//@ts-expect-error
			if( !(line.b instanceof BABYLON.Vector3) ) {
				throw new Error(i+" line.b");
			}

			this.scene.MeshBuilder.CreateLines("WalkableAreaBorderSegment"+i, {points: [line.a, line.b], material: this.material, updatable: false})
		});
}
}

let’s ping @Evgeni_Popov or @sebavan

Lines needs a special shader as they for instance can not have normals.

You can not use a standard or pbr material with them. You could nevertheless attach your own shader material to them. We do that here in Babylonhttps://github.com/sebavan/Babylon.js/blob/master/packages/dev/core/src/Meshes/linesMesh.ts#L115

1 Like

Ok thanks @sebavan

But I am confused now. Both the source at linesMesh.ts (no check for instanceof ShaderMaterial or so) and the working example provided above (https://playground.babylonjs.com/#MZ7QRG#2267) seem to suggest that providing a StandardMaterial should be alright.

Or is it more like something along the lines that I just got lucky that it worked in the playground?

Not sure about doing my own shader thing. My use case of the linesMesh is just for some minor visuals. I probably will resort to sticking with the colors parameter of the lines mesh or try the more expensive tubeMesh.

Interesting, are you on our latest version ?

It looks like the same error as this thread using the highlight layer. I can’t repro either thou…

You could also try using the background material to color the lines for another option… :slight_smile:

Yes, I think I do: “babylonjs”: “^5.28.0”.

Oh, interesting!

I just tried that except in my case it is the GlowLayer! So:

a) GlowLayer on + material on linesMesh set: crash
a) GlowLayer off + material on linesMesh set: no crash but also no color. It is just black.

@sebavan @Blake

Ok, got it. This should crash now: https://playground.babylonjs.com/#MZ7QRG#2271

1 Like

Thanks for the repro!

This PR will fix the problem:

Note that even with the fix you will see some flickering and/or different colors for the shading of the lines: that’s because the standard material is applying lighting. You probably want to use the emissive color for the line color and disable lighting, as in:

Oh sweet thanks a bunch :smiley:

@sebavan I marked Evgeni_Popov fix as solution now. Hope this is alright.