xeolabs / scenejs

An extensible WebGL-based 3D engine. This is an archived project.
https://xeolabs.github.io/scenejs/
Other
648 stars 165 forks source link

Physics and Collision Detection in SceneJS #216

Closed aqiruse closed 9 years ago

aqiruse commented 11 years ago

There seems to be a nice physics library for Three.js called PhysiJs. The code is on github at http://chandlerprall.github.io/Physijs/ I was wondering is there any such physics ability and collision detection for SceneJS? If not, is any planned? How about collision detection?

I used the Stats.js library (at https://github.com/mrdoob/stats.js/) for the Procedural City demo. It runs between 30 fps (when moving the camera around the city, and 61 fps (when the city view is stationary). I am wondering what the impact of collision detection and physics would be on this demo?

I am asking because collision detection and physics are an integral part of what I need to do. I also need a method of querying what I am colliding with, what is in the scene view and determining the properties of what I am looking at. Is SceneJS able to do that? If not, how difficult would be to extend to do those items (collision detection, physics, and property queries)?

xeolabs commented 11 years ago

Not in SceneJS yet, but definitely on the roadmap, and I've done a few experiments looking at how to extend the API to incorporate physics system attributes.

I found that if the physics is done in a worker thread, then the impact on FPS is actually quite minimal, the only real overhead being the transport of data between the threads. Updating transforms in SceneJS is quite efficient, requiring only a redraw of the display list (which is compiled from the scene graph).

I did some experiments with integrating JigLibJS with SceneJS earlier, with some throwaway experiments which I never posted, but what I envisaged was an "object" node type which groups it's subnodes under an "object identity", and can have physics attributes on it:

{
    type: "object",
    id: "myObject",
    physics: {        
        systemId: "somePhysicsSystem",
        mass: 5,
        boundary: { xmin: -20, .... },
        velocity: { x: .3, y: .2 .. },
    },
    nodes: [
        {
              type: "material",
              //..
              nodes: [
                    {
                         type: "geometry"
                         //..
                    }
              ]
        }
    ]
}

So that "object" node would be a sort of facade through which the modelling transform nodes (etc) within the subgraph could be accessed (read/written), as well as the boundary of the subgraph and whatever else.

The problem with the existing nodes is that they can be plugged into all sorts of random arrangements, where for things like physics integration, we need some sort of uniform object type that we can count on to have a position, boundary etc.

This hangs on some work I'm doing right now for custom node types - here's an example of what a custom node type definition would look like: https://gist.github.com/xeolabs/5697733

And a scene that would have an instance of one of these custom node types: https://gist.github.com/xeolabs/5697757

Hope you can get the vague idea of where I'm headed - I'm thinking that an "object" node type (or maybe a "physicsObject" node type or something) could be one of these types.

I'll get this custom node type feature out (this week hopefully), then that should provide the inroads to integrate physics. I dont know exactly what shape the code will take yet, but fairly confident it can be done with a custom node type like that, stay tuned..

xeolabs commented 11 years ago

PS the "object' node from the example above would wrap its subgraph in modelling transform nodes, into which it would feed position/orientation updates coming out of the physics system. It would also find the boundary of the geometries in its subgraph and register those in the physics system. in short, it's a scene-side proxy for a corresponding element in the physics system.

It would make sense to allow multiple systems running in parallel, each in a thread, hence the "systemId" attribute (or whatever). I had eight systems running in threads before the cost of transferring data across the threads started to have a negative impact.

aqiruse commented 11 years ago

I like the example, something like that might work. Need test something like once it is finished. I am wondering, would it also be possible, to include material / texture / color information in the custom node type? Including color information is important, material / texture could come later. Do you think this is possible?

xeolabs commented 11 years ago

Yes, given some appearance attributes, the "object" node could find material/texture nodes in the subgraph, or insert them if missing, then feed the attributes into those nodes.

Hopefully custom node types will allow some experimentation around this without affecting the core framework, then of course there will be various small capabilities needed to add to the SceneJS API as we'd go.

Once I've finished this custom node feature, I could provide a starting template for one of these node types and you could take it from there maybe, with a custom node type, then I could add bits and pieces for boundaries etc if needed in the core API?

xeolabs commented 11 years ago

BTW "SceneHub" was something I was working on to try and get an object hierarchy capability (that could potentially hook into a physics engine): http://scenehub.org/

I've abandoned it, just because it was confusing to have a second API on top of SceneJS, and because the custom node types seem to do the trick well enough.

aqiruse commented 11 years ago

Yes, with a custom node feature and a template, that should provide me the starting point I need for my work, and I could take it from there most likely. Last question, is there a method currently or planned for loading models from JSON, DAE, OBJ, or any other type of 3D model file? Instead of a second API, have you thought about taking the useful functionality from scenehub, like object heirarchy and physics engine hooking, and merely extending SceneJS to include those features, perhaps as optional abilities, instead of creating a new APi for them?

aqiruse commented 11 years ago

Here is a scenario, let's say you create a scene of a house. The house contains rooms, the rooms contain objects like a table, lamps and phones of the table, a chair or two, a couch, a TV, etc. Then being able to determine, which leg on the chair or table is being interacted with, is the phone or the lamp being used, is the couch being sat on, etc. What color is the table? If I move the table, physics wise, what happens to what is on the table and near the table (like the chair)? etc. Hope this gives you an idea of where I want to head with this.

xeolabs commented 11 years ago

Last question, is there a method currently or planned for loading models from JSON, DAE, OBJ, or any other type of 3D model file?

There was a DAE->SceneJS parser in python for V2.0, which is now very much out of date: https://github.com/xeolabs/scenejs-pycollada

I was thinking of extending this libary to convert DAE->SceneJS at some point, but ran out of time: https://github.com/xeolabs/collada2json

So yes, what SceneJS really needs at this point is a DAE importer..

Instead of a second API, have you thought about taking the useful functionality from scenehub, like object heirarchy and physics engine hooking, and merely extending SceneJS to include those features, perhaps as optional abilities, instead of creating a new APi for them?

Exactly yeah - a custom node type (ie. "object") for SceneJS would do what I was trying to do with scenehub. The other thing that scenehub was for was for organising libraries of reusable assets (geometry materials etc), but that also could be done via custom node types of some sort. SceneHub is pretty much redundant due to custom node types.

All that remains to do on them is extend the SceneJS API a bit to allow synchronization, since the custom node types can be dynamically loaded on demand, where their instances would appear in the graph asychronously once the node type definition plugin scripts have loaded and installed. Aim to have that by the end of the week.

xeolabs commented 11 years ago

PS. I found DAE and OBJ parsing is ideally not done in JS - better to preparse server-side.

BTW SceneJS also has support for binary geometry arrays as well if needed, via geometry plugins.

aqiruse commented 11 years ago

Thank you. I look forward to seeing the work. I appreciate the quick response(s) as well.

xeolabs commented 11 years ago

No prob, this ties in well with the custom node types - it's valuable to have concrete use cases. I think it should be fairly straightforward. Post any more requirements that come to mind in this issue..

xeolabs commented 11 years ago

Custom node types now supported: http://xeolabsblog.blogspot.de/2013/06/custom-node-types-in-scenejs-30.html

aqiruse commented 11 years ago

Thank you for implementing that so quickly. I will go more in depth into it soon.

In the meantime, I just had an idea, not exactly related though. How about a function like "loadContent" that you could pass it a file of some type, and it would reload the scene using the new content? For example, instead of a different page for each of the demos / examples, you could have a loadContent("viewTransform.js.xml.whatever") and to see the next example you could merely call loadContent("colorMap.js.xml.whatever") and it would reload the scene with the new object and the object properties while, perhaps, keeping the same initialization information? In terms of a CAD example, this would allow a person to compare two models of the object or two different objects without requiring an entire rewrite and inclusion of the webpage and corresponding scripts. Anyways, just a thought.

Or if not in the API, another though would be to put it in a utility file that could be included to perform that and any other useful functions.

aqiruse commented 11 years ago

Have you thought about using the work from Stats.js in your examples page to show the speed at which the examples work? This would give people an idea of what they could expect if using the SceneJs project. I realize Stats.js is a seperate project. It does however give a nice display of both ms for network load time and fps for framerate.

aqiruse commented 11 years ago

Okay, I working on this now. I have modified my working copy of my fork of SceneJS moderately. However, I am having a slight difficulty. I need a method of getting the node vertices positions from a Node immediately after calling addNode. Would you have any suggestions as to how I might implement such a feature? Or where to look for it if it is already implemented?

aqiruse commented 11 years ago

Also, slightly related, how do I set the position of and looking at position of a perspective camera at runtime? Is that something that needs added as well?

xeolabs commented 11 years ago

Hey I've made a start on some custom nodes that implement a rigid body physics system - check out the API docs: https://github.com/xeolabs/scenejs/wiki/Physics

The first physics system demo: http://scenejs.org/examples.html?page=physicsBouncingSpheres

This is alpha status.

I'm not auto-computing the physical boundary of the geometries that comprise each phycical body - my rationale is that whatever process is creating the physical bodies (eg a file loader etc) would be able to know the boundaries of the geometries within them. Plus, there will be additional custom convenience nodes such as physics/box, physics/cylinder that will encapsulate a geometry primitive wrapped with a physics body, where it will set the the body boundary to the prim, since those convenience nodes will be creating both the body and the prim. So the auto-fit thing will be put in the hands of the developer who makes these convenience nodes, to use whatever boundary estimation method they see fit.

There is however a getBoundary method on geometry nodes you might find useful if you do pursue auto-fitting, along with methods to get the modelling and view transform matrices on various transform nodes:

https://github.com/xeolabs/scenejs/blob/V3.1/src/core/scene/geometry.js#L579 https://github.com/xeolabs/scenejs/blob/V3.1/src/core/scene/rotate.js#L35

I'm not using shared typed arrays with the web worker yet, so I'm expecting significant speed increase when I get to that. I have to manage the fallback for when that's unsupported etc.

Also, note the array format on the physics nodes' vector params. For performance and easy integration, all node types developed from this point on will use arrays instead of objects, and the existing nodes will have soon get the ability to specify arrays for their vectors (ie. colors, translations etc).

Setting the position and direction of a camera is actually done with a lookat node: http://scenejs.org/examples.html?page=viewTransform

The camera node sets the projection transform, ie. the "camera optics". The lookat is used to orient the camera.

xeolabs commented 9 years ago

Partial implementation of a physics system started -

Demo: http://scenejs.org/examples/index.html#physics_balls

Writeup: http://xeolabs.com/articles/scenejs-physics/