Jump to content

Incremental Loading of Saved Content


Sparky
 Share

Recommended Posts

Hi,

 

I was just wondering how, in theory, you could incrementally load part of a scene that is changed in game and saved out? i.e. Load map, build things, save map. I've read the docs and seen that there is a way to do incremental loading, but that is using a piece of software that I won't have on the server. Can I save out the blocks of the scene into a certain json format?

 

Thanks for your help

Link to comment
Share on other sites

Yes, I've read that one. It links to source code for what looks like a C# project. It doesn't seem to have the spec for the .incremental.babylon files etc, which would be helpful (unless I've missed something). I'm not going to have those incremental files pre-built, so it doesn't look like that will be useful. I could always fight my way thought and refactor the code, but I was hoping that there was another option as I don't have Visual Studio on my home dev machine.

Link to comment
Share on other sites

Hi!

Just a note, incremental loading is triggered when the object is in the frustum (when it is seen by the camera). I wouldn't use it to load data after, for example, a new level is supposed to be shown.

As John said, you could use the ImportMesh to do that, or the Append method of the loader (which loads cameras and lights as well as meshes).

Incremental is automated, as I understand, you want to trigger it by yourself. Or am I way wrong here?

Link to comment
Share on other sites

Hi Raanan,

 

Thanks for your message. What I'm looking at is a shared map where users will have incrementally loaded sections, so I wouldn't be looking to trigger the incremental sections in that manner. But as the world is updated, I'll need to save out the updated sections for other users to load in.

 

I will also be looking to save out and load in sections during gameplay while they are in the frustum i.e. if another player updates that section of the map.

 

So from what you're saying, if I understand correctly, is that I should use incremental loading in the first instance (loading sections of map as the player moves around), but importMesh in the second instance (loading in a section of map from the server that has been updated by another player). Does that make sense?

Link to comment
Share on other sites

Control the loads manually using import mesh.... I do this with a game client I'm working on. I use PHP and Ajax to dynamically build maps based on databased coordinates etc. I think what you're expecting incremental loading to be is not what you think.

 

You will need a server engine to coordinate all the individual player changes, a heart beat from the clients to check for updates with the server, and an AJAX process to call import mesh from the server's list of new objects (or delete objects etc...).

 

I hope this makes since to you.

Link to comment
Share on other sites

I pass it the babylon scene and then make my import mesh calls on it. Can make one to delete objects too... I have all my objects in specific babylon "packages". All my trees etc are in one babylon file, and map specific items are in another. You can use an array of items in import mesh to only load what you want out of the babylon file. I use this is organize my babylon files without having one for each object.

 

Here's the main file I have... (looks like I have some stray marks to clean out of the dynamic function)

http://www.diviniaro.com/WGClient/Models/Loaders/map_loader.php

 

 

This is when I call a specific area of the map...

http://www.diviniaro.com/WGClient/Models/Loaders/map_loader.php?zone=1&region=1

Link to comment
Share on other sites

Here is the actual page if this helps.

 

You'll see that it's a very short script, but build dynamic load lists based on groups of 3D objects loaded from a database.

I group them by zone and region, and in the future will include sub-zones. The goal of my setup is eventually micro-managing the environment to minimize the amount of objects loaded. There's no reason to load everything in a house on the other side of town if you're not even near the building.

<?php	header('Content-type: text/javascript');	include("./database.php");	$region=$_GET['region'];	$zone=$_GET['zone'];	$file_type = "Raw";	$home_path = "..";	//create an array for the LOD scripts	unset($LOD);	list($res) = get_query("SELECT * FROM `lod_levels` ORDER BY `level`;");	while ($lodv = mysql_fetch_array($res))	{		if ($lodv['level']!=1)		{			$LOD[$lodv['level']] = $LOD[$lodv['level']-1] .", { quality: ". $lodv['percent'] .", distance: ". $lodv['distance'] ." }";		}		else		{			$LOD[$lodv['level']] = "{ quality: ". $lodv['percent'] .", distance: ". $lodv['distance'] ." }"; 		}	}	echo "var Prt_f01_map = function(scene, offset, DBObj){";	$last_obj="";	list($res) = get_query("SELECT * FROM `objects` LEFT JOIN `map_info` ON `objects`.`name`=`map_info`.`name` WHERE `region`=". $region ." && `zone`=". $zone ." ORDER BY `package`, `objects`.`name`;");		$count=0;	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'] ."\")				{					item_used=1;					var ". $objects['name'] ."_inst = 0;					mapZone[i].visiblity=true;					mapZone[i].isVisible=true;					mapZone[i].name = \"". $objects['name'] ."\";					mapZone[i].position = new BABYLON.Vector3(". $objects['px'] .", ". $objects['py'] .", ". $objects['pz'] .");					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;					DBObj[mapZone[i].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'] ."\"					};";			if ($objects['lod']!=0)			{				echo "					mapZone[i].simplify([". $LOD[$objects['lod']] ."], 						true, BABYLON.SimplificationType.QUADRATIC, function() {							// we're not using the callback function for now...but it's here						});";			}			echo "					////////////////////////////////////////////////////////					// Instance Copies					////////////////////////////////////////////////////////";		}		else		{			echo "					". $objects['name'] ."_inst++;					objInstance = mapZone[i].createInstance(\"". $objects['name'] ."_inst_\"+ ". $objects['name'] ."_inst +\"\");					objInstance.visible = true;					objInstance.isVisible = true;					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;					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'] ."\"					};";		}		$last_package=$objects['package'];		$last_obj=$objects['name'];	}	echo "				}			}		}	);}";?> 
Link to comment
Share on other sites

Thanks Red,

 

What I had been looking at (from another forum members suggestion) was generating the map and then sectioning it off into merged meshes. Once I have the merged meshes, I'll save those out so I can just load a section of map (terrain, buildings and any other static elements) as required once visible to the user. If I'm understanding you correctly, your approach is to save out each map square/building/whatever else and load in a regions worth when required, which you'll then merge once it's all client side, is that right? Your approach would certainly be easier to manage across multiple users, but more work for babylon (as you'd be repeatedly merging the meshes. Not sure which is the best way to go.

Link to comment
Share on other sites

I don't merge meshes. They're still individual objects. I want to avoid this when I can so that maps can be manipulated in real time by an admin, or for an event.

 

 

My planned structure...

Skybox - always loaded

 

Zone - my local segment of the world map with landmarks and terrain

Terrain - always loaded with LOD

Landmark objects - A ridiculous view distance and LOD

 

Region - subsets of the zone. These have the buildings, trees, and other map fillers that I only want visible from a moderate view range.

 

Rub-region - these are things like building interiors or dungeon crawler rooms. I don't want to render every cup, plate, and interior house detail if you're not inside the house, nor to I want to render every room of a large castle etc. From inside this area, I can also shut off all the other outside objects because you can't see the sky or buildings etc from inside a building.

Link to comment
Share on other sites

Ah ok, are you building something first person then? I'm looking at at RTS, so could end up with a lot of meshes, which from what i've read, can be problematic and cause performance issues, hence the merging. You can get around the manipulation by keeping data and un-merging when needed in order to manipulate, then re-merge. These evens would be reasonably rare for me such as building something, so I wouldn't need it to be super-real-time as you might with say, picking up a cup.

Link to comment
Share on other sites

I'm building an MMO environment. Things will added or removed from the render list based on distances to target and movement speed of the character. I'm sure I'll get into merging things once I've exhausted everything else. I use a lot of instancing though.

Link to comment
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...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...