vincent / recast.js

A wrapper for the RecastDetour navigation library for node and the browser
http://vincent.github.io/recast.js/tests/test.webgl.html
108 stars 21 forks source link

Add saving/loading navmesh features #9

Open vincent opened 10 years ago

LiamKarlMitchell commented 9 years ago

Saving / Loading a navmesh makes sense when it does not have to be generated every time would mean it can start up quicker. Is there a way I might be able to implement this or is it rather complex?

vincent commented 9 years ago

Hi, thanks for your interest :)

It should not be very hard, but you'll need to patch some files to have it working from the js.

First, did you reach to compile the project ? ? You must have an Emscripten install, patch the Recastnavigation project, and run npm run build.

Now, about the load/save.

I think the main difference with the cpp is the file handling. It's probably easier to just work with Strings or Buffers and put the fs logic directly in the javascript part. What do you think ?

LiamKarlMitchell commented 9 years ago

Hey thanks for the reply :) Sure I will have to look at getting Emscripten setup I have not actually used it before.

I suppose after I build it the editor https://github.com/vincent/recastjs-editor

Will work better? Currently it can crash rather easily I have yet to find why. But that's not relevant to this discussion anyway.

Possibly can have overloaded method? Load file from string Load file from file path Load file from buffer? I guess buffer could be toString automatically anyway im not sure.

It would just have to tell difference between string and file path. some sort of isPath or a check if string matches an obj file or has new line. (Since new line should not be in a file path)

Cheers I will have to check it out.

DoisKoh commented 9 years ago

Hello. Is this still being worked on? Does anyone already have a solution for this?

vincent commented 9 years ago

Hi,

I don't know about @LiamKarlMitchell but I'm not currently working on it.

If you have specific needs or ideas about it, please share them here :-)

DoisKoh commented 9 years ago

Hi!

I need to be able to save/load the nav meshes (instead of having to calculate them every time I run my application) because it takes too long to generate them for the large models my application uses.

Using web workers helps with responsiveness since I can still interact with the program whilst the mesh gets generated but what I really need is a much better startup time which I believe can be achieved through directly saving and loading the nav meshes.

LiamKarlMitchell commented 9 years ago

Sorry, I have been busy with other things.

Also noticed that recast was not being entirely accurate with the mesh (height wise) was getting flattened. Maybe there are some settings I can tweak for that but I haven't had the chance.

Something we did end up doing was using Atangeo Balancer to create lower poly mesh whilst keeping true to the topology as much as we could.

Here is a breif document on our findings. https://docs.google.com/document/d/1TLX8mAcPRLdz4WIq_lkbNQckFZxQG-KLsaIV8wr-CxU/edit

