Load progress feedback

Software: Away3D 4.x

Avatar
jscamposcr, Newbie
Posted: 10 July 2012 04:28 PM   Total Posts: 20

HI guys, I have a simple question:

Is there a way to get the progress of the loads(object and/or materials)?

Thanks in advance!
Jose Campos
JsCampos.com

   

Mr Margaret Scratcher, Sr. Member
Posted: 10 July 2012 10:05 PM   Total Posts: 344   [ # 1 ]

Replying so I can find out too…

   

Avatar
jscamposcr, Newbie
Posted: 10 July 2012 10:09 PM   Total Posts: 20   [ # 2 ]

Somewhere I read that this was also developed with Away3D:

http://nissan-stagejuk3d.com/

And they do have a loading system so I think there must be a way to get the feedback, I went into the classes to check the process, I did track down the load but I dont see any events or anything related to the progress, so the main question is: is there a way to get loading feedback or should we start looking for ways to build our own system?

Regards!
JsC

   

mmix7, Newbie
Posted: 11 July 2012 03:21 AM   Total Posts: 9   [ # 3 ]

Here is my thoughts on this.
Perhaps someone here has a better , less “raw” solution than mine.


I’ve written my own Parser to import a custom model file as raw text (as opposed to binary)—straight up vertices listing with uv’s, and it is much similar to the .obj parser. The way Parsers work in away is (as opposed to true multi-threading) every frame it has a persistent position-indicator of where it is at in the loading of a file (ie , char pos 240 of 1200 as it reads vertices line by line). And it has a mechanism flash as a whole has adopted to detect when the function should return from it’s processing loop in order to maintain frame-rate (ie, continue on the next frame cycle; fake-threading).

So in that sense, it should be very easy considering each file has a known-size, and a persistent known-current-position. And so if you are loading 1 file, progress is as simple as dividing the total file in char’s or bytes(in case it’s a binary stream processor, like for .awd), by the current char/byte position, in relation to scale of 100 for 1-100%.
per my example above(1 file of size 1200), that is:  100/1200=0.083, so multiply by current_pos(240) and get: 20% loading of 1 file complete.
And that’s just a per-char or per-byte resultant. Depending on the file you are loading, it’s possible to use the array of vertices. However the updateVertexData() is called at the end of processing just before finalizeAsset, so in that sense, you would have to add your progress-bar code inside the parser’s vertices loop, and another one for the UV, etc.
Put simply, wherever there is a loop inside a Parser, that is a location you must calculate current/total percentages in relation to one file per instance.


The same applies for multiple files, just conjoined mathematically. This type of loading screen seems to “jump”, because it’s not relative to the calculated(“expected” - varies by factors like cpu availability, page file, lag, etc)  time that it takes to complete the “entire” loading process of potentially multiple files as well as their rendering into the scene (which too can be conjoined as well for a rendering loading stage using callback events—easy stuff). That is why it is common to see progress bars that self-repeat, with changing texts. Especially in installers. So it will reset back to 0% each time it starts loading of a new type of entity, for example.

So i suppose the question is ... how detailed of a loading screen do you want, and how pretty do you want it to be?

And if you wanted to make it time-relative, you could scale it by the amount of time that has passed since the last frame-execution inside the parser’s loop relative to total file-size, making it more dynamic in terms of total progress, as opposed to byte-size, char-size, or chunck-size progress. This type of progress bar would look much more fluid as it progresses 1 to 100. But it is technically inaccurate, and if lag occurs, it could freeze or receive negative values as function of time (which is another topic entirely).

One problem I can think of is how the dependency system operates. It’s entirely possible to have a dependency (such as textures/bitmaps) load delayed from the processing of it’s actual file that references it (like in .awd files). So it may be more difficult to “predict” the total loading based on time via frame-rate.
Another problem is that I don’t believe away3d indexes the file-sizes prior to the initial processing of a specific file—so it may be impossible to determine total file-size without manually calculating it yourself prior to showing the loading screen.

Should definitely be doable. I plan to dive into this later on, so maybe I’ll post my findings here at that time.

And if you read all that, good luck to ya. :)

   

Avatar
jscamposcr, Newbie
Posted: 11 July 2012 04:37 AM   Total Posts: 20   [ # 4 ]

Well that sounds reasonable, but I think I will dive into the loaders to find how the loading process works and find the real fine loader and create an event that retrieves the loading process of each file, with that I can give some visual feedback, something changing in the screen so the user doesnt leave cause of the boring waiting. But of course it would be better if it came implemented wink

   

Richard Olsson, Administrator
Posted: 11 July 2012 08:24 AM   Total Posts: 1192   [ # 5 ]

I’ve replied to many questions like this, but I don’t mind doing it again (because I can’t find my old answers anyway smile). The short answer is that there is no (sensible) general-purpose way to create master loading progress feedback in the Away3D loaders. First of all, let me describe the problem.

In the realm of 3D, the file formats are generally more complex and relies more heavily on external references than what is common amongst the formats that we are used to loading in Flash (e.g. images, sounds and SWF files.)

Taking an OBJ file as an example, the most common case is that it references an external MTL file, and that will in turn often reference one or several external texture files.

This means that if we added a loading progress property to AssetLoader, for instance, and based it on the bytes loaded vs bytes total, it would be incompletely unreliable, and here’s why.

First the OBJ file would start loading. The server responds with total size, so AssetLoader knows both the bytes loaded and the total file size in bytes. So when the file has loaded fully, and the two properties (loaded/total) match, and we start parsing, we are effectively at 100% even though we haven’t started parsing yet. Lets solve that by just padding the progress a little bit, and define a rule that says that the loading is always 80% and parsing is always 20%. That way, when we have loaded the OBJ file, and are just about to start parsing, we are at 80%. This is what the progress property on AssetLoader would return at this point, and hence what your loading bar would display to the user.

A couple of lines into the OBJ file we find a reference to an MTL file that we will have to load. At this point we will have to pause parsing of the OBJ file and request that the MTL file is loaded. This means that we are now roughly at 81-82% of the OBJ file, but at 0% of the MTL file! Doing the math, this means that we are only about 40% of the total progress (assuming, since we don’t know about the size of the MTL file, that they’re equally big—this is in fact another problem with this approach entirely.)

At this point, the loading progress property (and hence your loading bar) would jump back to 40%!

Needless to say, when the MTL file has finished loading and we’re at roughly 80% again, it’s time to start loading any external texture references made in that MTL file, and the scenario described above will repeat itself.

To the user, if we were to blindly implement a progress property on AssetLoader like this (and programmers were to blindly use it to drive their loading bars) the progress bar would probably go like this, if there’s one texture:

1) Run up to 80% (OBJ loaded)
2) Jump back to 40% (MTL reference found)
3) Run up to 80% again (MTL loaded)
4) Run up to 90% (MTL parsed)
4) Jump back to 55% (texture reference found)
5) Run up to 90% again (texture loaded)
7) Run up to 100% (OBJ finished parsing)

