Recommended Posts

Hi again.

I am still figthing with scene optimization. My problem is that the scene I want to manage is very complex.

I have used many BABAYLON optimization features.

- Disabled from scene all non needed things: Physics, animations, fog, lensflares, paritcles, postprocesses, textures,probes, renderTargets, shadows, skeletons, sprites

- null mesh AUTOLOD based on bounding box size of each meshes included in the GLTFS I import in the scene and computing the distance

- Instances for using HW accelerated

- SceneOptimizerOptions

- freeWorldMatrix

 

All my meshes are opaque, no transparency. I wonder if would it be possible to apply a sortObjects like it is available in Threejs like a occussion culling

Best regards

 

Share this post


Link to post
Share on other sites

Do you think this will help? Where are you losing performance? On the CPU side? (you can check it with the profiler: Which function is the more expensive?)

If the fillrate is the issue then occlusion won't help but you can think about sorting your meshes from front to back to leverage the depth buffer

Share this post


Link to post
Share on other sites

Hi.

 

Not sure at all, but I guess by reading your answer that maybe makes not sense.

 

What about serializing the scene?

I have been reading that is also posible to stream the scene, do you have any example about how to do it?

 

Many thanks

Share this post


Link to post
Share on other sites

Hi.

Sorry for my lack of explanations about why I am wondering to use serialize.

 

My point is that I want to use the mesh.simplify feature but the problem is that the simplifications have to be computed each time the user loads the scene.

Is there any other way to save these mesh simplifications?

If not, could you describe how to serialize a complex scene (many GLTFS imported with all the optimizations I described in my previous mail) to a JSON file?

Many thanks in advanced

Share this post


Link to post
Share on other sites

Hi again.

Sorry for insisting in this topic but I think occlusion culling is one of the main lacks of this wonderful product.

I am thinking in a solution based on launching a matrix of rays.

The idea is to split the canvas in a matrix of rays for instance of (160 x 120 )

The point is that for me, every mesh smaller than the cell set in the matrix is so small that it doesn't need to be rendered.

The idea is to take on the first mesh selected by each ray.

Of course if the camera is no moving no need to do anything.

I can have the list of meshes in frustrum stored in an array and hide all meshes not picked by the ray matrix.

My main problem is that I don't know if in terms of performance this will be possible or not.

What do you think about?

 

Share this post


Link to post
Share on other sites

Hi.

Here the implementation of my idea using a matrix of ray-cast dividing the screen in cells (in my example 10 x 10).

http://www.babylonjs-playground.com/#FZJRWJ#83

In order to trigger the occlusion culling just do a double click with left mouse button and you will see.

My main problem is the time spend by scene.pick and number of cells in canvas.

In this example I am using  a matrix 10 x 10 of rays, the time spent is about 0.5 secs, but if I increase thi number (line 81), the the time increases dramtically.

For a matrix of 100 x 100 (c=100)  takes nearly 40 secs. It is inviable. My idea was to launch a 500x500 matrix.

It is really a pity that this function could not be executed by GPU.

We have the mechanism to implement famous occlusion culling but it is really too slow to be practicable.

Best regards

Share this post


Link to post
Share on other sites

Hi again.

Is there any difference in performance if I use raycast class instead of scene.pick method?

Is raycast processed by GPU or by CPU?

If I am correct, the scene.pick method is processed by CPU.

If it was possible to execute the same method by GPU by any trick it would be wonderfull.

 

Best regards

 

Share this post


Link to post
Share on other sites

Listen to Adam!

You can't speed up a scene unless you know where the bottleneck is. If your scene just has too many vertices, then culling objects might help, but if the problem is on the CPU side (and it usually is), adding more CPU work before rendering won't to help. Things also depend on  mobile vs desktop, etc.

If you have a lot of meshes, frustrum culling may be a huge issue - it certainly was for me. Using octrees and merging meshes (with SPS and with submeshes/multimaterials) helped this enormously. But it could be problems with materials, or something else - you have to know what's slow.

Share this post


Link to post
Share on other sites

I confirm : before making probably useless attempts in every directions, just find where the time is consumed in your scene.

Some leads :

- freeze the world matrix of all meshes that won't move, rotation nor scale

- set to alwaysActive all the meshes that you sure they always will be in the frustum (no culling computation for them)

