frenchtoast747 / webgl-obj-loader

A simple OBJ model loader to help facilitate the learning of WebGL.
http://frenchtoast747.github.io/webgl-obj-loader/
MIT License
281 stars 59 forks source link

normalize vertices #14

Closed nickdesaulniers closed 9 years ago

nickdesaulniers commented 9 years ago

I'm not sure if this is a best practice or not. It's frustrating when meshes' vertices are values greater than +/- 1. A friend described to me a trick where you fit a model to clip space by iterating over each vertex, keeping track of max & min x, y, & z values, then pass over them again multiplying them to fit within exactly the 2x2x2 clipping cube. This would make meshes that appear too small be a more reasonable size, and meshes that are too large fit within the standard clipping cube. You could always transform the vertices later with a model matrix. One issue is non uniform scaling. We wouldn't want to non-uniformly scale each axis, or that would mess up the dimensions of the model. Instead, we'd want to find out which axis was closest (or farthest, I guess) to -1:1 and just uniformly scale each axis. It might be a better idea to do this offline once for the obj, rather than every time at runtime. Either a command line tool, or an optional argument at runtime would be helpful.

frenchtoast747 commented 9 years ago

I was thinking about this the other day when I looked at the internals of an OBJ stored mesh: most of the vert coordinates were greater than 1.

I would say that, by default, the attributes shouldn't be normalized and allow for an optional parameter to normalize.

In order to also facilitate issues #12 and #13, the parsing portion could be broken out of the Mesh() initialization and some pre-processor/compiler could be brought in to create both the loader and a command-line tool from the same code (I'm thinking nodejs for the latter).

I would still like for the end user to only have to include the single script so I was thinking about doing some trickery in order to get the workers to work within a single script (something like having a string of parsing code and passing that to create the worker).

I dunno. Having a string of the parsing code sounds awful, though. I'm mostly just brainstorming. Above all, I want the result to be as simple as possible for the end user.

nickdesaulniers commented 9 years ago

I would still like for the end user to only have to include the single script so I was thinking about doing some trickery in order to get the workers to work within a single script (something like having a string of parsing code and passing that to create the worker).

Yes. Web Workers are a PITA in this regard. Especially because of this:

"When using these techniques to inline your worker code, importScripts() will only work if you supply an absolute URI. If you attempt to pass a relative URI, the browser will complain with a security error. The reason being: the worker (now created from a blob URL) will be resolved with a blob: prefix, while your app will be running from a different (presumably http://) scheme. Hence, the failure will be due to cross origin restrictions."

from here.

nickdesaulniers commented 9 years ago

command-line tool from the same code (I'm thinking nodejs for the latter).

This is the best idea. I've written the logic to fit the mesh to the culling cube. What I plan on doing now is:

  1. Create a separate library like this one, but rather than deserializing from OBJ (1 big string) to JS Arrays, serializes from JS Arrays to OBJ (1 big string).
  2. Create a separate library like this one, but does the transformation.
  3. Create a node.js command line utility to do the transform ahead of time, using the above two libraries.
nickdesaulniers commented 9 years ago
  1. https://github.com/nickdesaulniers/array-to-wavefront-obj
nickdesaulniers commented 9 years ago

2 is not worth putting in a seperate lib, since it's so simple:

Given max and min values for x, y, and z:

function scaleFactor (max, min) {
  return 1 / ((max - min) / 2);
};

function translationFactor (max, min) {
  return -(min + (max - min) / 2);
};
nickdesaulniers commented 9 years ago
  1. https://github.com/nickdesaulniers/transform-fit-obj