And imagine if there were more than a single texture!

Now that we have established what the problem is: What are some possible solutions?

Well, the only way to be able to reliably show a progress indicator when loading (and effectively queueing) a large number of files is to know beforehand the total size of those files, and use that to calculate the progress. Needless to say, Away3D can’t possibly know beforehand how many files it will need to load (e.g. in the OBJ case, whether it has an MTL file or not, and whether or not there are any texture references.) This leaves it up to the programmer to handle this.

Someone suggested that we implement an XML-format for loading, that defines to AssetLoader how many files it should assume that it will need to load, and how large those files are. I think this suggestion is way too complicated to be handled by Away3D, which is a 3D rendering engine, not a loading framework.

The other solution would be to have simpler properties on AssetLoader, like numFilesLoaded and numBytesLoaded, as well as curDependencyProgress. Note that I’m excluding filesTotal and bytesTotal, because Away3D can’t know these! This way, client code (i.e. your code) could implement whatever solution you want to calculating the total progress. This is something that might be added at some point.

   

Richard Olsson, Administrator
Posted: 11 July 2012 08:25 AM   Total Posts: 1192   [ # 6 ]

Now, let me adress some of the comments made by mmix7 in this thread. Most of what you say is perfectly valid, and I just want to clarify why some of what you say can’t be implemented as a general-purpose solution by the engine. I realize that’s probably not what you’re suggesting, but just for the sake of clarity:

First of all, while your general approach (i.e. keeping track of parsing progress) is indeed an important part of the bigger solution, there are some parts missing. First of all, you don’t seem to look at the loading time at all. Maybe you’re using embedded assets, but in the general case loading time has to be accounted for, and is often bigger than parsing time.

The other problem with implementing the solution that you have used for your custom format, on a more general scale, is that far from all formats work like that. First we have the problem with external dependencies (like the MTL file in the OBJ case) and then there are simply some formats that should not be parsed top-to-bottom, like for example Collada. How does one keep track of Collada parsing progress based on file pointer position and total number of bytes in the file, when the actual thing that’s being parsed is an in-memory tree representation of an XML document.

And then there’s the fact that not all of the time spent in a parser is spent on reading the data. Some of the parsers have a finalization step at the end of the parsing (long after the last byte has been read) where they convert an intermediate structure into the Away3D structure. Also, most of the parsers have a geometry post-processing step to split geometries into sub-geometries, and this is often heavier than reading the geometry data. These steps would be missed if progress was solely based on bytesRead/byteTotal, and for some formats these are actually the heaviest parts!

So while I’m sure your solution works great for your custom format, and it is indeed the solution I would have used for such a format as well, I’m afraid it’s not an approach that applies generally to all formats, and thus not an approach that we can implement in the library.

Instead, we would have to make it a responsibility of each parser to keep track of it’s own progress, in whatever way it chooses. Continuing on the Collada example, the DAEParser works in “phases”, and the progress could of course be based on how many phases have been passed and how many remain. But even that isn’t entirely bullet proof.

As I’m sure you guys can appreciate at this point, this is a rather complicated matter. It is something that I’ve been thinking about a lot though, and at some point we should implement a proper solution, but I can say for sure it won’t make it into 4.0.

In the meantime, if loading (and not parsing) is the biggest concern, I suggest either embedding the files into the SWF and using a frame-based preloader, or pre-loading them using URLLoader (e.g. through any of the existing third-party loading queue frameworks), and then just parsing them through Away3D.

   

Avatar
jscamposcr, Newbie
Posted: 11 July 2012 04:18 PM   Total Posts: 20   [ # 7 ]

All of that makes complete sense but now I was thinking about other ways to load files but it depends on how flexible the framework is, but the main question to be asked is: Is there a way to embed the model(OBJ) and its dependencies(MTL and maps) to the swf that I can compile that, load that, which I can track and then feed that in a way to the parser for it to create the object and apply the materials.

Another thing which I can do but it would be easier if someone with some insight would help is where can I dispatch an event every time one object or texture is loaded, with that I could give feedback to the user, not time or percentages but at least say “Loading Model”, “Loading Materials”.

Let me know and thanks for all the help so far!

   

Richard Olsson, Administrator
Posted: 11 July 2012 04:22 PM   Total Posts: 1192   [ # 8 ]

For embedding all dependencies and making sure that the AssetLoader finds them, use AssetLoaderContext. Example can be found here: http://away3d.com/forum/viewthread/2665/

As far as events go, you can listen for DEPENDENCY_COMPLETE for when entire single files finish loading, and you can listen for the usual AssetEvent events for when specific assets, e.g. textures, materials, meshes and geometries (from within any file) complete.

   

Avatar
jscamposcr, Newbie
Posted: 11 July 2012 04:26 PM   Total Posts: 20   [ # 9 ]

That it awesome and that solves my problem and looks like a decent way to solve the loading-feedback problem, once u have everything loaded there should be no big delay from when the swf loads to when the object is displayed.

Thanks a lot! And I hope this thread helps other people find a better way to show loading progress, you can create different SWFs for each object and loads them as you go being able to manage that.

   

Avatar
jscamposcr, Newbie
Posted: 11 July 2012 05:19 PM   Total Posts: 20   [ # 10 ]

Now I have another question, how do you track the parsing progress, we are going from a world where we had to use REALLY simple objects so the parsing process was rather fast and the update/render was the hard stuff to a world where we have the resources to render heavy duty stuff and this gives us the chance to use complex models which take time to parse and build so my question is: is there a way to track the parsing progress?, now I can track the load progress but once everything is loaded there is a pause in which the app is parsing and building the 3D environment, as of now I have a message saying “Creating Environment” but when applications get larger and environments get larger is there a way to show more feedback on this for the user?

Regards!
JsC

   

allensmith, Newbie
Posted: 12 January 2015 08:59 AM   Total Posts: 4   [ # 11 ]

Is there a way in JS to get the progress of a loading image while the image is being loaded? I want to use the new Progress tag of HTML5 to show the progress of loading images.

I wish there was something like:

var someImage = new Image()
someImage.onloadprogress = function(e{ progressBar.value e.loaded e.total };
someImage.src "image.jpg"

____________________________
welcome to qrcode barcode world

   

abbylee, Newbie
Posted: 01 June 2015 03:05 AM   Total Posts: 4   [ # 12 ]
allensmith - 12 January 2015 08:59 AM

Is there a way in JS to get the progress of a loading image while the image is being loaded? I want to use the new Progress tag of HTML5 to show the progress of loading images.

I wish there was something like:

var someImage = new Image()
someImage.onloadprogress = function(e{ progressBar.value e.loaded e.total };
someImage.src "image.jpg"

____________________________
welcome to qrcode barcode world

You can search html5 document viewer, it support loading, viewing and processing images.

   
   

X

Away3D Forum

Member Login

Username

Password

Remember_me



X