Skip to content
Browse files

merged with mod-conversion

  • Loading branch information...
2 parents 34d9213 + 6b13dde commit 7b0d44f2822e616dc98696972672b903830d5660 @cjcliffe committed
Sorry, we could not display the entire diff because it was too big.
View
13,081 CubicVR.js
114 additions, 12,967 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
10 HEADER
@@ -0,0 +1,10 @@
+/*
+ Javascript port of CubicVR 3D engine for WebGL
+ by Charles J. Cliffe
+ http://www.cubicvr.org/
+
+ May be used under the terms of the MIT license.
+ http://www.opensource.org/licenses/mit-license.php
+*/
+
+/*globals alert: false */
View
59 Makefile
@@ -2,15 +2,50 @@
CUBICVR := CubicVR
SRC_DIR := .
DIST_DIR := $(SRC_DIR)/dist
-CUBICVR_SRC := $(SRC_DIR)/$(CUBICVR).js
CUBICVR_DIST := $(DIST_DIR)/$(CUBICVR).js
CUBICVR_MIN := $(DIST_DIR)/$(CUBICVR).min.js
+CUBICVR_CORE := $(SRC_DIR)/CubicVR.js
CUBICVR_VS := $(SRC_DIR)/$(CUBICVR)_Core.vs
CUBICVR_FS := $(SRC_DIR)/$(CUBICVR)_Core.fs
TOOLS_DIR := $(SRC_DIR)/tools
TESTS_DIR := $(DIST_DIR)/tests
+SOURCE_DIR := $(SRC_DIR)/source
-compile = java -jar $(TOOLS_DIR)/closure/compiler.jar --js $(CUBICVR_DIST) \
+JS_SRCS := \
+ $(SOURCE_DIR)/CubicVR.COLLADA.js \
+ $(SOURCE_DIR)/CubicVR.CVRXML.js \
+ $(SOURCE_DIR)/CubicVR.Camera.js \
+ $(SOURCE_DIR)/CubicVR.GML.js \
+ $(SOURCE_DIR)/CubicVR.Landscape.js \
+ $(SOURCE_DIR)/CubicVR.Layout.js \
+ $(SOURCE_DIR)/CubicVR.Light.js \
+ $(SOURCE_DIR)/CubicVR.MainLoop.js \
+ $(SOURCE_DIR)/CubicVR.Material.js \
+ $(SOURCE_DIR)/CubicVR.Math.js \
+ $(SOURCE_DIR)/CubicVR.Mesh.js \
+ $(SOURCE_DIR)/CubicVR.Motion.js \
+ $(SOURCE_DIR)/CubicVR.Octree.js \
+ $(SOURCE_DIR)/CubicVR.Particles.js \
+ $(SOURCE_DIR)/CubicVR.PostProcess.js \
+ $(SOURCE_DIR)/CubicVR.Primitives.js \
+ $(SOURCE_DIR)/CubicVR.Renderer.js \
+ $(SOURCE_DIR)/CubicVR.Scene.js \
+ $(SOURCE_DIR)/CubicVR.Shader.js \
+ $(SOURCE_DIR)/CubicVR.Texture.js \
+ $(SOURCE_DIR)/CubicVR.UVMapper.js \
+ $(SOURCE_DIR)/CubicVR.Utility.js \
+ $(SOURCE_DIR)/CubicVR.Worker.js
+
+cutcore = ( python $(TOOLS_DIR)/cutter.py $(1) )
+
+addheader = @@cat $(SRC_DIR)/HEADER > $(DIST_DIR)/header.tmp && \
+ cat $(1) >> $(DIST_DIR)/header.tmp && \
+ rm -f $(1) && \
+ mv $(DIST_DIR)/header.tmp $(1)
+
+compile = java -jar $(TOOLS_DIR)/closure/compiler.jar \
+ --js $(CUBICVR_CORE) \
+ $(shell for js in $(JS_SRCS) ; do echo --js $$js ; done) \
--compilation_level SIMPLE_OPTIMIZATIONS \
--js_output_file $(1)
@@ -22,19 +57,25 @@ stringify = ( echo '/* Auto Embed $(2) */' ; \
all: $(DIST_DIR) $(CUBICVR_DIST) $(CUBICVR_MIN)
@@echo "Finished, see $(DIST_DIR)"
-$(DIST_DIR):
- @@echo "Creating $(DIST_DIR)"
- @@mkdir $(DIST_DIR)
-
-$(CUBICVR_DIST): $(DIST_DIR) $(CUBICVR_SRC)
+$(CUBICVR_DIST): $(DIST_DIR) $(JS_SRCS)
@@echo "Building $(CUBICVR_DIST)"
- @@cp $(CUBICVR_SRC) $(CUBICVR_DIST)
+ @@$(call cutcore, $(CUBICVR_CORE)) > $(CUBICVR_DIST)
+ @@cat $(JS_SRCS) >> $(CUBICVR_DIST)
+ @@$(call cutfile,$(CUBICVR_DIST))
@@$(call stringify,CubicVRCoreVS,$(CUBICVR_VS)) >> $(CUBICVR_DIST)
@@$(call stringify,CubicVRCoreFS,$(CUBICVR_FS)) >> $(CUBICVR_DIST)
+ @@$(call addheader,$(CUBICVR_DIST))
+
+$(DIST_DIR):
+ @@echo "Creating $(DIST_DIR)"
+ @@mkdir $(DIST_DIR)
-$(CUBICVR_MIN): $(DIST_DIR) $(CUBICVR_SRC) $(CUBICVR_DIST)
+$(CUBICVR_MIN): $(DIST_DIR) $(CUBICVR_DIST)
@@echo "Building $(CUBICVR_MIN)"
@@$(call compile,$(CUBICVR_MIN))
+ @@$(call addheader,$(CUBICVR_MIN))
+ @@$(call stringify,CubicVRCoreVS,$(CUBICVR_VS)) >> $(CUBICVR_MIN)
+ @@$(call stringify,CubicVRCoreFS,$(CUBICVR_FS)) >> $(CUBICVR_MIN)
tests: $(DIST_DIR) $(CUBICVR_MIN)
@@echo "Creating tests in $(TESTS_DIR)"
View
13 README.markdown
@@ -20,7 +20,9 @@ Javascript Port of the [CubicVR 3D Engine](http://www.cubicvr.org) by Charles J.
### Folders ###
- / -> core library (to be included as submodule)
+ / -> core library and shaders
+ /source -> source modules
+ /editor -> web-based 3D editor (work in progress)
/samples -> sample projects, useful as a starting point
/tests -> tests and prototypes for various core features
/lib -> external dependencies for any tests/examples
@@ -31,3 +33,12 @@ Javascript Port of the [CubicVR 3D Engine](http://www.cubicvr.org) by Charles J.
### Branches ###
master -> main branch
+
+### Building / Minification ###
+
+ To build the consolidated and minified versions of CubicVR.js simply run "make" in the repository root.
+
+ The resulting CubicVR.js and CubicVR.min.js builds with self-contained core shaders will be placed in dist/
+
+ Minification requires Python and Java to be installed, please review installation instructions for your platform.
+
View
0 collada.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
View
2 samples/basic/basic_primitives.html
@@ -130,4 +130,4 @@
<body onLoad="webGLStart();"></body>
-</html>
+</html>
View
71 samples/collada/wall_smash_cam_attach.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+
+ <head>
+ <title>
+ CubicVR.js: Using a COLLADA scene from a .dae file
+ </title>
+ <script src="../../CubicVR.js" type="text/javascript">
+ </script>
+ <script type='text/javascript'>
+ function webGLStart() {
+ // by default generate a full screen canvas with automatic resize
+ var gl = CubicVR.init();
+ var canvas = CubicVR.getCanvas();
+
+ if (!gl) {
+ alert("Sorry, no WebGL support.");
+ return;
+ };
+
+ // load the collada file, specify path for images
+ var scene = CubicVR.loadCollada("WallSmash/wall_smash.dae","WallSmash/");
+ scene.resize(canvas.width,canvas.height);
+// scene.camera.position = [20,20,-20]; // set our camera position
+// scene.camera.target = [0,5,-5]; // set our camera position
+ scene.camera.position = [0,1,3.5];
+ scene.camera.rotation = [0,0,0];
+ scene.camera.targeted = false;
+ scene.camera.setParent(scene.getSceneObject("Sphere"));
+ scene.camera.motion = null; // remove any camera motion
+ scene.lights = []; // clear the loaded lights
+
+ // Add a simple shadowed directional light
+ scene.bindLight(new CubicVR.Light({
+ type:CubicVR.enums.light.type.AREA,
+ distance:90,
+ areaCeiling:90,
+ specular:[1,1,1],
+ areaAxis:[-25,-10]
+ }));
+
+ CubicVR.setSoftShadows(true);
+
+ // Add our scene to the window resize list
+ CubicVR.addResizeable(scene);
+
+ // Use a basic envelope to loop/stretch the time
+ var looper = new CubicVR.Envelope({
+ in_behavior:CubicVR.enums.envelope.behavior.REPEAT,
+ out_behavior:CubicVR.enums.envelope.behavior.REPEAT
+ });
+ looper.addKey(0,0);
+ looper.addKey(10,10);
+ looper.addKey(15,0);
+
+ // Start our main drawing loop, it provides a timer and the gl context as parameters
+ CubicVR.MainLoop(function(timer, gl) {
+ scene.evaluate(looper.evaluate(timer.getSeconds()));
+ scene.updateShadows();
+ scene.render();
+ });
+
+ // initialize a mouse view controller
+ mvc = new CubicVR.MouseViewController(canvas, scene.camera);
+ }
+ </script>
+ </head>
+
+ <body onLoad="webGLStart();"></body>
+
+</html>
View
1,662 source/CubicVR.COLLADA.js
1,662 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
567 source/CubicVR.CVRXML.js
@@ -0,0 +1,567 @@
+
+CubicVR.RegisterModule("CVRXML",function(base) {
+
+ var undef = base.undef;
+ var nop = function(){ };
+ var enums = CubicVR.enums;
+ var GLCore = base.GLCore;
+
+ var MeshPool = [];
+
+
+ function cubicvr_isMotion(node) {
+ if (node === null) {
+ return false;
+ }
+
+ return (node.getElementsByTagName("x").length || node.getElementsByTagName("y").length || node.getElementsByTagName("z").length || node.getElementsByTagName("fov").length);
+ }
+
+
+ function cubicvr_nodeToMotion(node, controllerId, motion) {
+ var util = CubicVR.util;
+ var c = [];
+ c[0] = node.getElementsByTagName("x");
+ c[1] = node.getElementsByTagName("y");
+ c[2] = node.getElementsByTagName("z");
+ c[3] = node.getElementsByTagName("fov");
+
+ var etime, evalue, ein, eout, etcb;
+
+ for (var k in c) {
+ if (c.hasOwnProperty(k)) {
+ if (c[k] !== undef) {
+ if (c[k].length) {
+ etime = c[k][0].getElementsByTagName("time");
+ evalue = c[k][0].getElementsByTagName("value");
+ ein = c[k][0].getElementsByTagName("in");
+ eout = c[k][0].getElementsByTagName("out");
+ etcb = c[k][0].getElementsByTagName("tcb");
+
+ var time = null,
+ value = null,
+ tcb = null;
+
+ var intype = null,
+ outtype = null;
+
+ if (ein.length) {
+ intype = util.collectTextNode(ein[0]);
+ }
+
+ if (eout.length) {
+ outtype = util.collectTextNode(eout[0]);
+ }
+
+ if (etime.length) {
+ time = util.floatDelimArray(util.collectTextNode(etime[0]), " ");
+ }
+
+ if (evalue.length) {
+ value = util.floatDelimArray(util.collectTextNode(evalue[0]), " ");
+ }
+
+ if (etcb.length) {
+ tcb = util.floatDelimArray(util.collectTextNode(etcb[0]), " ");
+ }
+
+
+ if (time !== null && value !== null) {
+ for (var i = 0, iMax = time.length; i < iMax; i++) {
+ var mkey = motion.setKey(controllerId, k, time[i], value[i]);
+
+ if (tcb) {
+ mkey.tension = tcb[i * 3];
+ mkey.continuity = tcb[i * 3 + 1];
+ mkey.bias = tcb[i * 3 + 2];
+ }
+ }
+ }
+
+ var in_beh = enums.envelope.behavior.CONSTANT;
+ var out_beh = enums.envelope.behavior.CONSTANT;
+
+ if (intype) {
+ switch (intype) {
+ case "reset":
+ in_beh = enums.envelope.behavior.RESET;
+ break;
+ case "constant":
+ in_beh = enums.envelope.behavior.CONSTANT;
+ break;
+ case "repeat":
+ in_beh = enums.envelope.behavior.REPEAT;
+ break;
+ case "oscillate":
+ in_beh = enums.envelope.behavior.OSCILLATE;
+ break;
+ case "offset":
+ in_beh = enums.envelope.behavior.OFFSET;
+ break;
+ case "linear":
+ in_beh = enums.envelope.behavior.LINEAR;
+ break;
+ }
+ }
+
+ if (outtype) {
+ switch (outtype) {
+ case "reset":
+ out_beh = enums.envelope.behavior.RESET;
+ break;
+ case "constant":
+ out_beh = enums.envelope.behavior.CONSTANT;
+ break;
+ case "repeat":
+ out_beh = enums.envelope.behavior.REPEAT;
+ break;
+ case "oscillate":
+ out_beh = enums.envelope.behavior.OSCILLATE;
+ break;
+ case "offset":
+ out_beh = enums.envelope.behavior.OFFSET;
+ break;
+ case "linear":
+ out_beh = enums.envelope.behavior.LINEAR;
+ break;
+ }
+ }
+
+ motion.setBehavior(controllerId, k, in_beh, out_beh);
+ }
+ }
+ }
+ }
+ }
+
+ function cubicvr_loadMesh(meshUrl, prefix) {
+ if (MeshPool[meshUrl] !== undef) {
+ return MeshPool[meshUrl];
+ }
+
+ var util = CubicVR.util;
+
+ var i, j, p, iMax, jMax, pMax;
+
+ var obj = new CubicVR.Mesh();
+ var mesh = util.getXML(meshUrl);
+ var pts_elem = mesh.getElementsByTagName("points");
+
+ var pts_str = util.collectTextNode(pts_elem[0]);
+ var pts = pts_str.split(" ");
+
+ var texName, tex;
+
+ for (i = 0, iMax = pts.length; i < iMax; i++) {
+ pts[i] = pts[i].split(",");
+ for (j = 0, jMax = pts[i].length; j < jMax; j++) {
+ pts[i][j] = parseFloat(pts[i][j]);
+ }
+ }
+
+ obj.addPoint(pts);
+
+ var material_elem = mesh.getElementsByTagName("material");
+ var mappers = [];
+
+
+ for (i = 0, iMax = material_elem.length; i < iMax; i++) {
+ var melem = material_elem[i];
+
+ var matName = (melem.getElementsByTagName("name").length) ? (melem.getElementsByTagName("name")[0].firstChild.nodeValue) : null;
+ var mat = new CubicVR.Material(matName);
+
+ if (melem.getElementsByTagName("alpha").length) {
+ mat.opacity = parseFloat(melem.getElementsByTagName("alpha")[0].firstChild.nodeValue);
+ }
+ if (melem.getElementsByTagName("shininess").length) {
+ mat.shininess = (parseFloat(melem.getElementsByTagName("shininess")[0].firstChild.nodeValue) / 100.0);
+ }
+ if (melem.getElementsByTagName("max_smooth").length) {
+ mat.max_smooth = parseFloat(melem.getElementsByTagName("max_smooth")[0].firstChild.nodeValue);
+ }
+
+ if (melem.getElementsByTagName("color").length) {
+ mat.color = util.floatDelimArray(melem.getElementsByTagName("color")[0].firstChild.nodeValue);
+ }
+ if (melem.getElementsByTagName("ambient").length) {
+ mat.ambient = util.floatDelimArray(melem.getElementsByTagName("ambient")[0].firstChild.nodeValue);
+ }
+ if (melem.getElementsByTagName("diffuse").length) {
+ mat.diffuse = util.floatDelimArray(melem.getElementsByTagName("diffuse")[0].firstChild.nodeValue);
+ }
+ if (melem.getElementsByTagName("specular").length) {
+ mat.specular = util.floatDelimArray(melem.getElementsByTagName("specular")[0].firstChild.nodeValue);
+ }
+ if (melem.getElementsByTagName("texture").length) {
+ texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture")[0].firstChild.nodeValue;
+ tex = (base.Textures_ref[texName] !== undef) ? base.Textures_obj[base.Textures_ref[texName]] : (new CubicVR.Texture(texName));
+ mat.setTexture(tex, enums.texture.map.COLOR);
+ }
+
+ if (melem.getElementsByTagName("texture_luminosity").length) {
+ texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_luminosity")[0].firstChild.nodeValue;
+ tex = (base.Textures_ref[texName] !== undef) ? base.Textures_obj[base.Textures_ref[texName]] : (new CubicVR.Texture(texName));
+ mat.setTexture(tex, enums.texture.map.AMBIENT);
+ }
+
+ if (melem.getElementsByTagName("texture_normal").length) {
+ texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_normal")[0].firstChild.nodeValue;
+ tex = (base.Textures_ref[texName] !== undef) ? base.Textures_obj[base.Textures_ref[texName]] : (new CubicVR.Texture(texName));
+ mat.setTexture(tex, enums.texture.map.NORMAL);
+ }
+
+ if (melem.getElementsByTagName("texture_specular").length) {
+ texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_specular")[0].firstChild.nodeValue;
+ tex = (base.Textures_ref[texName] !== undef) ? base.Textures_obj[base.Textures_ref[texName]] : (new CubicVR.Texture(texName));
+ mat.setTexture(tex, enums.texture.map.SPECULAR);
+ }
+
+ if (melem.getElementsByTagName("texture_bump").length) {
+ texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_bump")[0].firstChild.nodeValue;
+ tex = (base.Textures_ref[texName] !== undef) ? base.Textures_obj[base.Textures_ref[texName]] : (new CubicVR.Texture(texName));
+ mat.setTexture(tex, enums.texture.map.BUMP);
+ }
+
+ if (melem.getElementsByTagName("texture_envsphere").length) {
+ texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_envsphere")[0].firstChild.nodeValue;
+ tex = (base.Textures_ref[texName] !== undef) ? base.Textures_obj[base.Textures_ref[texName]] : (new CubicVR.Texture(texName));
+ mat.setTexture(tex, enums.texture.map.ENVSPHERE);
+ }
+
+ if (melem.getElementsByTagName("texture_alpha").length) {
+ texName = (prefix ? prefix : "") + melem.getElementsByTagName("texture_alpha")[0].firstChild.nodeValue;
+ tex = (base.Textures_ref[texName] !== undef) ? base.Textures_obj[base.Textures_ref[texName]] : (new CubicVR.Texture(texName));
+ mat.setTexture(tex, enums.texture.map.ALPHA);
+ }
+
+ var uvSet = null;
+
+ if (melem.getElementsByTagName("uvmapper").length) {
+ var uvm = new CubicVR.UVMapper();
+ var uvelem = melem.getElementsByTagName("uvmapper")[0];
+ var uvmType = "";
+
+ if (uvelem.getElementsByTagName("type").length) {
+ uvmType = melem.getElementsByTagName("type")[0].firstChild.nodeValue;
+
+ switch (uvmType) {
+ case "uv":
+ break;
+ case "planar":
+ uvm.projection_mode = enums.uv.projection.PLANAR;
+ break;
+ case "cylindrical":
+ uvm.projection_mode = enums.uv.projection.CYLINDRICAL;
+ break;
+ case "spherical":
+ uvm.projection_mode = enums.uv.projection.SPHERICAL;
+ break;
+ case "cubic":
+ uvm.projection_mode = enums.uv.projection.CUBIC;
+ break;
+ }
+ }
+
+ if (uvmType === "uv") {
+ if (uvelem.getElementsByTagName("uv").length) {
+ var uvText = util.collectTextNode(melem.getElementsByTagName("uv")[0]);
+
+ uvSet = uvText.split(" ");
+
+ for (j = 0, jMax = uvSet.length; j < jMax; j++) {
+ uvSet[j] = util.floatDelimArray(uvSet[j]);
+ }
+ }
+ }
+
+ if (uvelem.getElementsByTagName("axis").length) {
+ var uvmAxis = melem.getElementsByTagName("axis")[0].firstChild.nodeValue;
+
+ switch (uvmAxis) {
+ case "x":
+ uvm.projection_axis = enums.uv.axis.X;
+ break;
+ case "y":
+ uvm.projection_axis = enums.uv.axis.Y;
+ break;
+ case "z":
+ uvm.projection_axis = enums.uv.axis.Z;
+ break;
+ }
+
+ }
+
+ if (melem.getElementsByTagName("center").length) {
+ uvm.center = util.floatDelimArray(melem.getElementsByTagName("center")[0].firstChild.nodeValue);
+ }
+ if (melem.getElementsByTagName("rotation").length) {
+ uvm.rotation = util.floatDelimArray(melem.getElementsByTagName("rotation")[0].firstChild.nodeValue);
+ }
+ if (melem.getElementsByTagName("scale").length) {
+ uvm.scale = util.floatDelimArray(melem.getElementsByTagName("scale")[0].firstChild.nodeValue);
+ }
+
+ if (uvmType !== "" && uvmType !== "uv") {
+ mappers.push([uvm, mat]);
+ }
+ }
+
+
+ var seglist = null;
+ var triangles = null;
+
+ if (melem.getElementsByTagName("segments").length) {
+ seglist = util.intDelimArray(util.collectTextNode(melem.getElementsByTagName("segments")[0]), " ");
+ }
+ if (melem.getElementsByTagName("triangles").length) {
+ triangles = util.intDelimArray(util.collectTextNode(melem.getElementsByTagName("triangles")[0]), " ");
+ }
+
+
+ if (seglist === null) {
+ seglist = [0, parseInt((triangles.length) / 3, 10)];
+ }
+
+ var ofs = 0;
+
+ obj.setFaceMaterial(mat);
+
+ if (triangles.length) {
+ for (p = 0, pMax = seglist.length; p < pMax; p += 2) {
+ var currentSegment = seglist[p];
+ var totalPts = seglist[p + 1] * 3;
+
+ obj.setSegment(currentSegment);
+
+ for (j = ofs, jMax = ofs + totalPts; j < jMax; j += 3) {
+ var newFace = obj.addFace([triangles[j], triangles[j + 1], triangles[j + 2]]);
+ if (uvSet) {
+ obj.faces[newFace].setUV([uvSet[j], uvSet[j + 1], uvSet[j + 2]]);
+ }
+ }
+
+ ofs += totalPts;
+ }
+ }
+ }
+
+ obj.calcNormals();
+
+ for (i = 0, iMax = mappers.length; i < iMax; i++) {
+ mappers[i][0].apply(obj, mappers[i][1]);
+ }
+
+ obj.compile();
+
+ MeshPool[meshUrl] = obj;
+
+ return obj;
+ }
+
+
+
+
+
+
+
+ function cubicvr_loadScene(sceneUrl, model_prefix, image_prefix) {
+ var util = CubicVR.util;
+ if (model_prefix === undef) {
+ model_prefix = "";
+ }
+ if (image_prefix === undef) {
+ image_prefix = "";
+ }
+
+ var obj = new CubicVR.Mesh();
+ var scene = util.getXML(sceneUrl);
+
+ var sceneOut = new CubicVR.Scene();
+
+ var parentingSet = [];
+
+ var sceneobjs = scene.getElementsByTagName("sceneobjects");
+
+ var tempNode;
+
+ var position, rotation, scale;
+
+ // var pts_str = util.collectTextNode(pts_elem[0]);
+ for (var i = 0, iMax = sceneobjs[0].childNodes.length; i < iMax; i++) {
+ var sobj = sceneobjs[0].childNodes[i];
+
+ if (sobj.tagName === "sceneobject") {
+
+ var name = "unnamed";
+ var parent = "";
+ var model = "";
+
+ tempNode = sobj.getElementsByTagName("name");
+ if (tempNode.length) {
+ name = util.collectTextNode(tempNode[0]);
+ }
+
+ tempNode = sobj.getElementsByTagName("parent");
+ if (tempNode.length) {
+ parent = util.collectTextNode(tempNode[0]);
+ }
+
+ tempNode = sobj.getElementsByTagName("model");
+ if (tempNode.length) {
+ model = util.collectTextNode(tempNode[0]);
+ }
+
+ position = null;
+ rotation = null;
+ scale = null;
+
+ tempNode = sobj.getElementsByTagName("position");
+ if (tempNode.length) {
+ position = tempNode[0];
+ }
+
+ tempNode = sobj.getElementsByTagName("rotation");
+ if (tempNode.length) {
+ rotation = tempNode[0];
+ }
+
+ tempNode = sobj.getElementsByTagName("scale");
+ if (tempNode.length) {
+ scale = tempNode[0];
+ }
+
+ obj = null;
+
+ if (model !== "") {
+ obj = cubicvr_loadMesh(model_prefix + model, image_prefix);
+ }
+
+ var sceneObject = new CubicVR.SceneObject(obj, name);
+
+ if (cubicvr_isMotion(position)) {
+ if (!sceneObject.motion) {
+ sceneObject.motion = new CubicVR.Motion();
+ }
+ cubicvr_nodeToMotion(position, enums.motion.POS, sceneObject.motion);
+ } else if (position) {
+ sceneObject.position = util.floatDelimArray(util.collectTextNode(position));
+ }
+
+ if (cubicvr_isMotion(rotation)) {
+ if (!sceneObject.motion) {
+ sceneObject.motion = new CubicVR.Motion();
+ }
+ cubicvr_nodeToMotion(rotation, enums.motion.ROT, sceneObject.motion);
+ } else {
+ sceneObject.rotation = util.floatDelimArray(util.collectTextNode(rotation));
+ }
+
+ if (cubicvr_isMotion(scale)) {
+ if (!sceneObject.motion) {
+ sceneObject.motion = new CubicVR.Motion();
+ }
+ cubicvr_nodeToMotion(scale, enums.motion.SCL, sceneObject.motion);
+ } else {
+ sceneObject.scale = util.floatDelimArray(util.collectTextNode(scale));
+
+ }
+
+ sceneOut.bindSceneObject(sceneObject);
+
+ if (parent !== "") {
+ parentingSet.push([sceneObject, parent]);
+ }
+ }
+ }
+
+ for (var j in parentingSet) {
+ if (parentingSet.hasOwnProperty(j)) {
+ sceneOut.getSceneObject(parentingSet[j][1]).bindChild(parentingSet[j][0]);
+ }
+ }
+
+ var camera = scene.getElementsByTagName("camera");
+
+ if (camera.length) {
+ position = null;
+ rotation = null;
+
+ var target = "";
+
+ tempNode = camera[0].getElementsByTagName("name");
+
+ var cam = sceneOut.camera;
+
+ var fov = null;
+
+ if (tempNode.length) {
+ target = tempNode[0].firstChild.nodeValue;
+ }
+
+ tempNode = camera[0].getElementsByTagName("target");
+ if (tempNode.length) {
+ target = tempNode[0].firstChild.nodeValue;
+ }
+
+ if (target !== "") {
+ cam.targetSceneObject = sceneOut.getSceneObject(target);
+ }
+
+ tempNode = camera[0].getElementsByTagName("position");
+ if (tempNode.length) {
+ position = tempNode[0];
+ }
+
+ tempNode = camera[0].getElementsByTagName("rotation");
+ if (tempNode.length) {
+ rotation = tempNode[0];
+ }
+
+ tempNode = camera[0].getElementsByTagName("fov");
+ if (tempNode.length) {
+ fov = tempNode[0];
+ }
+
+ if (cubicvr_isMotion(position)) {
+ if (!cam.motion) {
+ cam.motion = new CubicVR.Motion();
+ }
+ cubicvr_nodeToMotion(position, enums.motion.POS, cam.motion);
+ } else if (position) {
+ cam.position = util.floatDelimArray(position.firstChild.nodeValue);
+ }
+
+ if (cubicvr_isMotion(rotation)) {
+ if (!cam.motion) {
+ cam.motion = new CubicVR.Motion();
+ }
+ cubicvr_nodeToMotion(rotation, enums.motion.ROT, cam.motion);
+ } else if (rotation) {
+ cam.rotation = util.floatDelimArray(rotation.firstChild.nodeValue);
+ }
+
+ if (cubicvr_isMotion(fov)) {
+ if (!cam.motion) {
+ cam.motion = new CubicVR.Motion();
+ }
+ cubicvr_nodeToMotion(fov, enums.motion.FOV, cam.motion);
+ } else if (fov) {
+ cam.fov = parseFloat(fov.firstChild.nodeValue);
+ }
+
+ }
+
+
+ return sceneOut;
+ }
+
+
+ var exports = {
+ loadMesh: cubicvr_loadMesh,
+ loadScene: cubicvr_loadScene
+ };
+
+ return exports;
+
+});
View
374 source/CubicVR.Camera.js
@@ -0,0 +1,374 @@
+CubicVR.RegisterModule("Camera", function (base) {
+
+ var undef = base.undef;
+ var enums = CubicVR.enums;
+ var GLCore = base.GLCore;
+ var mat4 = CubicVR.mat4;
+
+
+ var cubicvr_identity = [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0];
+
+
+ function Camera(width, height, fov, nearclip, farclip) {
+ this.frustum = new CubicVR.Frustum();
+
+ if (typeof (width) == 'object') {
+ this.position = width.position ? width.position : [0, 0, 0];
+ this.rotation = width.rotation ? width.rotation : [0, 0, 0];
+ this.target = width.target ? width.target : [0, 0, 0];
+ this.fov = width.fov ? width.fov : 60.0;
+ this.nearclip = width.nearclip ? width.nearclip : 0.1;
+ this.farclip = width.farclip ? width.farclip : 400.0;
+ this.targeted = width.targeted ? width.targeted : true;
+ this.calc_nmatrix = width.calcNormalMatrix ? width.calcNormalMatrix : true;
+
+ height = width.height ? width.height : undef;
+ width = width.width ? width.width : undef;
+ } else {
+ this.position = [0, 0, 0];
+ this.rotation = [0, 0, 0];
+ this.target = [0, 0, 0];
+ this.fov = (fov !== undef) ? fov : 60.0;
+ this.nearclip = (nearclip !== undef) ? nearclip : 0.1;
+ this.farclip = (farclip !== undef) ? farclip : 400.0;
+ this.targeted = true;
+ this.calc_nmatrix = true;
+ }
+
+ this.targetSceneObject = null;
+ this.motion = null;
+ this.transform = new CubicVR.Transform();
+
+ this.manual = false;
+
+ this.setDimensions((width !== undef) ? width : 512, (height !== undef) ? height : 512);
+
+ this.mvMatrix = mat4.identity();
+ this.pMatrix = null;
+ this.calcProjection();
+
+ this.ortho = false;
+ this.ortho_view = {
+ left: -1,
+ right: 1,
+ bottom: -1,
+ top: 1
+ };
+ this.parent = null;
+ }
+
+ Camera.prototype = {
+ setParent: function(camParent) {
+ this.parent = camParent;
+ },
+
+ setOrtho: function (left, right, bottom, top) {
+ this.ortho = true;
+ this.ortho_view.left = left;
+ this.ortho_view.right = right;
+ this.ortho_view.bottom = bottom;
+ this.ortho_view.top = top;
+ },
+
+ control: function (controllerId, motionId, value) {
+ if (controllerId === enums.motion.ROT) {
+ this.rotation[motionId] = value;
+ } else if (controllerId === enums.motion.POS) {
+ this.position[motionId] = value;
+ } else if (controllerId === enums.motion.FOV) {
+ this.setFOV(value);
+ } else if (controllerId === enums.motion.LENS) {
+ this.setLENS(value);
+ } else if (controllerId === enums.motion.NEARCLIP) {
+ this.setClip(value, this.farclip);
+ } else if (controllerId === enums.motion.FARCLIP) {
+ this.setClip(this.nearclip, value);
+ }
+ },
+
+ makeFrustum: function (left, right, bottom, top, zNear, zFar) {
+ var A = (right + left) / (right - left);
+ var B = (top + bottom) / (top - bottom);
+ var C = -(zFar + zNear) / (zFar - zNear);
+ var D = -2.0 * zFar * zNear / (zFar - zNear);
+
+ return [2.0 * zNear / (right - left), 0.0, 0.0, 0.0, 0.0, 2.0 * zNear / (top - bottom), 0.0, 0.0, A, B, C, -1.0, 0.0, 0.0, D, 0.0];
+ },
+
+
+ setTargeted: function (targeted) {
+ this.targeted = targeted;
+ },
+
+ calcProjection: function () {
+ var mat4 = CubicVR.mat4;
+ var mat3 = CubicVR.mat3;
+ var vec3 = CubicVR.vec3;
+ var gl = GLCore.gl;
+
+ if (this.ortho) {
+ this.pMatrix = mat4.ortho(this.ortho_view.left, this.ortho_view.right, this.ortho_view.bottom, this.ortho_view.top, this.nearclip, this.farclip);
+ } else {
+ this.pMatrix = mat4.perspective(this.fov, this.aspect, this.nearclip, this.farclip);
+ }
+
+ if (!this.targeted) {
+ mat4.identity(this.mvMatrix);
+
+ mat4.rotate(-this.rotation[0],-this.rotation[1],-this.rotation[2], this.mvMatrix);
+ mat4.translate(-this.position[0], -this.position[1], -this.position[2], this.mvMatrix);
+
+ if (this.parent !== null) {
+ mat4.multiply(this.mvMatrix.slice(0),mat4.inverse(this.parent.tMatrix),this.mvMatrix);
+ }
+
+ if (this.calc_nmatrix) {
+ this.nMatrix = mat4.inverse_mat3(this.mvMatrix);
+ mat3.transpose_inline(this.nMatrix);
+ } else {
+ mat4.identity(this.nMatrix);
+ }
+ }
+
+ this.frustum.extract(this, this.mvMatrix, this.pMatrix);
+ },
+
+ setClip: function (nearclip, farclip) {
+ this.nearclip = nearclip;
+ this.farclip = farclip;
+ this.calcProjection();
+ },
+
+ setDimensions: function (width, height) {
+ this.width = width;
+ this.height = height;
+
+ this.aspect = width / height;
+ this.calcProjection();
+ },
+
+ resize: function (width, height) {
+ this.setDimensions(width, height);
+ },
+
+ setFOV: function (fov) {
+ this.fov = fov;
+ this.ortho = false;
+ this.calcProjection();
+ },
+
+ setLENS: function (lens) {
+ this.setFOV(2.0 * Math.atan(16.0 / lens) * (180.0 / Math.PI));
+ },
+
+ lookat: function (eyeX, eyeY, eyeZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ) {
+ var mat4 = CubicVR.mat4;
+ var mat3 = CubicVR.mat3;
+
+ if (typeof (eyeX) == 'object') {
+ this.lookat(this.position[0], this.position[1], this.position[2], eyeX[0], eyeX[1], eyeX[2], 0, 1, 0);
+ return;
+ }
+
+ this.mvMatrix = mat4.lookat(eyeX, eyeY, eyeZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ);
+
+ if (this.rotation[2]) {
+ this.transform.clearStack();
+ this.transform.rotate(-this.rotation[2], 0, 0, 1);
+ this.transform.pushMatrix(this.mvMatrix);
+ this.mvMatrix = this.transform.getResult();
+ }
+
+ if (this.calc_nmatrix) {
+ this.nMatrix = mat4.inverse_mat3(this.mvMatrix);
+ mat3.transpose_inline(this.nMatrix);
+ } else {
+ this.nMatrix = cubicvr_identity;
+ }
+
+ this.frustum.extract(this, this.mvMatrix, this.pMatrix);
+ },
+
+ unProject: function (winx, winy, winz) {
+ var mat4 = CubicVR.mat4;
+
+ // var tmpClip = this.nearclip;
+ // if (tmpClip < 1.0) { this.nearclip = 1.0; this.calcProjection(); }
+ var viewport = [0, 0, this.width, this.height];
+
+ if (winz === undef) winz = this.farclip;
+
+ var p = [(((winx - viewport[0]) / (viewport[2])) * 2) - 1, -((((winy - viewport[1]) / (viewport[3])) * 2) - 1), (winz - this.nearclip) / (this.farclip - this.nearclip), 1.0];
+
+ var invp = mat4.vec4_multiply(mat4.vec4_multiply(p, mat4.inverse(this.pMatrix)), mat4.inverse(this.mvMatrix));
+
+ // if (tmpClip < 1.0) { this.nearclip = tmpClip; this.calcProjection(); }
+ return [invp[0] / invp[3], invp[1] / invp[3], invp[2] / invp[3]];
+ },
+
+ project: function (objx, objy, objz) {
+ var mat4 = CubicVR.mat4;
+
+ var p = [objx, objy, objz, 1.0];
+
+ var mp = mat4.vec4_multiply(mat4.vec4_multiply(p, this.mvMatrix), this.pMatrix);
+
+ return [((mp[0] / mp[3] + 1.0) / 2.0) * this.width, ((-mp[1] / mp[3] + 1.0) / 2.0) * this.height, ((mp[2] / mp[3])) * (this.farclip - this.nearclip) + this.nearclip];
+ }
+ }
+
+
+ /*** Auto-Cam Prototype ***/
+
+ function AutoCameraNode(pos) {
+ this.position = (pos !== undef) ? pos : [0, 0, 0];
+ }
+
+ AutoCameraNode.prototype = {
+ control: function (controllerId, motionId, value) {
+ if (controllerId === enums.motion.POS) {
+ this.position[motionId] = value;
+ }
+ }
+ }
+
+ function AutoCamera(start_position, target, bounds) {
+ this.camPath = new CubicVR.Motion();
+ this.targetPath = new CubicVR.Motion();
+
+ this.start_position = (start_position !== undef) ? start_position : [8, 8, 8];
+ this.target = (target !== undef) ? target : [0, 0, 0];
+
+ this.bounds = (bounds !== undef) ? bounds : [
+ [-15, 3, -15],
+ [15, 20, 15]
+ ];
+
+ this.safe_bb = [];
+ this.avoid_sphere = [];
+
+ this.segment_time = 3.0;
+ this.buffer_time = 20.0;
+ this.start_time = 0.0;
+ this.current_time = 0.0;
+
+ this.path_time = 0.0;
+ this.path_length = 0;
+
+ this.min_distance = 2.0;
+ this.max_distance = 40.0;
+
+ this.angle_min = 40;
+ this.angle_max = 180;
+ }
+
+
+ AutoCamera.prototype = {
+
+ inBounds: function (pt) {
+ var vec3 = CubicVR.vec3;
+ if (!(pt[0] > this.bounds[0][0] && pt[1] > this.bounds[0][1] && pt[2] > this.bounds[0][2] && pt[0] < this.bounds[1][0] && pt[1] < this.bounds[1][1] && pt[2] < this.bounds[1][2])) {
+ return false;
+ }
+
+ for (var i = 0, iMax = this.avoid_sphere.length; i < iMax; i++) {
+ var l = vec3.length(pt, this.avoid_sphere[i][0]);
+ if (l < this.avoid_sphere[i][1]) {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ findNextNode: function (aNode, bNode) {
+ var vec3 = CubicVR.vec3;
+ var d = [this.bounds[1][0] - this.bounds[0][0], this.bounds[1][1] - this.bounds[0][1], this.bounds[1][2] - this.bounds[0][2]];
+
+ var nextNodePos = [0, 0, 0];
+ var randVector = [0, 0, 0];
+ var l = 0.0;
+ var loopkill = 0;
+ var valid = false;
+
+ do {
+ randVector[0] = Math.random() - 0.5;
+ randVector[1] = Math.random() - 0.5;
+ randVector[2] = Math.random() - 0.5;
+
+ randVector = vec3.normalize(randVector);
+
+ var r = Math.random();
+
+ l = (r * (this.max_distance - this.min_distance)) + this.min_distance;
+
+ nextNodePos = vec3.add(bNode.position, vec3.multiply(randVector, l));
+
+ valid = this.inBounds(nextNodePos);
+
+ loopkill++;
+
+ if (loopkill > 30) {
+ nextNodePos = bNode.position;
+ break;
+ }
+ } while (!valid);
+
+ return nextNodePos;
+ },
+
+ run: function (timer) {
+ this.current_time = timer;
+
+ if (this.path_time === 0.0) {
+ this.path_time = this.current_time;
+
+ this.camPath.setKey(enums.motion.POS, enums.motion.X, this.path_time, this.start_position[0]);
+ this.camPath.setKey(enums.motion.POS, enums.motion.Y, this.path_time, this.start_position[1]);
+ this.camPath.setKey(enums.motion.POS, enums.motion.Z, this.path_time, this.start_position[2]);
+ }
+
+ while (this.path_time < this.current_time + this.buffer_time) {
+ this.path_time += this.segment_time;
+
+ var tmpNodeA = new AutoCameraNode();
+ var tmpNodeB = new AutoCameraNode();
+
+ if (this.path_length) {
+ this.camPath.apply(this.path_time - (this.segment_time * 2.0), tmpNodeA);
+ }
+
+ this.camPath.apply(this.path_time - this.segment_time, tmpNodeB);
+
+ var nextPos = this.findNextNode(tmpNodeA, tmpNodeB);
+
+ this.camPath.setKey(enums.motion.POS, enums.motion.X, this.path_time, nextPos[0]);
+ this.camPath.setKey(enums.motion.POS, enums.motion.Y, this.path_time, nextPos[1]);
+ this.camPath.setKey(enums.motion.POS, enums.motion.Z, this.path_time, nextPos[2]);
+
+ this.path_length++;
+ }
+
+ var tmpNodeC = new AutoCameraNode();
+
+ this.camPath.apply(timer, tmpNodeC);
+
+ return tmpNodeC.position;
+ },
+
+ addSafeBound: function (min, max) {
+ this.safe_bb.push([min, max]);
+ },
+
+ addAvoidSphere: function (center, radius) {
+ this.avoid_sphere.push([center, radius]);
+ }
+ }
+
+ var exports = {
+ Camera: Camera,
+ AutoCamera: AutoCamera
+ };
+
+ return exports;
+});
View
377 source/CubicVR.GML.js
@@ -0,0 +1,377 @@
+CubicVR.RegisterModule("GML", function (base) {
+
+ var undef = base.undef;
+ var GLCore = base.GLCore;
+ var enums = CubicVR.enums;
+
+ function GML(srcUrl) {
+ var util = CubicVR.util;
+ this.strokes = [];
+ this.bounds = [1, 1, 1];
+ this.origin = [0, 0, 0];
+ this.upvector = [0, 1, 0];
+ this.viewvector = [0, 0, 1];
+ this.manual_pos = 0;
+
+ if (srcUrl === undef) {
+ return;
+ }
+
+ var gml = util.getXML(srcUrl);
+
+ var gml_header = gml.getElementsByTagName("header");
+
+ if (!gml_header.length) {
+ return null;
+ }
+
+ var header = gml_header[0];
+
+ var gml_environment = gml.getElementsByTagName("environment");
+
+
+ if (!gml_environment.length) {
+ return null;
+ }
+
+ this.name = null;
+
+ var gml_name = header.getElementsByTagName("name");
+
+ if (gml_name.length) {
+ this.name = util.collectTextNode(gml_name[0]);
+ }
+
+ var gml_screenbounds = gml_environment[0].getElementsByTagName("screenBounds");
+
+ if (gml_screenbounds.length) {
+ this.bounds = [
+ parseFloat(util.collectTextNode(gml_screenbounds[0].getElementsByTagName("x")[0])), parseFloat(util.collectTextNode(gml_screenbounds[0].getElementsByTagName("y")[0])), parseFloat(util.collectTextNode(gml_screenbounds[0].getElementsByTagName("z")[0]))];
+ }
+
+ var gml_origin = gml_environment[0].getElementsByTagName("origin");
+
+ if (gml_origin.length) {
+ this.origin = [
+ parseFloat(util.collectTextNode(gml_origin[0].getElementsByTagName("x")[0])), parseFloat(util.collectTextNode(gml_origin[0].getElementsByTagName("y")[0])), parseFloat(util.collectTextNode(gml_origin[0].getElementsByTagName("z")[0]))];
+ }
+
+ var gml_upvector = gml_environment[0].getElementsByTagName("up");
+
+ if (gml_upvector.length) {
+ this.upvector = [
+ parseFloat(util.collectTextNode(gml_upvector[0].getElementsByTagName("x")[0])), parseFloat(util.collectTextNode(gml_upvector[0].getElementsByTagName("y")[0])), parseFloat(util.collectTextNode(gml_upvector[0].getElementsByTagName("z")[0]))];
+ }
+
+ var gml_drawings = gml.getElementsByTagName("drawing");
+
+ var drawings = [];
+
+ for (var dCount = 0, dMax = gml_drawings.length; dCount < dMax; dCount++) {
+ var drawing = gml_drawings[dCount];
+ var gml_strokes = drawing.getElementsByTagName("stroke");
+
+ var xm = 0,
+ ym = 0,
+ zm = 0,
+ tm = 0;
+
+ for (var sCount = 0, sMax = gml_strokes.length; sCount < sMax; sCount++) {
+ var gml_stroke = gml_strokes[sCount];
+ var gml_points = gml_stroke.getElementsByTagName("pt");
+ var plen = gml_points.length;
+
+ var points = new Array(plen);
+ var px, py, pz, pt;
+
+ for (var pCount = 0, pMax = plen; pCount < pMax; pCount++) {
+ var gml_point = gml_points[pCount];
+
+ px = parseFloat(util.collectTextNode(gml_point.getElementsByTagName("x")[0]));
+ py = parseFloat(util.collectTextNode(gml_point.getElementsByTagName("y")[0]));
+ pz = parseFloat(util.collectTextNode(gml_point.getElementsByTagName("z")[0]));
+ pt = parseFloat(util.collectTextNode(gml_point.getElementsByTagName("time")[0]));
+
+ if (this.upvector[0] === 1) {
+ points[pCount] = [(py !== py) ? 0 : py, (px !== px) ? 0 : -px, (pz !== pz) ? 0 : pz, pt];
+ } else if (this.upvector[1] === 1) {
+ points[pCount] = [(px !== px) ? 0 : px, (py !== py) ? 0 : py, (pz !== pz) ? 0 : pz, pt];
+ } else if (this.upvector[2] === 1) {
+ points[pCount] = [(px !== px) ? 0 : px, (pz !== pz) ? 0 : -pz, (py !== py) ? 0 : py, pt];
+ }
+
+ if (xm < px) {
+ xm = px;
+ }
+ if (ym < py) {
+ ym = py;
+ }
+ if (zm < pz) {
+ zm = pz;
+ }
+ if (tm < pt) {
+ tm = pt;
+ }
+ }
+
+ if (zm > tm) { // fix swapped Z/Time
+ for (var i = 0, iMax = points.length; i < iMax; i++) {
+ var t = points[i][3];
+ points[i][3] = points[i][2];
+ points[i][2] = t / this.bounds[2];
+ }
+ }
+
+ this.strokes[sCount] = points;
+ }
+ }
+ }
+
+ GML.prototype = {
+ addStroke: function (points, tstep) {
+ var pts = [];
+
+ if (tstep === undef) {
+ tstep = 0.1;
+ }
+
+ for (var i = 0, iMax = points.length; i < iMax; i++) {
+ var ta = [points[i][0], points[i][1], points[i][2]];
+ this.manual_pos += tstep;
+ ta.push(this.manual_pos);
+ pts.push(ta);
+ }
+
+ this.strokes.push(pts);
+ },
+
+
+ recenter: function () {
+ var vec3 = CubicVR.vec3;
+ var min = [0, 0, 0];
+ var max = [this.strokes[0][0][0], this.strokes[0][0][1], this.strokes[0][0][2]];
+
+ var i, iMax, s, sMax;
+
+ for (s = 0, sMax = this.strokes.length; s < sMax; s++) {
+ for (i = 0, iMax = this.strokes[s].length; i < iMax; i++) {
+ if (min[0] > this.strokes[s][i][0]) {
+ min[0] = this.strokes[s][i][0];
+ }
+ if (min[1] > this.strokes[s][i][1]) {
+ min[1] = this.strokes[s][i][1];
+ }
+ if (min[2] > this.strokes[s][i][2]) {
+ min[2] = this.strokes[s][i][2];
+ }
+
+ if (max[0] < this.strokes[s][i][0]) {
+ max[0] = this.strokes[s][i][0];
+ }
+ if (max[1] < this.strokes[s][i][1]) {
+ max[1] = this.strokes[s][i][1];
+ }
+ if (max[2] < this.strokes[s][i][2]) {
+ max[2] = this.strokes[s][i][2];
+ }
+ }
+ }
+
+ var center = vec3.multiply(vec3.subtract(max, min), 0.5);
+
+ for (s = 0, sMax = this.strokes.length; s < sMax; s++) {
+ for (i = 0, iMax = this.strokes[s].length; i < iMax; i++) {
+ this.strokes[s][i][0] = this.strokes[s][i][0] - center[0];
+ this.strokes[s][i][1] = this.strokes[s][i][1] - (this.upvector[1] ? center[1] : (-center[1]));
+ this.strokes[s][i][2] = this.strokes[s][i][2] - center[2];
+ }
+ }
+ },
+
+ generateObject: function (seg_mod, extrude_depth, pwidth, divsper, do_zmove) {
+ var vec3 = CubicVR.vec3;
+
+ if (seg_mod === undef) {
+ seg_mod = 0;
+ }
+ if (extrude_depth === undef) {
+ extrude_depth = 0;
+ }
+ if (do_zmove === undef) {
+ do_zmove = false;
+ }
+
+ // temporary defaults
+ var divs = 3;
+ // var divsper = 0.02;
+ if (divsper === undef) divsper = 0.02;
+ // var pwidth = 0.015;
+ if (pwidth === undef) pwidth = 0.015;
+
+ var extrude = extrude_depth !== 0;
+
+ var segCount = 0;
+ var faceSegment = 0;
+
+ var obj = new CubicVR.Mesh(this.name);
+
+ var lx, ly, lz, lt;
+
+ var i, iMax, pCount;
+
+ for (var sCount = 0, sMax = this.strokes.length; sCount < sMax; sCount++) {
+ var strokeEnvX = new CubicVR.Envelope();
+ var strokeEnvY = new CubicVR.Envelope();
+ var strokeEnvZ = new CubicVR.Envelope();
+
+ var pMax = this.strokes[sCount].length;
+
+ var d = 0;
+ var len_set = [];
+ var time_set = [];
+ var start_time = 0;
+ var strk = this.strokes[sCount];
+
+ for (pCount = 0; pCount < pMax; pCount++) {
+ var pt = strk[pCount];
+
+ var k1 = strokeEnvX.addKey(pt[3], pt[0]);
+ var k2 = strokeEnvY.addKey(pt[3], pt[1]);
+ var k3;
+
+ if (do_zmove) {
+ k3 = strokeEnvZ.addKey(pt[3], pt[2]);
+ } else {
+ k3 = strokeEnvZ.addKey(pt[3], 0);
+ }
+
+ k1.tension = 0.5;
+ k2.tension = 0.5;
+ k3.tension = 0.5;
+
+ if (pCount !== 0) {
+ var dx = pt[0] - lx;
+ var dy = pt[1] - ly;
+ var dz = pt[2] - lz;
+ var dt = pt[3] - lt;
+ var dlen = Math.sqrt(dx * dx + dy * dy + dz * dz);
+
+ d += dlen;
+
+ len_set[pCount - 1] = dlen;
+ time_set[pCount - 1] = dt;
+ } else {
+ start_time = pt[3];
+ }
+
+ lx = pt[0];
+ ly = pt[1];
+ lz = pt[2];
+ lt = pt[3];
+ }
+
+ var dpos = start_time;
+ var ptofs = obj.points.length;
+
+ for (pCount = 0; pCount < len_set.length; pCount++) {
+ var segLen = len_set[pCount];
+ var segTime = time_set[pCount];
+ var segNum = Math.ceil((segLen / divsper) * divs);
+
+ for (var t = dpos, tMax = dpos + segTime, tInc = (segTime / segNum); t < (tMax - tInc); t += tInc) {
+ if (t === dpos) {
+ lx = strokeEnvX.evaluate(t);
+ ly = strokeEnvY.evaluate(t);
+ lz = strokeEnvZ.evaluate(t);
+ }
+
+ var px, py, pz;
+
+ px = strokeEnvX.evaluate(t + tInc);
+ py = strokeEnvY.evaluate(t + tInc);
+ pz = strokeEnvZ.evaluate(t + tInc);
+
+ var pdx = (px - lx),
+ pdy = py - ly,
+ pdz = pz - lz;
+ var pd = Math.sqrt(pdx * pdx + pdy * pdy + pdz * pdz);
+ var a;
+
+ a = vec3.multiply(
+ vec3.normalize(
+ vec3.cross(this.viewvector, vec3.normalize([pdx, pdy, pdz]))), pwidth / 2.0);
+
+ obj.addPoint([lx - a[0], -(ly - a[1]), (lz - a[2]) + (extrude ? (extrude_depth / 2.0) : 0)]);
+ obj.addPoint([lx + a[0], -(ly + a[1]), (lz + a[2]) + (extrude ? (extrude_depth / 2.0) : 0)]);
+
+ lx = px;
+ ly = py;
+ lz = pz;
+ }
+
+ dpos += segTime;
+ }
+
+ var ptlen = obj.points.length;
+
+ if (extrude) {
+ for (i = ptofs, iMax = ptlen; i < iMax; i++) {
+ obj.addPoint([obj.points[i][0], obj.points[i][1], obj.points[i][2] - (extrude ? (extrude_depth / 2.0) : 0)]);
+ }
+ }
+
+ for (i = 0, iMax = ptlen - ptofs; i <= iMax - 4; i += 2) {
+ if (segCount % seg_mod === 0) {
+ faceSegment++;
+ }
+
+ obj.setSegment(faceSegment);
+
+ var arFace = [ptofs + i, ptofs + i + 1, ptofs + i + 3, ptofs + i + 2];
+ // var ftest = vec3.dot(this.viewvector, triangle.normal(obj.points[arFace[0]], obj.points[arFace[1]], obj.points[arFace[2]]));
+ var faceNum = obj.addFace(arFace);
+
+ // if (ftest < 0) {
+ // this.faces[faceNum].flip();
+ // }
+ if (extrude) {
+ var arFace2 = [arFace[3] + ptlen - ptofs, arFace[2] + ptlen - ptofs, arFace[1] + ptlen - ptofs, arFace[0] + ptlen - ptofs];
+ faceNum = obj.addFace(arFace2);
+
+ arFace2 = [ptofs + i, ptofs + i + 2, ptofs + i + 2 + ptlen - ptofs, ptofs + i + ptlen - ptofs];
+ faceNum = obj.addFace(arFace2);
+
+ arFace2 = [ptofs + i + 1 + ptlen - ptofs, ptofs + i + 3 + ptlen - ptofs, ptofs + i + 3, ptofs + i + 1];
+ faceNum = obj.addFace(arFace2);
+
+ if (i === 0) {
+ arFace2 = [ptofs + i + ptlen - ptofs, ptofs + i + 1 + ptlen - ptofs, ptofs + i + 1, ptofs + i];
+ faceNum = obj.addFace(arFace2);
+ }
+ if (i === iMax - 4) {
+ arFace2 = [ptofs + i + 2, ptofs + i + 3, ptofs + i + 3 + ptlen - ptofs, ptofs + i + 2 + ptlen - ptofs];
+ faceNum = obj.addFace(arFace2);
+ }
+ }
+
+ segCount++;
+ }
+ }
+
+
+ obj.calcFaceNormals();
+
+ obj.triangulateQuads();
+ obj.calcNormals();
+ obj.compile();
+
+ return obj;
+ }
+ }
+
+ var extend = {
+ GML: GML
+ };
+
+ return extend;
+});
View
211 source/CubicVR.Landscape.js
@@ -0,0 +1,211 @@
+CubicVR.RegisterModule("Landscape", function (base) {
+
+ var undef = base.undef;
+ var enums = CubicVR.enums;
+ var GLCore = base.GLCore;
+
+ var cubicvr_identity = [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0];
+
+
+ var M_TWO_PI = 2.0 * Math.PI;
+ var M_HALF_PI = Math.PI / 2.0;
+
+ function Landscape(size_in, divisions_in_w, divisions_in_h, matRef_in) {
+ this.doTransform = function () {};
+ this.tMatrix = cubicvr_identity;
+
+ this.parent = null;
+ this.position = [0, 0, 0];
+ this.scale = [1, 1, 1];
+ this.size = size_in;
+ this.divisions_w = divisions_in_w;
+ this.divisions_h = divisions_in_h;
+ this.matRef = matRef_in;
+ this.children = null;
+
+ this.obj = new CubicVR.Mesh();
+
+ var i, j;
+
+ if (this.divisions_w > this.divisions_h) {
+ this.size_w = size_in;
+ this.size_h = (size_in / this.divisions_w) * this.divisions_h;
+ } else if (this.divisions_h > this.divisions_w) {
+ this.size_w = (size_in / this.divisions_h) * this.divisions_w;
+ this.size_h = size_in;
+ } else {
+ this.size_w = size_in;
+ this.size_h = size_in;
+ }
+
+ for (j = -(this.size_h / 2.0); j < (this.size_h / 2.0); j += (this.size_h / this.divisions_h)) {
+ for (i = -(this.size_w / 2.0); i < (this.size_w / 2.0); i += (this.size_w / this.divisions_w)) {
+ this.obj.addPoint([i + ((this.size_w / (this.divisions_w)) / 2.0), 0, j + ((this.size_h / (this.divisions_h)) / 2.0)]);
+ }
+ }
+
+ var k, l;
+
+ this.obj.setFaceMaterial(this.matRef);
+
+ for (l = 0; l < this.divisions_h - 1; l++) {
+ for (k = 0; k < this.divisions_w - 1; k++) {
+ this.obj.addFace([(k) + ((l + 1) * this.divisions_w), (k + 1) + ((l) * this.divisions_w), (k) + ((l) * this.divisions_w)]);
+
+ this.obj.addFace([(k) + ((l + 1) * this.divisions_w), (k + 1) + ((l + 1) * this.divisions_w), (k + 1) + ((l) * this.divisions_w)]);
+ }
+ }
+ }
+
+ Landscape.prototype = {
+ getMesh: function () {
+ return this.obj;
+ },
+
+ setIndexedHeight: function (ipos, jpos, val) {
+ obj.points[(ipos) + (jpos * this.divisions_w)][1] = val;
+ },
+
+ mapGen: function (w_func, ipos, jpos, ilen, jlen) {
+ var pt;
+
+ if (ipos !== undef && jpos !== undef && ilen !== undef && jlen !== undef) {
+ if (ipos >= this.divisions_w) return;
+ if (jpos >= this.divisions_h) return;
+ if (ipos + ilen >= this.divisions_w) ilen = this.divisions_w - 1 - ipos;
+ if (jpos + jlen >= this.divisions_h) jlen = this.divisions_h - 1 - jpos;
+ if (ilen <= 0 || jlen <= 0) return;
+
+ for (var i = ipos, imax = ipos + ilen; i < imax; i++) {
+ for (var j = jpos, jmax = jpos + jlen; j < jmax; j++) {
+ pt = this.obj.points[(i) + (j * this.divisions_w)];
+
+ pt[1] = w_func(pt[0], pt[2]);
+ }
+ }
+ } else {
+ for (var x = 0, xmax = this.obj.points.length; x < xmax; x++) {
+ pt = this.obj.points[x];
+
+ pt[1] = w_func(pt[0], pt[2]);
+ }
+ }
+ },
+
+ getFaceAt: function (x, z) {
+ if (typeof (x) === 'object') {
+ return this.getFaceAt(x[0], x[2]);
+ }
+
+ var ofs_w = (this.size_w / 2.0) - ((this.size_w / (this.divisions_w)) / 2.0);
+ var ofs_h = (this.size_h / 2.0) - ((this.size_h / (this.divisions_h)) / 2.0);
+
+ var i = parseInt(Math.floor(((x + ofs_w) / this.size_w) * (this.divisions_w)), 10);
+ var j = parseInt(Math.floor(((z + ofs_h) / this.size_h) * (this.divisions_h)), 10);
+
+ if (i < 0) {
+ return -1;
+ }
+ if (i >= this.divisions_w - 1) {
+ return -1;
+ }
+ if (j < 0) {
+ return -1;
+ }
+ if (j >= this.divisions_h - 1) {
+ return -1;
+ }
+
+ var faceNum1 = parseInt(i + (j * (this.divisions_w - 1)), 10) * 2;
+ var faceNum2 = parseInt(faceNum1 + 1, 10);
+
+ var testPt = this.obj.points[this.obj.faces[faceNum1].points[0]];
+
+ var slope = Math.abs(z - testPt[2]) / Math.abs(x - testPt[0]);
+
+ if (slope >= 1.0) {
+ return (faceNum1);
+ } else {
+ return (faceNum2);
+ }
+ },
+
+ getHeightValue: function (x, z) {
+ var triangle = CubicVR.triangle;
+
+ if (typeof (x) === 'object') {
+ return this.getHeightValue(x[0], x[2]);
+ }
+
+ var tmpFace;
+ var tmpPoint;
+
+ var faceNum = this.getFaceAt(x, z);
+
+ if (faceNum === -1) {
+ return 0;
+ }
+
+ tmpFace = this.obj.faces[faceNum];
+ tmpPoint = this.obj.points[this.obj.faces[faceNum].points[0]];
+
+ var tmpNorm = triangle.normal(this.obj.points[this.obj.faces[faceNum].points[0]], this.obj.points[this.obj.faces[faceNum].points[1]], this.obj.points[this.obj.faces[faceNum].points[2]]);
+
+ var na = tmpNorm[0];
+ var nb = tmpNorm[1];
+ var nc = tmpNorm[2];
+
+ var d = -(na * tmpPoint[0]) - (nb * tmpPoint[1]) - (nc * tmpPoint[2]);
+
+ return (((na * x) + (nc * z) + d) / (-nb)); // add height ofs here
+ },
+
+ orient: function (x, z, width, length, heading, center) {
+ if (center === undef) {
+ center = 0;
+ }
+
+ var xpos, zpos;
+ var xrot, zrot;
+ var heightsample = [];
+ var xyzTmp;
+
+ var halfw = width / 2.0;
+ var halfl = length / 2.0;
+
+ var mag = Math.sqrt(halfl * halfl + halfw * halfw);
+ var ang = Math.atan2(halfl, halfw);
+
+ heading *= (Math.PI / 180.0);
+
+ xpos = x + (Math.sin(heading) * center);
+ zpos = z + (Math.cos(heading) * center);
+
+ heightsample[0] = this.getHeightValue([xpos + mag * Math.cos(-ang - M_HALF_PI + heading), 0, zpos + mag * -Math.sin(-ang - M_HALF_PI + heading)]);
+ heightsample[1] = this.getHeightValue([xpos + mag * Math.cos(ang - M_HALF_PI + heading), 0, zpos + mag * (-Math.sin(ang - M_HALF_PI + heading))]);
+ heightsample[2] = this.getHeightValue([xpos + mag * Math.cos(-ang + M_HALF_PI + heading), 0, zpos + mag * (-Math.sin(-ang + M_HALF_PI + heading))]);
+ heightsample[3] = this.getHeightValue([xpos + mag * Math.cos(ang + M_HALF_PI + heading), 0, zpos + mag * (-Math.sin(ang + M_HALF_PI + heading))]);
+
+ xrot = -Math.atan2((heightsample[1] - heightsample[2]), width);
+ zrot = -Math.atan2((heightsample[0] - heightsample[1]), length);
+
+ xrot += -Math.atan2((heightsample[0] - heightsample[3]), width);
+ zrot += -Math.atan2((heightsample[3] - heightsample[2]), length);
+
+ xrot /= 2.0; // average angles
+ zrot /= 2.0;
+
+
+ return [[x, ((heightsample[2] + heightsample[3] + heightsample[1] + heightsample[0])) / 4.0, z], //
+ [xrot * (180.0 / Math.PI), heading, zrot * (180.0 / Math.PI)]];
+ }
+ }
+
+ var exports = {
+ Landscape: Landscape
+ };
+
+ return exports;
+
+
+});
View
226 source/CubicVR.Layout.js
@@ -0,0 +1,226 @@
+CubicVR.RegisterModule("Layout", function (base) {
+
+ var undef = base.undef;
+ var GLCore = base.GLCore;
+
+ function View(obj_init) {
+
+ this.texture = obj_init.texture ? obj_init.texture : null;
+ this.width = obj_init.width ? obj_init.width : 128;
+ this.height = obj_init.height ? obj_init.height : 128;
+ this.x = obj_init.x ? obj_init.x : 0;
+ this.y = obj_init.y ? obj_init.y : 0;
+ this.blend = obj_init.blend ? obj_init.blend : false;
+ this.opacity = (typeof (obj_init.opacity) !== 'undefined') ? obj_init.opacity : 1.0;
+ this.tint = obj_init.tint ? obj_init.tint : [1.0, 1.0, 1.0];
+
+ this.type = 'view';
+
+ this.superView = null;
+ this.childViews = [];
+ this.panel = null;
+ }
+
+ View.prototype = {
+ addSubview: function (view) {
+ this.childViews.push(view);
+ // this.superView.makePanel(view);
+ view.superView = this;
+ },
+
+ makePanel: function (view) {
+ return this.superView.makePanel(view);
+ }
+ };
+
+ function Layout(obj_init) {
+
+ this.texture = obj_init.texture ? obj_init.texture : null;
+ this.width = obj_init.width ? obj_init.width : 128;
+ this.height = obj_init.height ? obj_init.height : 128;
+ this.x = obj_init.x ? obj_init.x : 0;
+ this.y = obj_init.y ? obj_init.y : 0;
+ this.blend = obj_init.blend ? obj_init.blend : false;
+ this.opacity = (typeof (obj_init.opacity) !== 'undefined') ? obj_init.opacity : 1.0;
+ this.tint = obj_init.tint ? obj_init.tint : [1.0, 1.0, 1.0];
+
+ this.type = 'root';
+
+ this.superView = null;
+ this.childViews = [];
+ this.setupShader();
+
+ this.panel = null;
+ this.makePanel(this);
+ }
+
+ Layout.prototype = {
+ setupShader: function () {
+ this.shader = new CubicVR.PostProcessShader({
+ shader_vertex: [
+ "attribute vec3 aVertex;",
+ "attribute vec2 aTex;",
+ "varying vec2 vTex;",
+ "uniform vec3 screen;",
+ "uniform vec3 position;",
+ "uniform vec3 size;",
+ "void main(void) {",
+ "vTex = aTex;",
+ "vec4 vPos = vec4(aVertex.xyz,1.0);",
+ "vPos.x *= size.x/screen.x;",
+ "vPos.y *= size.y/screen.y;",
+ "vPos.x += (size.x/screen.x);",
+ "vPos.y -= (size.y/screen.y);",
+ "vPos.x += (position.x/screen.x)*2.0 - 1.0;", "vPos.y -= (position.y/screen.y)*2.0 - 1.0;",
+ "gl_Position = vPos;",
+ "}"
+ ].join("\n"),
+ shader_fragment: [
+ "#ifdef GL_ES",
+ "precision highp float;",
+ "#endif",
+ "uniform sampler2D srcTex;",
+ "uniform vec3 tint;",
+ "varying vec2 vTex;",
+ "void main(void) {",
+ "vec4 color = texture2D(srcTex, vTex)*vec4(tint,1.0);",
+ // "if (color.a == 0.0) discard;",
+ "gl_FragColor = color;",
+ "}"
+ ].join("\n"),
+ init: function (shader) {
+ shader.setInt("srcTex", 0);
+ shader.addVector("screen");
+ shader.addVector("position");
+ shader.addVector("tint");
+ shader.addVector("size");
+ }
+ });
+ },
+
+ addSubview: function (view) {
+ this.childViews.push(view);
+ // this.makePanel(view);
+ view.superView = this;
+ },
+
+ makePanel: function (view) {
+ var gl = CubicVR.GLCore.gl;
+ var pQuad = {}; // intentional empty object
+ pQuad.vbo_points = new Float32Array([-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0]);
+ pQuad.vbo_uvs = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1]);
+
+ pQuad.gl_points = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, pQuad.gl_points);
+ gl.bufferData(gl.ARRAY_BUFFER, pQuad.vbo_points, gl.STATIC_DRAW);
+
+ pQuad.gl_uvs = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, pQuad.gl_uvs);
+ gl.bufferData(gl.ARRAY_BUFFER, pQuad.vbo_uvs, gl.STATIC_DRAW);
+
+ view.panel = pQuad;
+ },
+
+
+ renderPanel: function (view, panel) {
+ var gl = CubicVR.GLCore.gl;
+
+ if (!view.texture) {
+ return false;
+ }
+
+ view.texture.use(gl.TEXTURE0);
+ },
+
+ renderView: function (view) {
+ if (!view.texture) return;
+
+ var gl = CubicVR.GLCore.gl;
+
+ var offsetLeft = view.offsetLeft;
+ var offsetTop = view.offsetTop;
+
+ if (!offsetLeft) offsetLeft = 0;
+ if (!offsetTop) offsetTop = 0;
+
+ var shader = this.shader.shader;
+
+ shader.use();
+ shader.setVector("screen", [this.width, this.height, 0]);
+ shader.setVector("position", [view.x + offsetLeft, view.y + offsetTop, 0]);
+ shader.setVector("size", [view.width, view.height, 0]);
+ shader.setVector("tint", view.tint);
+
+ if (view.blend) {
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+ }
+
+ view.texture.use(gl.TEXTURE0);
+
+ // this.renderPanel(view,this.panel);
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ if (view.blend) {
+ gl.disable(gl.BLEND);
+ gl.blendFunc(gl.ONE, gl.ZERO);
+ }
+ },
+
+ render: function () {
+ var gl = CubicVR.GLCore.gl;
+
+ gl.disable(gl.DEPTH_TEST);
+
+ if (this.texture) this.renderView(this);
+
+ var stack = [];
+ var framestack = [];
+
+ this.offsetLeft = 0, this.offsetTop = 0;
+ stack.push(this);
+
+
+ shader = this.shader.shader;
+ shader.use();
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.panel.gl_points);
+ gl.vertexAttribPointer(shader.uniforms["aVertex"], 3, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(shader.uniforms["aVertex"]);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.panel.gl_uvs);
+ gl.vertexAttribPointer(shader.uniforms["aTex"], 2, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(shader.uniforms["aTex"]);
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
+
+ while (stack.length) {
+ var view = stack.pop();
+
+ this.renderView(view);
+
+ if (view.childViews.length) {
+ for (var i = view.childViews.length - 1, iMin = 0; i >= iMin; i--) {
+ view.childViews[i].offsetLeft = view.x + view.offsetLeft;
+ view.childViews[i].offsetTop = view.y + view.offsetTop;
+ stack.push(view.childViews[i]);
+ }
+ }
+
+ }
+
+ gl.disableVertexAttribArray(shader.uniforms["aTex"]);
+
+ gl.enable(gl.DEPTH_TEST);
+ }
+ };
+
+ var extend = {
+ Layout: Layout,
+ View: View
+ };
+
+ return extend;
+});
View
441 source/CubicVR.Light.js
@@ -0,0 +1,441 @@
+CubicVR.RegisterModule("Light", function (base) {
+
+ var GLCore = base.GLCore;
+ var enums = CubicVR.enums;
+ var undef = base.undef;
+
+ var cubicvr_identity = [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0];
+
+ // Light Types
+ enums.light = {
+ type: {
+ NULL: 0,
+ POINT: 1,
+ DIRECTIONAL: 2,
+ SPOT: 3,
+ AREA: 4,
+ DEPTH_PACK: 5,
+ // this lets us pass the shadow stage in as a light definition
+ SPOT_SHADOW: 6,
+ MAX: 7
+ },
+ method: {
+ GLOBAL: 0,
+ STATIC: 1,
+ DYNAMIC: 2
+ }
+ };
+
+ function Light(light_type, lighting_method) {
+ var aabbMath = CubicVR.aabb;
+
+ if (light_type === undef) {
+ light_type = enums.light.type.POINT;
+ }
+ if (lighting_method === undef) {
+ lighting_method = enums.light.method.DYNAMIC;
+ }
+
+ if (typeof (light_type) == 'object') {
+ this.light_type = (light_type.type !== undef) ? light_type.type : enums.light.type.POINT;
+ this.diffuse = (light_type.diffuse !== undef) ? light_type.diffuse : [1, 1, 1];
+ this.specular = (light_type.specular !== undef) ? light_type.specular : [1.0, 1.0, 1.0];
+ this.intensity = (light_type.intensity !== undef) ? light_type.intensity : 1.0;
+ this.position = (light_type.position !== undef) ? light_type.position : [0, 0, 0];
+ this.direction = (light_type.direction !== undef) ? light_type.direction : [0, 0, 0];
+ this.distance = (light_type.distance !== undef) ? light_type.distance : ((this.light_type === enums.light.type.AREA) ? 30 : 10);
+ this.cutoff = (light_type.cutoff !== undef) ? light_type.cutoff : 60;
+ this.map_res = (light_type.map_res !== undef) ? light_type.map_res : (this.light_type === enums.light.type.AREA) ? 2048 : 512;
+ this.map_res = (light_type.mapRes !== undef) ? light_type.mapRes : this.map_res;
+ this.method = (light_type.method !== undef) ? light_type.method : lighting_method;
+ this.areaCam = (light_type.areaCam !== undef) ? light_type.areaCam : null;
+ this.areaCeiling = (light_type.areaCeiling !== undef) ? light_type.areaCeiling : 40;
+ this.areaFloor = (light_type.areaFloor !== undef) ? light_type.areaFloor : -40;
+ this.areaAxis = (light_type.areaAxis !== undef) ? light_type.areaAxis : [1, 1, 0];
+ } else {
+ this.light_type = light_type;
+ this.diffuse = [1, 1, 1];
+ this.specular = [1.0, 1.0, 1.0];
+ this.intensity = 1.0;
+ this.position = [0, 0, 0];
+ this.direction = [0, 0, 0];
+ this.distance = ((this.light_type === enums.light.type.AREA) ? 30 : 10);
+ this.cutoff = 60;
+ this.map_res = (this.light_type === enums.light.type.AREA) ? 2048 : 512;
+ this.method = lighting_method;
+ this.areaCam = null;
+ this.areaCeiling = 40;
+ this.areaFloor = -40;
+ this.areaAxis = [1, 1, 0];
+ }
+
+ this.trans = new CubicVR.Transform();
+ this.lposition = [0, 0, 0];
+ this.tMatrix = this.trans.getResult();
+ this.dirty = true;
+ this.octree_leaves = [];
+ this.octree_common_root = null;
+ this.octree_aabb = [
+ [0, 0, 0],
+ [0, 0, 0]
+ ];
+ this.ignore_octree = false;
+ this.visible = true;
+ this.culled = true;
+ this.was_culled = true;
+ this.aabb = [
+ [0, 0, 0],
+ [0, 0, 0]
+ ];
+ aabbMath.reset(this.aabb, this.position);
+ this.adjust_octree = CubicVR.SceneObject.prototype.adjust_octree;
+ this.motion = null;
+ this.rotation = [0, 0, 0];
+
+ if (this.light_type === enums.light.type.SPOT_SHADOW || this.light_type === enums.light.type.AREA) {
+ this.setShadow(this.map_res);
+ }
+
+ // modelview / normalmatrix transform outputs
+ this.lDir = [0, 0, 0];
+ this.lPos = [0, 0, 0];
+ }
+
+ Light.prototype = {
+ setType: function (light_type) {
+ this.light_type = type;
+ },
+
+ setMethod: function (method) {
+ this.method = method;
+ },
+
+ setDiffuse: function (diffuse) {
+ this.diffuse = diffuse;
+ },
+
+ setSpecular: function (specular) {
+ this.specular = specular;
+ },
+
+ setIntensity: function (intensity) {
+ this.intensity = intensity;
+ },
+
+ setPosition: function (position) {
+ this.position = position;
+ },
+
+ setDistance: function (distance) {
+ this.distance = distance;
+ },
+
+ setCutoff: function (cutoff_angle) {
+ this.cutoff = cutoff_angle;
+ },
+
+ prepare: function (camera) {
+ var mat4 = CubicVR.mat4;
+ var mat3 = CubicVR.mat3;
+ var ltype = this.light_type;
+
+ if (ltype === enums.light.type.DIRECTIONAL) {
+ this.lDir = mat3.vec3_multiply(this.direction, camera.nMatrix);
+ } else if (ltype === enums.light.type.SPOT || ltype === enums.light.type.SPOT_SHADOW) {
+ this.lDir = mat3.vec3_multiply(this.direction, camera.nMatrix);
+ this.lPos = mat4.vec3_multiply(this.position, camera.mvMatrix);
+ } else if (ltype === enums.light.type.POINT) {
+ this.lPos = mat4.vec3_multiply(this.position, camera.mvMatrix);
+ } else if (ltype === enums.light.type.AREA) {
+ this.lDir = mat3.vec3_multiply(this.direction, camera.nMatrix);
+ }
+ },
+
+ control: function (controllerId, motionId, value) {
+ if (controllerId === enums.motion.POS) {
+ this.position[motionId] = value;
+ } else if (controllerId === enums.motion.INTENSITY) {
+ this.intensity = value;
+ }
+
+ // else if (controllerId === enums.motion.ROT) {
+ // this.rotation[motionId] = value;
+ // }
+ },
+
+ doTransform: function (mat) {
+ var vec3 = CubicVR.vec3;
+ if (!vec3.equal(this.lposition, this.position) || (mat !== undef)) {
+ this.trans.clearStack();
+ this.trans.translate(this.position);
+ if ((mat !== undef)) {
+ this.trans.pushMatrix(mat);
+ }
+ this.tMatrix = this.trans.getResult();
+ this.lposition[0] = this.position[0];
+ this.lposition[1] = this.position[1];
+ this.lposition[2] = this.position[2];
+ this.dirty = true;
+ this.adjust_octree();
+ } //if
+ },
+ //Light::doTransform
+ getAABB: function () {
+ var vec3 = CubicVR.vec3;
+ var aabbMath