sinisterchipmunk / jax

Framework for creating rich WebGL-enabled applications using JavaScript and Ruby
http://jaxgl.com
MIT License
96 stars 16 forks source link

Submeshes #95

Open Goutte opened 11 years ago

Goutte commented 11 years ago

Hello !

I've been thinking about submeshes for a while. I know you use the term submesh in jax to describe the additional mesh(es) used to cheat the buffer limitations, but I've not found a better term to describe what I'm trying to do : refactor the logic concerning portions of a mesh.

Think complex faces, like quadrilaterals, hexagons, etc...

Right now, I'm using something like this :

###
A submesh is a fragment of a mesh.
This is an attempt to refactor some tile-related logic.

A quadface is a square, rectangle, or any other ABCD quadrilateral
made of two centrally symmetric triangles, ABD and CDB.

 A     B
  +---+
  | / |
  +---+
 D     C

###
Jax.Submesh or= {}
class Jax.Submesh.Quadface # Quadrilateral?

  constructor: (@mesh, @verticesIndex) ->

  ###
  Get the coordinates of the 4 corners
  ###
  getABCD: () ->
    i = @verticesIndex
    v = @mesh.vertices

    [
      vec3.fromValues v[i+0], v[i+1],  v[i+2]
      vec3.fromValues v[i+3], v[i+4],  v[i+5]
      vec3.fromValues v[i+9], v[i+10], v[i+11]
      vec3.fromValues v[i+6], v[i+7],  v[i+8]
    ]

  ###
  Re-calculate the center of the face, the mean of the four corners.
  We could use only two corners, but with four it is more error-tolerant.
  ###
  getCenter: () ->
    [a,b,c,d] = @getABCD()

    center = vec3.create()
    vec3.add center, a, c
    vec3.add center, center, b
    vec3.add center, center, d
    vec3.scale center, center, 0.25

    center

Does this make your eyes bleed ?

discussion

sinisterchipmunk commented 11 years ago

The last time I tried to introduce a high level API not unlike the one you've suggested, it did not perform so well. Hardware and JS engines have undoubtedly improved since then, but lessons learned: wrapping classes around many small portions of vertices in a potentially large mesh is a performance killer.

Having said that, I wouldn't write off their usefulness. I'm already thinking about how nice it would be to get at individual instances of Triangle -- collision detection and physics engines come springing to mind. Such things are partially implemented in the form of Jax.Geometry.Triangle, but I've not yet managed to merge the APIs for (math) geometry with the APIs for (mesh) geometry. That's in the list of things to do, but it has to be written and used with care, and ideally pushed off into a Web Worker to take advantage of threading.

For APIs like this, instantiation is the most expensive part. If you can keep JavaScript from stalling, you're golden, but for large meshes I don't know if this is an option, until we are using Web Workers for mesh construction.

Edit: Also, it'd be a better practice to build a buffer view on the original vertex buffer, so that if the high-level API makes a change to its vertex data, the change is reflected in the mesh itself. This gets more complicated when you consider that normals may have to be recalculated, tangent data, etc. -- but in v3.0 I have tried to expose APIs for invalidating mesh data for exactly this reason.