Less detail means loading quicker right :) (We found we could goto about 35% of the total faces.

In the meantime before this sort of feature is implemented would you happen to know of an open source algorithm or command line app that could be put in the build pipeline to compact the maps down?"

Have to reduce polycount whilst keeping the topology and edges correctly.

DoisKoh commented 9 years ago

Sorry, I'm very new to this and have nothing to recommend.

I'm running on Windows and have finally managed to compile the code with Emscripten but the library I get (recast.js) is 1 whole megabyte less than the one online... and more importantly it also doesn't work when I substitute the pre-compiled one (that I've been using in my project) with it. If I ever figure out how to get all this working and I have anything worth sharing, I'll post it.

vincent commented 9 years ago

I began to hack something, but I struggle a bit on the serialization. doing it by hand seems a pity, and shipping an external lib like Boost seems overkill.

I think I'll try to use the built-in file dump and use that as a workaround in the meanwhile.

vincent commented 9 years ago

Hi @LiamKarlMitchell , hi @DoisKoh ,

I have a load/save capable branch in f.load.save, although it needs some polish.

Do you think you could test it ?

I've made examples for both saving and loading https://github.com/vincent/recast.js/blob/f.load.save/tests/test.navmesh_save.js https://github.com/vincent/recast.js/blob/f.load.save/tests/test.navmesh_load.js

It works at least with the test level, but don't know if it's really faster with a bigger mesh.

LiamKarlMitchell commented 9 years ago

Hi @vincent thank's I will take a look into this.

vincent commented 9 years ago

Thank you.

Note that using a navmesh saved from the RecastDemo app should work, this could ease the process a bit. Otherwise, you'll need to run a script like the "test.navmesh_save" with nodejs to create one.

LiamKarlMitchell commented 9 years ago

Sure :), I plan to use a grunt task to load each one and save it.

Currently we have code that uses A* and Funnel on simplified meshes to do our navigation. So it will be interesting to compare.

Maybe I can get it in there over the next week.

DoisKoh commented 9 years ago

Hah! Well I recently completed a simple working version as well...

Saving of Nav Mesh

// Loads the model into recast to get ready for generating the nav mesh
recast.OBJLoader(modelPath + ".obj", function() {

    // Build the nav mesh and then download it as a text file
    // buildSoloSave() returns a string (all lines end with line feed '\n' only,
    // just write that string into a text file for loading.) "download" is just a
    // function I'm using to save the text to a file. You can get it in
    // the demo app linked below.
    var a = recast.buildSoloSave();
    download(a, modelName + ".txt", "text/plain");
});

Loading of Nav Mesh

// Load the nav mesh from a text file
recast.getFileContents(modelPath + ".txt", function(contents) {

        // Reads the nav mesh data from a text file, then creates the detour tiled mesh or whatever
        recast.loadNavMeshFromContents(contents);
    }
}

Link to download recastjs with save/load https://docs.google.com/uc?authuser=0&id=0B4dM88QNro7jX1lZT3Q4a2F3d1k&export=download

Link to download Demo App https://docs.google.com/uc?authuser=0&id=0B4dM88QNro7jRnEtTzVUYUNKbEU&export=download

I'm busy with something else now, but I'm going to try yours out and we're probably going to switch to your solution since I'm just a temp and your code will be maintained.

vincent commented 9 years ago

I've added a small tool to convert .obj to a tilecache here https://github.com/vincent/recast.js/blob/f.load.save/tools/make-tilecache

AmdEagle commented 9 years ago

Thank you for the feature of loading/saving the mesh data. i encountered an error will trying to load an obj attached is a screenshot of the error i encountered.Please advise on error.

error when loading obj

vincent commented 9 years ago

Hi @BalakrishnanV

Can you paste the code you are using ? I think I got the same when trying to load multiple times a mesh/tilecache.

AmdEagle commented 9 years ago

Thank you for the quick response here the line of code i am using to load the object. --> recast.OBJLoader( 'test.obj', recast.cb(onRecastLevelLoaded) );

Attached is the complete Error screenshot error when loading obj

AmdEagle commented 9 years ago

@vincent Any updates on the issue ?

vincent commented 9 years ago

not yet, sorry. I hope I'll have some free time this week end.

LiamKarlMitchell commented 9 years ago

We all hope for free time on the weekend :D Sorry I haven't had a chance to test it yet but its still on my todo list :).

vincent commented 9 years ago

Hey @BalakrishnanV

Can you tell me a bit more about this issue ? It seems I cannot reproduce it in the simple use cases.

Which branch are you using ? fyi, load and save features have been merged in master by now. What use case lead to this error ? Do you encounter it while running tests ?

cheers,

jdestefx commented 6 years ago

I have not been able to get loading and saving to work. I used @vincent tool make-tilecache.js, but the callback on this line is never triggered:

recast.saveTileCache('/tmp/navmesh.bin', recast.cb(function (error, serialized) {

... and so of course no tilecache file ever gets written.

In my main project, I can use the OBJLoader and buildSolo() with no problems.

vincent commented 6 years ago

hi @jdestefx

I'm struggling to reproduce your issue. Could you check that you called recast.buildTiled(); before saving it ?

jdestefx commented 6 years ago

Using the code from your recent edits to the docs, I was finally able to get a .bin file created, but now when I try to use recast.loadTileMesh, I get a lot of file-related errors, particularly "file not found" errors.

Looking over the recast.loadTileMesh functions, I'm even more confused:

713 recast.loadTileMesh = function (path, callback_id) {
714   // with node FS api
715   if (ENVIRONMENT_IS_NODE) {
716     var fs = require('fs');
717     fs.readFile(path, function(err, data) {
718       if (err) throw new Error(err);
719       // FIXME
720       FS.writeFile(path, data, { encoding: 'binary' });
721       recast._loadTileMesh(path, callback_id);
723     });
724 
725   // with ajax
726   } else {
727     _ajax(path, {}, function(data) {
728       // FIXME
729       FS.writeFile(path, new Int8Array(data), { encoding: 'binary' });
730       recast._loadTileMesh(path, callback_id);
731     }, null, 'arraybuffer');
732   }
733 };

1) //FIXME?   something tells me this never actually worked...
2) 720: why are we re-writing the file we just read? and why are we re-writing over the same path? 
3) 720: FS.writeFile is an asynchronous function but there is no callback specified here. is the intention that recast._loadTileMesh is supposed to be called when writeFile is done?