- you could also add your own pre-culling depending on your scene and your logic (example : if a mesh reaches some position where you know it's not visible anymore, deactivate it to sort it out the culling process)

- group, merge everything possible with instances, sps, multimaterial or per mesh UVs, etc to reduce the draw call numbers, use octree else

etc

But the point is to find first WHAT and WHERE to optimize.

Share this post


Link to post
Share on other sites

Hi.

I am already using all these techniques.

- LOD based on distance

- HW instances in combination with LOD (4 levels + null)

- Octrees

- Freeze the world matrix of all meshes

- I have also disabled from scene Collisions, Textures, Physics Engine, Animations, LensFlared, Fog, Particles, Skeletons, Sprites, RenderTarget, PostProcesses and probes

I have also disabled camera collisions.

- I have also tried with scene optimization techniques, but no positive feedback at all.

About setting to alwaysActive all the meshes that you sure they always will be in the frustum, it is not an option for me. The camera can move at any direction.

My solution is based on first load the different parts in scene (with LODS) and when all them are loaded then I start to build the scene by instantiating them.

Please, don't tell me that I am going in all directions, I have tried everything and Occlusion Culling is the only solution I see. In fact if this is not posible then my only option is to replace the scene by its bounding box, twhen changing camera position and then when camera will be aging static make the scene visible again.

Here you can see the numbers from stats provided by Debug Layer in one of my scenes:

Total Meshes: 80289

Draw Calls: 1737

Total Lights: 1

Total Vertices: 77477904

Total Materials:4817

Total Textures: 0

Active Meshes: 21998

Active Indices: 1732170

As you can see the scene is very complex, and this is the reason why I am thinking in performing a kind of occlusion culling technique. I am making an intensive usage of instancing to reduce the number of drawcalls.

I don't need any tool to see where the problem is, (numbers of drawcalls and vertices) As you can guess, if you try to rotate the camera you will see that this is un-handleable by BABYLONJS.

I would really appreciate if you could answer to my question and tell me if it is possible to use GPU to mesh picking in anyway. I continue thinking that my idea is good but not achievable due that this method is computed by CPU and not by GPU.

Many thanks in advanced.

Best regards

Share this post


Link to post
Share on other sites

Are you sure there is no way of avoiding Raycasting ?

Could some algorithm like

  • Each frame
  • Pick N meshes
  • Compute their size on screen (squared distance from Camera could be enough if they have the same size)
  • IF small enough (far enough if you computed squared distance) : Hide
  • ELSE : Show

Do the job ? For this kind of case (many meshes), I've seen it working pretty well...

Share this post


Link to post
Share on other sites
1 hour ago, ua4192 said:

I am already using all these techniques [LOD/instances/octrees]   ... I don't need any tool to see where the problem is

This is a kind of dangerous way to do things. All those techniques can slow down a scene as well as speed it up; if you're not profiling often it's hard to know if they're helping.

1 hour ago, ua4192 said:

I would really appreciate if you could answer to my question and tell me if it is possible to use GPU to mesh picking in anyway. I continue thinking that my idea is good but not achievable due that this method is computed by CPU and not by GPU.

I don't think there's any general thing that can be done automatically for occlusion culling - if there was every engine would do it already. There are apparently GPU culling techniques (I'm not familiar with them), but they need to be designed around the content.

So I think your best bet for culling is what Jerome said - it will help if it can be done manually based on unchanging things in your scene. For example if there's a building in the middle of the scene, and you can know that when the player is on one side of it then things on the other side are occluded, etc. Or more generally, you could take some kind of approach of choosing the most complex geometries in the scene and pre-caclucating some data structure of where they're visible from.

But any kind of general occlusion testing that's done per-frame is going to cost more than it saves.

Share this post


Link to post
Share on other sites

Follow up - in looking at the sorting feature Three does, I don't thing BJS does this but I've no idea if it would help. You could try it easily enough - AFAIK if you manually sort the "scene.meshes" list by distance every N frames it ought to have the same effect.

Share this post


Link to post
Share on other sites

Hi.

It seems that there is some kind of technique to pick meshes by using GPU is possible:

http://www.html5gamedevs.com/topic/22471-gpu-picking-system/

My problem is I am totally new with GPU system and to be frank I don't catch the code.

In fact the solution I did was using the method scene.pick in order to apply my own occlussion culling function. Of course the time spent by this function depends directly on the amount of rays launched in each iteration.

10*10 --> 0.3 secs

25 * 25 --> 3.5 secs

50 * 50 --> 30 secs

100*100 --> 90 secs

 

I will continue investigating.

 

Many many thanks for your support.

Share this post


Link to post
Share on other sites
Quote

 

Total Meshes: 80289

Draw Calls: 1737

Total Vertices: 77477904

Total Materials:4817

Active Meshes: 21998

 

Ouch !

Imho, you should reduce every number from this list for several reasons :

- 22K meshes in the frustum is more than the human eyes can distinguish on the screen. Imagine that you could manage only 8-12K instances (what is already huge), recycle them to display all of them as if they were 22K instead (say, you paste a texture in the background with just images of your distant meshes far away or any other trick). Handling 10K of things compared to 22K makes a real difference for the CPU.

- Actually, your scene has 80K meshes !!! Well... JS is monothreaded, you know, and you will probably have to iterate 80K times to process the logic of all your meshes. Even for the latest V8 engine, with the latest CPU model, this is a long computation compared to the small delay of 16ms between two frames if you want to keep 60 fps. As an example, just try to compute 80K times the multiplication of two 4x4 float matrices, then with a vector4, then normalize the result (something what is done dozen of times for any little 3D maths operation inside the engine) and check the elapsed time. No logic, no rendering, just a standard 3D calculation. You might be surprised ;-)

Remember that the iterations of your logic are followed by the same iterations by the engine to compute the culling, then the world matrices and the rendering ... much work for the CPU.

So here again, I would suggest that you manage far less meshes. 

Maybe could you manage 80K logical representations or data structures and only the really lowest number of meshes. As they can't be seen all at once, neither distinguished, you probably don't need to instanciate such a high number of things that will then be injected and processed by the whole 3D workflow.

- Same advice for the number of materials, especially if you don't use any texture !

- At last, try also to reduce the total number of draw calls : well, this would automatically decrease with less managed meshes, less visible meshes and less materials.

So, before trying to investigate the GPU occlusion, if I were you, I would rather rethink the global approach and decouple the logic (maybe you need 80K occurrences of something anyway) from what would really have to be currently depicted by meshes (3D representation of the logic, what is to be passed to the engine) and then how to reduce/optimize/fake the final render of this representation (the meshes in the frustum at the lower cost).

 

 

Share this post


Link to post
Share on other sites

Hi.

I am afraid I am not able to apply these techniques.

I will try to explain briefly.

My framework is a CAD visualization system.

The ASSETS are extracted from  an Oracle DB, basically for each record in the DB I have the  following information:

- Filename

- Row_ID

- Transformation matrix (position and rotation)

I have no idea about occlusion culling logic of my CAD data. The goal is to be able to see the scene moving the camera in any direction, so this is the reason I am thinking in this approach to limit the number of meshes in the frustrum. The reason you see so many active meshes is that 80% of them are occluded by other meshes. Think in a plane fuselage and parts inside..

If scene.pickmesh was executed by GPU, I am quite sure my solution run fine.

For me launching a matrix of 30x30 should be enough (900 meshes at maximum) at any moment.

Of course if the camera is not moving, no need to launch the function to occlude meshes.

If the camera only pans, a % of already computed occluded meshes could be still valid, for zooming in and out, maybe not so easy to resuse.

Do you understand my problem now and why I am thinking in deploying this technique?

Best regards

Share this post


Link to post
Share on other sites

I understand what you mean but if you want to pass 80K meshes to the GPU (or 77 million vertices !), before any selection CPU side to reduce drastically this order of magnitude, I'm afraid you will still encounter performance issues anyway, even with a good GPU occlusion algo.

That's the reason why I was suggesting to rethink the global approach and to decouple the data extracted from your DB from their 3D representations (the meshes) in order to manage far less 3D representations than the total data. Just my humble opinion.

But I'm really curious to discover a decent working GPU occlusion algo that would achieve to handle so many meshes. 

Share this post


Link to post
Share on other sites

I couldn't find a good occlusion method either @jerome I ended up subdividing my scene into dynamic regions and calculating 'neighbor' cubes and dropping the visibility of those meshes not in my local regions. Every so many frames I recalc what region the camera is in and reevaluate what regions are loaded and what regions need to be hidden or loaded. When you call this evaluation can probably still be greatly optimized. This is just something I'm playing with as I have time....

I'm loading lists of models dynamically from a database too.

 

You can see the region functions I wrote here and the fully built scene load call:
http://www.red12.studio/Demos/Web/Include/Loaders/map_loader.php?region=1&zone=1

 

This is the PHP for the actual load builder (creates a javascript function to call "load map" from the main scene)

<?php
echo "
// build all the map objects
var load_map = function(scene, offset, DBObj, REGIONS)
{";
	$last_obj="";
	list($res) = get_query("SELECT MIN( px ) AS min_px, MAX( px ) AS max_px, MIN( pz ) AS min_pz, MAX( pz ) AS max_pz, MIN( py ) AS min_py, MAX( py ) AS max_py FROM `map_info` WHERE `region`=". $region ." && `zone`=". $zone .";");
	$SR = mysql_fetch_array($res);

	$min_x = $SR['min_px'];
	$max_x = $SR['max_px'];
	$min_z = $SR['min_pz'];
	$max_z = $SR['max_pz'];
	$min_y = $SR['min_py'];
	$max_y = $SR['max_py'];

	if ($min_x < 0) { $min_x = floor($min_x); } else { $min_x = ceil($min_x); }
	if ($max_x < 0) { $max_x = floor($max_x); } else { $max_x = ceil($max_x); }
	if ($min_y < 0) { $min_y = floor($min_y); } else { $min_y = ceil($min_y); }
	if ($max_y < 0) { $max_y = floor($max_y); } else { $max_y = ceil($max_y); }
	if ($min_z < 0) { $min_z = floor($min_z); } else { $min_z = ceil($min_z); }
	if ($max_z < 0) { $max_z = floor($max_z); } else { $max_z = ceil($max_z); }

	$x_levels = ceil((abs($max_x) + abs($min_x)) / $sub_region_size);
	$y_levels = ceil((abs($max_y) + abs($min_y)) / $sub_region_size);
	$z_levels = ceil((abs($max_z) + abs($min_z)) / $sub_region_size);

	$region_id = 1;
	for ($ix=1; $ix<=$x_levels; $ix++)
	{
		$min_x_t = $min_x + ($sub_region_size * ($ix-1));
		$max_x_t = $min_x_t + $sub_region_size;
		$min_y_t = $min_y;
		$max_y_t = $min_y_t + $sub_region_size;
		$min_z_t = $min_z;
		$max_z_t = $min_z_t + $sub_region_size;

		for ($iz=1; $iz<=$z_levels; $iz++)
		{
			$min_z_t = $min_z + ($sub_region_size * ($iz-1));
			$max_z_t = $min_z_t + $sub_region_size;

			for ($iy=1; $iy<=$y_levels; $iy++)
			{
				$min_y_t = $min_y + ($sub_region_size * ($iy-1));
				$max_y_t = $min_y_t + $sub_region_size;

				$region_info[$region_id]['min_x'] = $min_x_t;
				$region_info[$region_id]['max_x'] = $max_x_t;
				$region_info[$region_id]['min_y'] = $min_y_t;
				$region_info[$region_id]['max_y'] = $max_y_t;
				$region_info[$region_id]['min_z'] = $min_z_t;
				$region_info[$region_id]['max_z'] = $max_z_t;

				echo "
	REGIONS[". $region_id ."] = {
		min_x: ". $min_x_t .",
		max_x: ". $max_x_t .",
		min_y: ". $min_y_t .",
		max_y: ". $max_y_t .",
		min_z: ". $min_z_t .",
		max_z: ". $max_z_t .",
		region_x: ". $ix .",
		region_y: ". $iy .",
		region_z: ". $iz .",
		neighbors: [],
		inside: []
	};";

				$region_id++;
			}
		}
	}


	echo "

	calculate_neighbors(REGIONS);


	// lights
	var sun = new BABYLON.HemisphericLight(\"Hemi0\", new BABYLON.Vector3(0, 1, 0), scene);";


	if (!$inside)
	{
		echo "


	// skybox
	var skybox = BABYLON.Mesh.CreateBox(\"skyBox\", 170.0, scene);
	var skyboxMaterial = new BABYLON.StandardMaterial(\"skyBox\", scene);
	skyboxMaterial.backFaceCulling = false;
	skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture(\"Include/Skybox/skybox\", scene);
	skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
	skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
	skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
	skybox.material = skyboxMaterial;
	skybox.infiniteDistance = true;
	skybox.isPickable = true;
	skybox.name= \"skybox\";

	DBObj[skybox.name] = {
		ID: \"999999999\",
		Name:  \"Skybox\",
		px: \"0\",
		py: \"0\",
		pz: \"0\",
		rx: \"0\",
		ry: \"0\",
		rz: \"0\",
		sx: \"0\",
		sy: \"0\",
		sz: \"0\",
		wx: \"0\",
		wy: \"0\",
		wz: \"0\",
		visible: \"1\",
		inside: \"0\",
		allvisible: \"1\",
		maxview: \"0\",
		collision: \"0\"
	};";
	}


	// build all the water textures and babylon meshes...
	$water_count=0;
	$water_id=999991000;
	unset($water_name);
	list($res) = get_query("SELECT * FROM `water` WHERE `region`=". $region ." && `zone`=". $zone .";");
	while ($water = mysql_fetch_array($res))
	{
		$water_name[$water['water_id']] = $water['name'];
		$water_count += 1;
		$water_id += 1;
		echo "


	var ". $water['name'] ."_tex = new BABYLON.WaterMaterial(\"water_material". $water_count ."\", scene);
	". $water['name'] ."_tex.bumpTexture = new BABYLON.Texture(\"Include/Textures/Bawssump/". $water['bump'] ."\", scene);
	". $water['name'] ."_tex.bumpHeight = 0.1;
	". $water['name'] ."_tex.windForce = ". $water['wind_force'] .";
	". $water['name'] ."_tex.windDirection = new BABYLON.Vector2(". $water['wind_dir1'] .", ". $water['wind_dir2'] .");
	". $water['name'] ."_tex.waveHeight = ". $water['wave_height'] .";
	". $water['name'] ."_tex.waveLength = ". $water['wave_length'] .";
	". $water['name'] ."_tex.waterColor = new BABYLON.Color3(". $water['red'] .", ". $water['green'] .", ". $water['blue'] .");
	". $water['name'] ."_tex.colorBlendFactor = ". $water['color_blend'] .";";

		if (!$inside)
		{
			echo "
	". $water['name'] ."_tex.addToRenderList(skybox);";
		}


		if (!$water['texture_only'])
		{

			echo "

	var ". $water['name'] ."_mesh = BABYLON.Mesh.CreateGround(\"ground\", ". $water['length'] .", ". $water['width'] .", ". $water['depth'] .", scene);
	". $water['name'] ."_mesh.name = \"". $water['name'] ."\";
	". $water['name'] ."_mesh.position.y += ". $water['x'] .";
	". $water['name'] ."_mesh.position.y += ". $water['y'] .";
	". $water['name'] ."_mesh.position.y += ". $water['z'] .";
// need to add in rotation for the water later...
	//". $water['name'] ."_mesh.rotation.y = ". $water['r'] .";
	". $water['name'] ."_mesh.backFaceCulling = true;
	". $water['name'] ."_mesh.material = ". $water['name'] ."_tex;

	DBObj[". $water['name'] ."_mesh.name] = {
		ID: \"". $water_id ."\",
		Name:  \"". $water['name'] ."\",
		px: \"0\",
		py: \"0\",
		pz: \"0\",
		rx: \"0\",
		ry: \"0\",
		rz: \"0\",
		sx: \"0\",
		sy: \"0\",
		sz: \"0\",
		wx: \"0\",
		wy: \"0\",
		wz: \"0\",
		visible: \"1\",
		inside: \"0\",
		allvisible: \"1\",
		maxview: \"0\",
		collision: \"0\"
	};";

		}


	}

	if ($water_count)
	{
		echo "


		";
	}

	
	//$sub
	$count=0;
	list($res) = get_query("SELECT * FROM `objects` LEFT JOIN `map_info` ON `objects`.`name`=`map_info`.`name`  WHERE `region`=". $region ." && `zone`=". $zone ." && `disabled`=0 ORDER BY `package`, `objects`.`name`;");
	while ($objects = mysql_fetch_array($res))
	{
		if ($last_package!=$objects['package'])
		{
			if ($last_package!="")
			{
				echo "];";
				$count=0;
			}

			echo "


	// package meshes
	var package_". $objects['package'] ." = [";
		}

		if ($last_obj!=$objects['name'])
		{
			if ($count>0)
			{
				echo ", ";
			}

			echo "\"". $objects['name'] ."\"";
			$count++;
		}

		$last_package = $objects['package'];
		$last_obj = $objects['name'];
	}


	echo "];";


	$last_package="";
	$last_obj="";
	mysql_data_seek($res, 0);
	while ($objects = mysql_fetch_array($res))
	{
		if ($last_package!=$objects['package'])
		{
			if ($last_package!="")
			{
				echo "
				}
			}
		}
	);



";
			}

			echo "


	BABYLON.SceneLoader.ImportMesh(package_". $objects['package'] .", \"". $home_path . $objects['dir'] . $file_type ."/". $objects['package'] ."/\", \"". $objects['package'] .".babylon\", scene, 
		function(mapZone, particleSystems, skeletons)
		{
			for (var i=0; i<mapZone.length; i++)
			{
";
		}


		if ($last_obj!=$objects['name'])
		{

			if ($last_obj!="" && $last_package==$objects['package'])
			{
				echo "
				}";
			}

			echo "

				if (mapZone[i].name == \"". $objects['name'] ."\")
				{
					////////////////////////////////////////////////////////
					// Parent Mesh
					// Due to issues when hiding the parent mesh, making the 
					// parent it's own thing and dropped below where it
					// would ever be viewed.
					////////////////////////////////////////////////////////

					mapZone[i].visiblity=true;
					mapZone[i].isVisible=true;
					mapZone[i].name = \"". $objects['name'] ."\";
					mapZone[i].position = new BABYLON.Vector3(0, -100000, 0);
					mapZone[i].scaling = new BABYLON.Vector3(". $objects['sx'] .", ". $objects['sy'] .", ". $objects['sz'] .");
					mapZone[i].rotationQuaternion = null;
					mapZone[i].rotation = new BABYLON.Vector3(". $objects['rx'] .", ". $objects['ry'] .", ". $objects['rz'] .");
					mapZone[i].backFaceCulling = false;
					mapZone[i].isPickable = true;


					////////////////////////////////////////////////////////
					// Instance Copies
					// Making every model an instance. Increases the verts, 
					// but there are issue with hiding the parent models.
					////////////////////////////////////////////////////////

					item_used=1;
					var ". $objects['name'] ."_inst = 0;";
		}

		echo "

					". $objects['name'] ."_inst++;
					objInstance = mapZone[i].createInstance(\"". $objects['name'] ."_inst_\"+ ". $objects['name'] ."_inst +\"\");
					objInstance.visiblity = true;";

		if ($objects['always_visible'])
		{
			echo "
					objInstance.isVisible=true;";
		}
		else
		{
			echo "
					objInstance.isVisible=false;";
		}

		echo "
					objInstance.position = new BABYLON.Vector3(". $objects['px'] .", ". $objects['py'] .", ". $objects['pz'] .");
					objInstance.scaling = new BABYLON.Vector3(". $objects['sx'] .", ". $objects['sy'] .", ". $objects['sz'] .");
					objInstance.rotationQuaternion = null;
					objInstance.rotation = new BABYLON.Vector3(". $objects['rx'] .", ". $objects['ry'] .", ". $objects['rz'] .");
					objInstance.backFaceCulling = false;
					objInstance.isPickable = true;
					objInstance.freezeMatrix();
					objInstance.freezeMaterials();
					DBObj[objInstance.name] = {
						ID: ". $objects['object_id'] .",
						Name:  \"". $objects['name'] ."\",
						px: \"". $objects['px'] ."\",
						py: \"". $objects['py'] ."\",
						pz: \"". $objects['pz'] ."\",
						rx: \"". $objects['rx'] ."\",
						ry: \"". $objects['ry'] ."\",
						rz: \"". $objects['rz'] ."\",
						sx: \"". $objects['sx'] ."\",
						sy: \"". $objects['sy'] ."\",
						sz: \"". $objects['sz'] ."\",
						wx: \"". $objects['wx'] ."\",
						wy: \"". $objects['wy'] ."\",
						wz: \"". $objects['wz'] ."\",
						visible: \"". $objects['visible'] ."\",
						inside: \"". $objects['inside'] ."\",
						allvisible: \"". $objects['always_visible'] ."\",
						maxview: \"". $objects['max_distance'] ."\",
						collision: \"". $objects['collision'] ."\"";


			for ($FR=1; $FR<=sizeof($region_info); $FR++)
			{
				if (
					($region_info[$FR]['min_x']<=$objects['wx'] && $region_info[$FR]['max_x']>=$objects['wx'])
					&& ($region_info[$FR]['min_y']<=$objects['wy'] && $region_info[$FR]['max_y']>=$objects['wy'])
					&& ($region_info[$FR]['min_z']<=$objects['wz'] && $region_info[$FR]['max_z']>=$objects['wz'])
				)
				{
					echo ",
						region: ". $FR ."";
					break;
				}
			}

			echo "
					};
					BABYLON.Tags.AddTagsTo(objInstance, \"region\"+ ". $FR ." +\"\");";


		// any mesh that is water needs the material added
		if ($objects['water'])
		{
			echo "
					objInstance.material = null;
					objInstance.material = ". $water_name[$objects['water']] ."_tex;";
		}

		// add water reflection / refractions
		list($w_res) = get_query("SELECT `water`.`name` FROM `map_info_reflect` LEFT JOIN `water` ON `map_info_reflect`.`water_id` = `water`.`water_id` WHERE `map_info_reflect`.`object_id`=". $objects['object_id'] ."");
		while ($reflect = mysql_fetch_array($w_res))
		{
			echo "
					". $reflect['name'] ."_tex.addToRenderList(objInstance);";
		}

		$last_package=$objects['package'];
		$last_obj=$objects['name'];
	}


	echo "
				}
			}
		}
	);
}";

?> 

 

Share this post


Link to post
Share on other sites

Thinking back to your huge amount of meshes ...

I notice that you said you froze the mesh World matrices. This implies your mesh won't move in the scene, right ?

Well, if your meshes are positioned at their final location forever, you could pre-compute (before entering the render loop) some areas to sort you meshes in (kind of octree or, better said, a space partitioning with blocks). Then according to the camera position, you can decide to de/activate the meshes in the distant partition sections.

This is a bit similar to what reddozen just proposed.

The partitioning from the feature FacetData works this way. It's quite light, easy to implement with a single flat array, easy to set and fast to access then : https://github.com/BabylonJS/Babylon.js/blob/master/src/Mesh/babylon.mesh.vertexData.ts#L2335

 

Share this post


Link to post
Share on other sites

Hi

 

Many many thanks to everybody for your answers.

This portal is wonderful.

Yes my CAD is static, no animations at all.

I will have a look to your answers and come back yo you in short.

Would it be possible for you to put ans example in PG?

And again, many many thanks.

Best regards

Share this post


Link to post
Share on other sites
On 6/29/2017 at 6:57 AM, jerome said:

This is a bit similar to what reddozen just proposed.

The partitioning from the feature FacetData works this way. It's quite light, easy to implement with a single flat array, easy to set and fast to access then : https://github.com/BabylonJS/Babylon.js/blob/master/src/Mesh/babylon.mesh.vertexData.ts#L2335

I'll have to look at that... may be able to simplify mine some.

ua4192,
I forgot to mention that mine uses the "tags" feature to group objects in their regions. But you can see that from looking at it. That simplified my organized lists by letting Babylon keep up with it instead of me. Not sure if that's more or less process heavy, but it works well.

Share this post


Link to post
Share on other sites

Yo @Deltakosh or @RaananW ...

So does this mean the Babylonjs DOES support occlusion culling... I dont hav to do anything right... if the mesh is NOT part of the VIEW frustum BJS will automatically cull that mesh.

So if I have a terrain ground mesh that is a grid of 3 x 3 sections (I am still trying to effectively split a large terrain mesh into smaller chunks) if I am facing forward in the middle top section (say grid sort 0, 2... the second square at top) then the rest of the meshes in the grid behind my camera view SHOULD not rendered... That is occlusion culling... Right ???

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.