Monday, June 4, 2012

UV Projection Mapping and Gladius

‹prev | My Chain | next›

I am making my way slowly into the world of 3d gaming, focusing exclusively on Gladius so far. It can be a bit overwhelming looking through code. In a previous life, I could fake my way through Hamiltonian physics, but I may have a breakdown if I need to figure out quarternions. Up tonight, I hope to get a better grasp on something a little easier: some of the options in "meshes" and how they relate, if at all, to Gladius CubicVR.

The Cubic VR JavaScript project bills itself as a WebGL-based 3d engine. Gladius is also an engine, but a game engine, not a 3d engine. Probably in an effort to cut down on confusion, Gladius calls Cubic VR a rendering backend, not another "engine". Similarly, the Gladius Box2D extension is a physics backend, not an engine. So Gladius is a game engine that is comprised of a number of backends that typically think of themselves as engines of one sort or another. I think that makes sense in a weird way.

Anyhow, the mesh in the cube example has two entries that I don't quite understand:
  var mesh =
  {
    // ...
    uv: [
      [ [0, 1], [1, 1], [1, 0], [0, 0] ],
      [ [0, 1], [1, 1], [1, 0], [0, 0] ],
      [ [0, 1], [1, 1], [1, 0], [0, 0] ],
      [ [0, 1], [1, 1], [1, 0], [0, 0] ],
      [ [0, 1], [1, 1], [1, 0], [0, 0] ],
      [ [0, 1], [1, 1], [1, 0], [0, 0] ]
    ],
    uvmapper: {
            projectionMode: "cubic",
            scale: [1, 1, 1]
    }
  };
I am none too sure what "uv" represents, but there are six sides to a cube and there are six entries in the uv property. A quick bit of research (in other words, I looked it up on Wikipedia), turns up that UV mapping is the mapping done onto a projected space. So, on each of the faces of a cubic (with cubic projection), u and v are what x and y would be in normal 2d Cartesian space. At least that's what I think it is.

I am not sure what mucking with UV order would do. I rotate the first face's UV mapping:
  var mesh =
  {
    // ...
    uv: [
      [ [1, 0], [0, 0], [0, 1], [1, 1] ],
      [ [0, 1], [1, 1], [1, 0], [0, 0] ],
      [ [0, 1], [1, 1], [1, 0], [0, 0] ],
      [ [0, 1], [1, 1], [1, 0], [0, 0] ],
      [ [0, 1], [1, 1], [1, 0], [0, 0] ],
      [ [0, 1], [1, 1], [1, 0], [0, 0] ]
    ],
    // ...
  };
But that has no effect that I can discern:



Looking through the CubicVR documentation on Mesh it seems like I can set a color for each face point, but I cannot figure out why I would want to do that.

It seems, at least superficially, like there is more interesting stuff to be done in the material settings. Per the CubicVR.js documentation on Material, I ought to be able to add an image on each projection. So I grab an image from the CubicVR.js project:
wget https://github.com/cjcliffe/CubicVR.js/raw/master/samples/images/1422-diffuse.jpg
And add it to the material definition for my cubes:
        return {
          textures: {
            color: '/images/1422-diffuse.jpg'
          },
          opacity: 0.9
        };
With that, I get cool textured cubes spinning about:



I think this UV projection stuff is starting to make some sense. To be sure, I will probably continue with this tomorrow, possibly experimenting with other shapes.


Day #407

1 comment:

  1. I have no idea if this is the case, but from looking at the code, it seems like changing the order would change the orientation of your uv map. I'm assuming the range for each coordinate is between 0 and 1, and that [0,0] is top-left and [1,1] is bottom-right.

    You could check this by translating/scaling the coordinates to a half sized box, centered:

    var mesh =
    {
    // ...
    uv: [
    [ [0, 1], [1, 1], [1, 0], [0, 0] ],
    [ [0, 1], [1, 1], [1, 0], [0, 0] ],
    [ [0, 1], [1, 1], [1, 0], [0, 0] ],
    [ [0, 1], [1, 1], [1, 0], [0, 0] ],
    [ [0, 1], [1, 1], [1, 0], [0, 0] ],
    [ [0, 1], [1, 1], [1, 0], [0, 0] ]
    ],
    uvmapper: {
    projectionMode: "cubic",
    scale: [1, 1, 1]
    }
    };

    var mapped = mesh.uv.map(function(mappings) {
    return mappings.map(function(uv_pair) {
    return uv_pair.map(function(i) {
    return (i/2) + .25;
    });
    })
    });

    which yields the following for mapped:

    [ [ [ 0.25, 0.75 ], [ 0.75, 0.75 ], [ 0.75, 0.25 ], [ 0.25, 0.25 ] ],
    [ [ 0.25, 0.75 ], [ 0.75, 0.75 ], [ 0.75, 0.25 ], [ 0.25, 0.25 ] ],
    [ [ 0.25, 0.75 ], [ 0.75, 0.75 ], [ 0.75, 0.25 ], [ 0.25, 0.25 ] ],
    [ [ 0.25, 0.75 ], [ 0.75, 0.75 ], [ 0.75, 0.25 ], [ 0.25, 0.25 ] ],
    [ [ 0.25, 0.75 ], [ 0.75, 0.75 ], [ 0.75, 0.25 ], [ 0.25, 0.25 ] ],
    [ [ 0.25, 0.75 ], [ 0.75, 0.75 ], [ 0.75, 0.25 ], [ 0.25, 0.25 ] ] ]

    That should give you a better idea of what it's doing I'd think.

    I have no idea, but I'd guess that the first (original) code uv maps to [top-right, bottom-right, bottom-left, top-left]. So maybe your changes would map the uv to [bottom-left, top-left, top-right, bottom-right]? Essentially, you rotated the uv map 180 degrees? And since it looks like the "map" is just a blue material, you wouldn't notice it if it was rotated. It would probably be more apparent with the texture you looked at right before calling it a night.

    BUT... that's all pure speculation on my part.

    ReplyDelete