Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add saving/loading navmesh features #9

Open
vincent opened this issue Jul 11, 2014 · 25 comments
Open

Add saving/loading navmesh features #9

vincent opened this issue Jul 11, 2014 · 25 comments

Comments

@vincent
Copy link
Owner

vincent commented Jul 11, 2014

No description provided.

@LiamKarlMitchell
Copy link

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
Copy link
Owner Author

vincent commented Mar 24, 2015

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 logic is entirely handled by the Recast's load / save methods here
  • you'll need to implement the method in JSInterface/main.cpp and export it like here

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
Copy link

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
Copy link

DoisKoh commented Jun 8, 2015

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

@vincent
Copy link
Owner Author

vincent commented Jun 8, 2015

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
Copy link

DoisKoh commented Jun 8, 2015

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
Copy link

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
Copy link

DoisKoh commented Jun 8, 2015

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
Copy link
Owner Author

vincent commented Jun 9, 2015

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
Copy link
Owner Author

vincent commented Jun 19, 2015

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
Copy link

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

@vincent
Copy link
Owner Author

vincent commented Jun 20, 2015

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
Copy link

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
Copy link

DoisKoh commented Jun 22, 2015

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
Copy link
Owner Author

vincent commented Jun 22, 2015

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
Copy link

AmdEagle commented Jul 1, 2015

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
Copy link
Owner Author

vincent commented Jul 1, 2015

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
Copy link

AmdEagle commented Jul 2, 2015

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
Copy link

AmdEagle commented Jul 8, 2015

@vincent Any updates on the issue ?

@vincent
Copy link
Owner Author

vincent commented Jul 9, 2015

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

@LiamKarlMitchell
Copy link

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
Copy link
Owner Author

vincent commented Jul 11, 2015

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
Copy link

jdestefx commented Jul 7, 2018

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
Copy link
Owner Author

vincent commented Jul 8, 2018

hi @jdestefx

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

@jdestefx
Copy link

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? 


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants