kestrelm/Creature_WebGL

BabylonJS rendering issue

kefniark opened this issue · 9 comments

Description

Hello there,

I'm using the babylon.js runtime since few days and I've encountered 2 issues, and I was able to reproduce them with the sample provided on the website.

First one, texture overlapping:

screen shot 2018-09-05 at 11 41 56 am

As we can see, the blue flame is sometime visible through the body. After few research, I realized it was caused by a setting on the camera
camera.minZ = 0.0001;

I managed to workaround this issue by not using this property.

Second one, visibility issue:

With the default sample, its possible to move the camera around the creature without any problem.
So I decided to use the same to move the creature around my 3d environment

new_creature_renderer.renderMesh.position = new Vector3(11, 0.5, -11);
new_creature_renderer.renderMesh.scaling = new Vector3(0.05, 0.05, 0.05);

But with this, the creature start to blink or disappear based on the camera position (kinda looks like some culling)
Demo, the creature blink after the camera was moved

Is there any other way to move the creature in the scene? or a setting to solve this?

Hello, this does not seem like a Creature runtime issue. It feels like a BabylonJS rendering issue, you might want to check their docs to see if you can increase the culling distance. This is typical of all 3D engines, there should be an option on their end to change the culling distance ( so objects far away do not get culled)

A quick google search brings up some info like this for example:
http://www.html5gamedevs.com/topic/8359-camera-clipping-planes/

Thanks

The problem is that I cant reproduce this issue with anything else (custom mesh, planes, ...).
This seem to happen only with the creature2d mesh.

I will also open an issue on the babylon repository but I dont really see what they can do on their side if it's not reproducible with anything else.

For information, here is the code (mostly the default sample):

import { Engine, Scene, ArcRotateCamera, HemisphericLight, Vector3, Mesh, Texture, AssetsManager, StandardMaterial, Material, Color3, Light, IShadowLight, Color4, FreeCamera, MeshBuilder, CubeTexture, UniversalCamera } from "babylonjs";

var canvas: any = document.getElementById("renderCanvas");
if (!canvas) throw new Error("no canvas to init");

var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', 'iceDemonExport_character_data.json', true); // Replace 'my_data' with the path to your file
xobj.onreadystatechange = function () {
	if (xobj.readyState == 4 && xobj.status === 200) {
		var response = xobj.responseText;
		// Parse JSON string into object
		var actual_JSON = JSON.parse(response);

		var new_creature = new Creature(actual_JSON, false);
		var new_animation_1 = new CreatureAnimation(actual_JSON, "default", false);

		var new_manager = new CreatureManager(new_creature);
		new_manager.AddAnimation(new_animation_1);
		new_manager.SetActiveAnimationName("default", false);
		new_manager.SetShouldLoop(true);
		new_manager.SetIsPlaying(true);
		new_manager.RunAtTime(0);

		// Load the BABYLON 3D engine
		var engine = new Engine(canvas, true);

		// Now, call the createScene function that you just finished creating
		var data = createScene(canvas, engine);

		// Create creature renderer
		var new_creature_renderer = new CreatureBabylonRenderer("CreatureRenderer", data.scene, new_manager, data.creature_texture);
		new_creature_renderer.UpdateData();

		// Change position
		new_creature_renderer.renderMesh.position = new Vector3(11, 0.5, -11);

		// Register a render loop to repeatedly render the scene
		engine.runRenderLoop(function () {
			new_manager.Update(0.05);
			new_creature_renderer.UpdateData();

			data.scene.render();
		});
	}
};
xobj.send(null);


// This begins the creation of a function that we will 'call' just after it's built
var createScene = function (canvas, engine) {
	// Now create a basic Babylon Scene object 
	var scene = new Scene(engine);

	// This creates and positions a free camera
	var camera = new UniversalCamera("UniversalCamera", new Vector3(0, 0.5, -15), scene);

	// This targets the camera to scene origin
	camera.setTarget(new Vector3(11, 0.5, -11));

	// This attaches the camera to the canvas
	camera.attachControl(canvas, false);

	// This creates a light, aiming 0,1,0 - to the sky.
	var light = new HemisphericLight("light1", new Vector3(0, 1, 0), scene);
	light.intensity = 0.8;

	// creature
	var creature_texture = new StandardMaterial("creatureTexture", scene);
	creature_texture.diffuseTexture = new Texture("iceDemonExport_character_img.png", scene);
	creature_texture.diffuseTexture.hasAlpha = true;
	creature_texture.emissiveTexture = new Texture("iceDemonExport_character_img.png", scene);
	creature_texture.backFaceCulling = false;

	var plane = MeshBuilder.CreatePlane("test", { size: 10 }, scene);
	plane.position.set(10, 0.5, -10);
	plane.material = creature_texture;

	// Leave this function
	return { "scene": scene, "creature_texture": creature_texture };
};

P.S. and no .maxZ does not change anything, I dont think culling would make the mesh to blink like this.

The Creature Babylon renderer actually just uses the standard BabylonJS Mesh object, really nothing fancy going on there:
https://github.com/kestrelm/Creature_WebGL/blob/master/CreatureBabylonRenderer.js

It does not do anything special or unique with it, just calls regular BabylonJS functions. Not sure if this helps:
http://www.html5gamedevs.com/topic/18357-always-visible-mesh/

Anyway as I said, it is a standard BabylonJS Mesh object, there is no custom code there.

Ho good catch,
forcing the mesh as always visible make this issue disappear.
So it's probably something to do with the bounding box or the frustum 🤔

So not sure if the bounding box of the mesh of the Creature character needs to be updated per frame update?
It is slightly expensive though ( depending on the number of vertices of the character). There is also another thread discussing this issue, might be worth to take a look too:
http://www.html5gamedevs.com/topic/15255-is-it-possible-to-set-the-size-of-the-bounding-box/

screen shot 2018-09-05 at 3 31 42 pm

Yes the bounding box doesn't seem to be affected by the mesh position and seem to stay at 0, 0, 0

I wonder if it has anything to do with having to refresh the bounding box:
http://www.html5gamedevs.com/topic/30842-solvedhow-to-get-boundingbox-info-of-a-parent-mesh-with-all-children-size/

I am guessing the bounding box needs to follow the character based off the points and the character transform...

yes I was testing exactly the same thing ^^
I found a way to solve the issue without using mesh.alwaysSelectAsActiveMesh = true

new_creature_renderer.UpdateData();
new_creature_renderer.renderMesh.refreshBoundingInfo();

Not sure about the performance cost of this method but it fix the bounding box position and solve the blinking issue 👍

screen shot 2018-09-05 at 3 45 20 pm

Awesome! Nice job, but take note there is some penalty cost involved in calculating the bbox per update. In any case, that is the correct thing to do if you are going to be shifting the camera around. But I think alwaysSelectAsActiveMesh = true might be cheaper in your case if you don't mind always rendering that character vs recomputing the bounding box. I will close this issue since this is a BabylonJS option.

Cheers