From 13939882afe5f1618e9830b6d63f897375303945 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Sat, 25 Dec 2010 17:21:28 -0500 Subject: [PATCH 01/29] add gitignore file, ignore dist/ and docs/ --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5c53e32e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +dist/ +docs/ From 0365d5e878d32c7c280024559f29ac86386d4f41 Mon Sep 17 00:00:00 2001 From: Lindsay Kay Date: Tue, 25 Jan 2011 00:15:11 +0100 Subject: [PATCH 02/29] Fix "constant" type interpolator - cheers Terrance --- src/scenejs/interpolation/interpolator.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scenejs/interpolation/interpolator.js b/src/scenejs/interpolation/interpolator.js index c673504f..0593d329 100755 --- a/src/scenejs/interpolation/interpolator.js +++ b/src/scenejs/interpolation/interpolator.js @@ -254,9 +254,9 @@ SceneJS.Interpolator.prototype._linearInterpolate = function(k) { // @private SceneJS.Interpolator.prototype._constantInterpolate = function(k) { if (Math.abs((k - this._attr.keys[this._key1])) < Math.abs((k - this._attr.keys[this._key2]))) { - return this._attr.keys[this._key1]; + return this._attr.values[this._key1]; } else { - return this._attr.keys[this._key2]; + return this._attr.values[this._key2]; } }; From 9fb4074337d019844728222b4de31d048e53e15e Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Mon, 31 Jan 2011 12:59:39 -0500 Subject: [PATCH 03/29] new ant tasks: package-lib, packge-examples If you are modifying the source code and testing it with a new example or your own project the following ant tasks which complete in just a couple of seconds may be helpful. ant package-lib Create the "dist" directory and populate the lib directory with scenejs.js, scenejs.min.js, and the plugins and utils directories. ant packge-examples Create the "dist" directory and populate the lib directory and the examples directory. --- README.markdown | 14 +- build.xml | 804 ++++++++++++++++++++++++------------------------ 2 files changed, 417 insertions(+), 401 deletions(-) diff --git a/README.markdown b/README.markdown index 996a5f7f..b7144c23 100755 --- a/README.markdown +++ b/README.markdown @@ -28,7 +28,19 @@ To build SceneJS, you'll need Java and ANT. Then at the same level as build.xml, ant all -That will create the "dist" directory, which will contain SceneJS libraries, JSDocs and examples. +Create the "dist" directory, which will contain all the SceneJS libraries, JSDocs and examples. + +If you are modifying the source code and testing it with a new example or your own project the following +ant tasks which complete in just a couple of seconds may be helpful. + +ant package-lib + +Create the "dist" directory and populate the lib directory with scenejs.js, scenejs.min.js, and the plugins and utils directories. + +ant packge-examples + +Create the "dist" directory and populate the lib directory and the examples directory. + # Resources diff --git a/build.xml b/build.xml index e18139b9..4c20fb50 100755 --- a/build.xml +++ b/build.xml @@ -1,400 +1,404 @@ - - - - - - - - - - - - - - ************** Building SceneJS Version ${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID}.${PATCH_ID} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - V${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID}.${PATCH_ID} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + ************** Building SceneJS Version ${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID}.${PATCH_ID} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + V${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID}.${PATCH_ID} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 734b192ee66e05f03a8160cd04de02ebb55307f4 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Mon, 31 Jan 2011 13:28:24 -0500 Subject: [PATCH 04/29] create index.html when packaging examples forgot this when refactoring ant tasks --- build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.xml b/build.xml index 4c20fb50..d0b80eb8 100755 --- a/build.xml +++ b/build.xml @@ -357,7 +357,7 @@ - + From 14f7959c708500e282396bf655371121602698f5 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Mon, 31 Jan 2011 14:28:17 -0500 Subject: [PATCH 05/29] ant package-examples, package-lib don't clean dist/ When hacking on SceneJS or an example it is helpful to keep the generated documentation while regenerating scenejs.js, scenejs.min.js and the examples. The ant tasks: all, package, package-docs, docs clean the dist directory. The ant tasks package-examples, package-utils and package-lib do not clean the dist directory. --- README.markdown | 3 ++- build.xml | 14 +++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/README.markdown b/README.markdown index b7144c23..05eac658 100755 --- a/README.markdown +++ b/README.markdown @@ -31,7 +31,8 @@ ant all Create the "dist" directory, which will contain all the SceneJS libraries, JSDocs and examples. If you are modifying the source code and testing it with a new example or your own project the following -ant tasks which complete in just a couple of seconds may be helpful. +ant tasks which complete in just a couple of seconds may be helpful. These tasks do not clean the dist +directory so previously-generated JSDocs will still available ant package-lib diff --git a/build.xml b/build.xml index d0b80eb8..4b40e396 100755 --- a/build.xml +++ b/build.xml @@ -10,7 +10,6 @@ - ************** Building SceneJS Version ${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID}.${PATCH_ID} @@ -162,6 +161,9 @@ + + + @@ -299,7 +301,7 @@ + depends="package-lib, package-lib-utils, package-lib-plugins, package-index, package-examples, package-docs"> - + + + + + + + From cf384cc92039d3daa81854c2a05cdd5a2b289610 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Mon, 31 Jan 2011 23:30:04 -0500 Subject: [PATCH 06/29] horizontal list style for multiple-canvases example --- resources/web/style.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/resources/web/style.css b/resources/web/style.css index 7c9ff1e6..4adbdd2b 100644 --- a/resources/web/style.css +++ b/resources/web/style.css @@ -197,6 +197,14 @@ h4 { margin-left: 20px; } +#content ul.hlist li { + line-height: 1.4em; + color: #444444 !important; + margin-left: 5px; + display: inline; + list-style-type: none; +} + #content p.intro { margin: auto; color: #CC6600 !important; From 6e703e2be85de6404dc164e00da402f64454d569 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Mon, 31 Jan 2011 23:31:24 -0500 Subject: [PATCH 07/29] multiple-canvases example Multiple Canvases SceneJS scene which renders the venerable OpenGL teapot into four canvases. Stephen Bannasch sbannasch@concord.org Adapted fron the hello-teapot example by: Lindsay S. Kay, lindsay.kay@xeolabs.com This example renders separate scenegraphs containing a teapot object from different perspectives into four separate canvases. Dragging in the pitch and yaw axes in any one canvas will affect the orientation of the teapot object in the other three canvases. Each of the rotatable Newell Teapots are illuminated by three light sources from the same direction. --- src/examples/multiple-canvases/index.html | 92 ++ .../multiple-canvases/multiple-canvases.js | 853 ++++++++++++++++++ 2 files changed, 945 insertions(+) create mode 100644 src/examples/multiple-canvases/index.html create mode 100644 src/examples/multiple-canvases/multiple-canvases.js diff --git a/src/examples/multiple-canvases/index.html b/src/examples/multiple-canvases/index.html new file mode 100644 index 00000000..a30c241f --- /dev/null +++ b/src/examples/multiple-canvases/index.html @@ -0,0 +1,92 @@ + + + + + + + + +
+ +
+
    +
  • + +

    This example requires a browser that supports the + HTML5 + <canvas> feature.

    +
    +
  • +
  • + +

    This example requires a browser that supports the + HTML5 + <canvas> feature.

    +
    +
  • +
+
    +
  • + +

    This example requires a browser that supports the + HTML5 + <canvas> feature.

    +
    +
  • +
  • + +

    This example requires a browser that supports the + HTML5 + <canvas> feature.

    +
    +
  • +
+
+

Multiple Canvases, Using SceneJS

+ +

This renders separate scenegraphs containing a teapot object from different perspectives + into four separate canvases. Dragging in the pitch and yaw axes in any one canvas will + affect the orientation of the teapot object in the other three canvases. Each of the + rotatable Newell Teapots are illuminated by three light sources from the same direction.

+ +
+ + +
+
+

Log 1

+
+

Log 2

+
+

Log 3

+
+

Log 4

+
+
+
+
+ + + + \ No newline at end of file diff --git a/src/examples/multiple-canvases/multiple-canvases.js b/src/examples/multiple-canvases/multiple-canvases.js new file mode 100644 index 00000000..84f1748c --- /dev/null +++ b/src/examples/multiple-canvases/multiple-canvases.js @@ -0,0 +1,853 @@ +/* + Multiple Canvases SceneJS scene which renders the venerable OpenGL teapot. + + Stephen Bannasch + sbannasch@concord.org + + Adapted fron the hello-teapot example by: + Lindsay S. Kay, + lindsay.kay@xeolabs.com + + This renders separate scenegraphs containing a teapot object from different perspectives + into four separate canvases. + + This scene is interactive; to rotate the view, it takes two variables, "yaw" and "pitch", which are + updated on rotate nodes from mouse input. + + Dragging in the pitch and yaw axes in any one canvas will affect the orientation of the teapot + object in the other three canvases. Each of the rotatable Newell Teapots are illuminated by three + light sources from the same direction. + + */ +SceneJS.createNode({ + + type: "scene", + + /* ID that we'll access the scene by when we want to render it + */ + id: "theScene1", + + /* Bind scene to a WebGL canvas: + */ + canvasId: "theCanvas1", + + /* You can optionally write logging to a DIV - scene will log to the console as well. + */ + loggingElementId: "theLoggingDiv1", + + nodes: [ + + /* Viewing transform specifies eye position, looking + * at the origin by default + */ + { + type: "lookAt", + eye : { x: 0.0, y: 10.0, z: -15 }, + look : { y:1.0 }, + up : { y: 1.0 }, + + nodes: [ + + /* Camera describes the projection + */ + { + type: "camera", + optics: { + type: "perspective", + fovy : 25.0, + aspect : 1.47, + near : 0.10, + far : 300.0 + }, + + nodes: [ + + + /* A lights node inserts point lights into the world-space. + * You can have many of these, nested within modelling transforms + * if you want to move them around. + */ + { + type: "light", + mode: "dir", + color: { r: 1.0, g: 0.5, b: 0.5 }, + diffuse: true, + specular: true, + dir: { x: 1.0, y: 1.0, z: -1.0 } + }, + + { + type: "light", + mode: "dir", + color: { r: 0.5, g: 1.0, b: 0.5 }, + diffuse: true, + specular: true, + dir: { x: 0.0, y: 1.0, z: -1.0 } + }, + + { + type: "light", + mode: "dir", + color: { r: 0.2, g: 0.2, b: 1.0 }, + diffuse: true, + specular: true, + dir: { x: -1.0, y: 0.0, z: -1.0 } + }, + + /* Next, modelling transforms to orient our teapot. See how these have IDs, + * so we can access them to set their angle attributes. + */ + { + type: "rotate", + id: "pitch1", + angle: 0.0, + x : 1.0, + + nodes: [ + { + type: "rotate", + id: "yaw1", + angle: 0.0, + y : 1.0, + + nodes: [ + { + type: "rotate", + id: "roll1", + angle: 0.0, + z : 1.0, + + nodes: [ + + /* Specify the amounts of ambient, diffuse and specular + * lights our teapot reflects + */ + { + type: "material", + emit: 0, + baseColor: { r: 0.3, g: 0.3, b: 0.9 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 100.0, + + nodes: [ + + { + type: "translate", // Example translation + x:0.0, + y:0.0, + z:0.0, + + nodes : [ + { + type: "scale", // Example scaling + x:1.0, + y:1.0, + z:1.0, + + nodes: [ + { + type : "teapot" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] +}); + + +/*---------------------------------------------------------------------- + * Scene rendering loop and mouse handler stuff follows + *---------------------------------------------------------------------*/ +var yaw1 = 0; +var pitch1 = 0; +var lastX1; +var lastY1; +var dragging1 = false; + +SceneJS.withNode("theScene1").render(); + +var canvas1 = document.getElementById("theCanvas1"); + +function mouseDown1(event) { + lastX1 = event.clientX; + lastY1 = event.clientY; + dragging1 = true; +} + +function mouseUp1() { + dragging1 = false; +} + +/* On a mouse drag, we'll re-render the scene, passing in + * incremented angles in each time. + */ +function mouseMove1(event) { + if (dragging1) { + yaw1 += (event.clientX - lastX1) * 0.2; + pitch1 += (event.clientY - lastY1) * -0.2; + + SceneJS.withNode("yaw1").set("angle", yaw1); + SceneJS.withNode("pitch1").set("angle", pitch1); + + SceneJS.withNode("theScene1").render(); + + lastX1 = event.clientX; + lastY1 = event.clientY; + + SceneJS.withNode("yaw2").set("angle", yaw1); + SceneJS.withNode("roll2").set("angle", pitch1); + SceneJS.withNode("theScene2").render(); + + SceneJS.withNode("yaw3").set("angle", yaw1); + SceneJS.withNode("pitch3").set("angle", pitch1); + SceneJS.withNode("theScene3").render(); + + SceneJS.withNode("yaw4").set("angle", yaw1); + SceneJS.withNode("roll4").set("angle", pitch1); + SceneJS.withNode("theScene4").render(); + + } +} + +canvas1.addEventListener('mousedown', mouseDown1, true); +canvas1.addEventListener('mousemove', mouseMove1, true); +canvas1.addEventListener('mouseup', mouseUp1, true); + +SceneJS.createNode({ + + type: "scene", + + /* ID that we'll access the scene by when we want to render it + */ + id: "theScene2", + + /* Bind scene to a WebGL canvas: + */ + canvasId: "theCanvas2", + + /* You can optionally write logging to a DIV - scene will log to the console as well. + */ + loggingElementId: "theLoggingDiv2", + + nodes: [ + + /* Viewing transform specifies eye position, looking + * at the origin by default + */ + { + type: "lookAt", + eye : { x: 15, y: 10.0, z: 0 }, + look : { y:1.0 }, + up : { y: 1.0 }, + + nodes: [ + + /* Camera describes the projection + */ + { + type: "camera", + optics: { + type: "perspective", + fovy : 25.0, + aspect : 1.47, + near : 0.10, + far : 300.0 + }, + + nodes: [ + + + /* A lights node inserts point lights into the world-space. + * You can have many of these, nested within modelling transforms + * if you want to move them around. + */ + { + type: "light", + mode: "dir", + color: { r: 1.0, g: 0.5, b: 0.5 }, + diffuse: true, + specular: true, + dir: { x: 1.0, y: 1.0, z: -1.0 } + }, + + { + type: "light", + mode: "dir", + color: { r: 0.5, g: 1.0, b: 0.5 }, + diffuse: true, + specular: true, + dir: { x: 0.0, y: 1.0, z: -1.0 } + }, + + { + type: "light", + mode: "dir", + color: { r: 0.2, g: 0.2, b: 1.0 }, + diffuse: true, + specular: true, + dir: { x: -1.0, y: 0.0, z: -1.0 } + }, + + /* Next, modelling transforms to orient our teapot. See how these have IDs, + * so we can access them to set their angle attributes. + */ + { + type: "rotate", + id: "pitch2", + angle: 0.0, + z : 1.0, + + nodes: [ + { + type: "rotate", + id: "yaw2", + angle: 0.0, + y : 1.0, + + nodes: [ + { + type: "rotate", + id: "roll2", + angle: 0.0, + x : 1.0, + + nodes: [ + + /* Specify the amounts of ambient, diffuse and specular + * lights our teapot reflects + */ + { + type: "material", + emit: 0, + baseColor: { r: 0.3, g: 0.3, b: 0.9 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 100.0, + + nodes: [ + + { + type: "translate", // Example translation + x:0.0, + y:0.0, + z:0.0, + + nodes : [ + { + type: "scale", // Example scaling + x:1.0, + y:1.0, + z:1.0, + + nodes: [ + { + type : "teapot" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] +}); + + +/*---------------------------------------------------------------------- + * Scene rendering loop and mouse handler stuff follows + *---------------------------------------------------------------------*/ +var yaw2 = 0; +var pitch2 = 0; +var lastX2; +var lastY2; +var dragging2 = false; + +SceneJS.withNode("theScene2").render(); + +var canvas2 = document.getElementById("theCanvas2"); + +function mouseDown2(event) { + lastX2 = event.clientX; + lastY2 = event.clientY; + dragging2 = true; +} + +function mouseUp2() { + dragging2 = false; +} + +/* On a mouse drag, we'll re-render the scene, passing in + * incremented angles in each time. + */ +function mouseMove2(event) { + if (dragging2) { + yaw2 += (event.clientX - lastX2) * 0.2; + pitch2 += (event.clientY - lastY2) * -0.2; + + SceneJS.withNode("yaw2").set("angle", yaw2); + SceneJS.withNode("pitch2").set("angle", pitch2); + + SceneJS.withNode("theScene2").render(); + + lastX2 = event.clientX; + lastY2 = event.clientY; + + SceneJS.withNode("yaw1").set("angle", yaw2); + SceneJS.withNode("roll1").set("angle", pitch2); + SceneJS.withNode("theScene1").render(); + + SceneJS.withNode("roll3").set("angle", yaw2); + SceneJS.withNode("yaw3").set("angle", pitch2); + SceneJS.withNode("theScene3").render(); + + SceneJS.withNode("yaw4").set("angle", yaw2); + SceneJS.withNode("pitch4").set("angle", pitch2); + SceneJS.withNode("theScene4").render(); + + } +} + +canvas2.addEventListener('mousedown', mouseDown2, true); +canvas2.addEventListener('mousemove', mouseMove2, true); +canvas2.addEventListener('mouseup', mouseUp2, true); + + +SceneJS.createNode({ + + type: "scene", + + /* ID that we'll access the scene by when we want to render it + */ + id: "theScene3", + + /* Bind scene to a WebGL canvas: + */ + canvasId: "theCanvas3", + + /* You can optionally write logging to a DIV - scene will log to the console as well. + */ + loggingElementId: "theLoggingDiv3", + + nodes: [ + + /* Viewing transform specifies eye position, looking + * at the origin by default + */ + { + type: "lookAt", + eye : { x: 0, y: 15, z: 0 }, + look : { y:1.0 }, + up : { z: 1.0 }, + + nodes: [ + + /* Camera describes the projection + */ + { + type: "camera", + optics: { + type: "perspective", + fovy : 25.0, + aspect : 1.47, + near : 0.10, + far : 300.0 + }, + + nodes: [ + + + /* A lights node inserts point lights into the world-space. + * You can have many of these, nested within modelling transforms + * if you want to move them around. + */ + { + type: "light", + mode: "dir", + color: { r: 1.0, g: 0.5, b: 0.5 }, + diffuse: true, + specular: true, + dir: { x: 1.0, y: 1.0, z: -1.0 } + }, + + { + type: "light", + mode: "dir", + color: { r: 0.5, g: 1.0, b: 0.5 }, + diffuse: true, + specular: true, + dir: { x: 0.0, y: 1.0, z: -1.0 } + }, + + { + type: "light", + mode: "dir", + color: { r: 0.2, g: 0.2, b: 1.0 }, + diffuse: true, + specular: true, + dir: { x: -1.0, y: 0.0, z: -1.0 } + }, + + /* Next, modelling transforms to orient our teapot. See how these have IDs, + * so we can access them to set their angle attributes. + */ + { + type: "rotate", + id: "pitch3", + angle: 0.0, + x : 1.0, + + nodes: [ + { + type: "rotate", + id: "yaw3", + angle: 0.0, + z : 1.0, + + nodes: [ + { + type: "rotate", + id: "roll3", + angle: 0.0, + y : 1.0, + + nodes: [ + + /* Specify the amounts of ambient, diffuse and specular + * lights our teapot reflects + */ + { + type: "material", + emit: 0, + baseColor: { r: 0.3, g: 0.3, b: 0.9 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 100.0, + + nodes: [ + + { + type: "translate", // Example translation + x:0.0, + y:0.0, + z:0.0, + + nodes : [ + { + type: "scale", // Example scaling + x:1.0, + y:1.0, + z:1.0, + + nodes: [ + { + type : "teapot" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] +}); + + +/*---------------------------------------------------------------------- + * Scene rendering loop and mouse handler stuff follows + *---------------------------------------------------------------------*/ +var yaw3 = 0; +var pitch3 = 0; +var lastX3; +var lastY3; +var dragging3 = false; + +SceneJS.withNode("theScene3").render(); + +var canvas3 = document.getElementById("theCanvas3"); + +function mouseDown3(event) { + lastX3 = event.clientX; + lastY3 = event.clientY; + dragging3 = true; +} + +function mouseUp3() { + dragging3 = false; +} + +/* On a mouse drag, we'll re-render the scene, passing in + * incremented angles in each time. + */ +function mouseMove3(event) { + if (dragging3) { + yaw3 += (event.clientX - lastX3) * 0.2; + pitch3 += (event.clientY - lastY3) * -0.2; + + SceneJS.withNode("yaw3").set("angle", yaw3); + SceneJS.withNode("pitch3").set("angle", pitch3); + + SceneJS.withNode("theScene3").render(); + + lastX3 = event.clientX; + lastY3 = event.clientY; + + SceneJS.withNode("roll1").set("angle", yaw3); + SceneJS.withNode("pitch1").set("angle", pitch3); + SceneJS.withNode("theScene1").render(); + + SceneJS.withNode("pitch2").set("angle", yaw3); + SceneJS.withNode("roll2").set("angle", pitch3); + SceneJS.withNode("theScene2").render(); + + SceneJS.withNode("pitch4").set("angle", yaw3); + SceneJS.withNode("roll4").set("angle", pitch3); + SceneJS.withNode("theScene4").render(); + + } +} + +canvas3.addEventListener('mousedown', mouseDown3, true); +canvas3.addEventListener('mousemove', mouseMove3, true); +canvas3.addEventListener('mouseup', mouseUp3, true); + +SceneJS.createNode({ + + type: "scene", + + /* ID that we'll access the scene by when we want to render it + */ + id: "theScene4", + + /* Bind scene to a WebGL canvas: + */ + canvasId: "theCanvas4", + + /* You can optionally write logging to a DIV - scene will log to the console as well. + */ + loggingElementId: "theLoggingDiv4", + + nodes: [ + + /* Viewing transform specifies eye position, looking + * at the origin by default + */ + { + type: "lookAt", + eye : { x: 45, y: 30.0, z: 0 }, + look : { y:1.0 }, + up : { y: 1.0 }, + + nodes: [ + + /* Camera describes the projection + */ + { + type: "camera", + optics: { + type: "perspective", + fovy : 25.0, + aspect : 1.47, + near : 0.10, + far : 300.0 + }, + + nodes: [ + + + /* A lights node inserts point lights into the world-space. + * You can have many of these, nested within modelling transforms + * if you want to move them around. + */ + { + type: "light", + mode: "dir", + color: { r: 1.0, g: 0.5, b: 0.5 }, + diffuse: true, + specular: true, + dir: { x: 1.0, y: 1.0, z: -1.0 } + }, + + { + type: "light", + mode: "dir", + color: { r: 0.5, g: 1.0, b: 0.5 }, + diffuse: true, + specular: true, + dir: { x: 0.0, y: 1.0, z: -1.0 } + }, + + { + type: "light", + mode: "dir", + color: { r: 0.2, g: 0.2, b: 1.0 }, + diffuse: true, + specular: true, + dir: { x: -1.0, y: 0.0, z: -1.0 } + }, + + /* Next, modelling transforms to orient our teapot. See how these have IDs, + * so we can access them to set their angle attributes. + */ + { + type: "rotate", + id: "pitch4", + angle: 0.0, + z : 1.0, + + nodes: [ + { + type: "rotate", + id: "yaw4", + angle: 0.0, + y : 1.0, + + nodes: [ + { + type: "rotate", + id: "roll4", + angle: 0.0, + x : 1.0, + + nodes: [ + + /* Specify the amounts of ambient, diffuse and specular + * lights our teapot reflects + */ + { + type: "material", + emit: 0, + baseColor: { r: 0.3, g: 0.3, b: 0.9 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 100.0, + + nodes: [ + + { + type: "translate", // Example translation + x:0.0, + y:0.0, + z:0.0, + + nodes : [ + { + type: "scale", // Example scaling + x:1.0, + y:1.0, + z:1.0, + + nodes: [ + { + type : "teapot" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] +}); + + +/*---------------------------------------------------------------------- + * Scene rendering loop and mouse handler stuff follows + *---------------------------------------------------------------------*/ +var yaw4 = 0; +var pitch4 = 0; +var lastX4; +var lastY4; +var dragging4 = false; + +SceneJS.withNode("theScene4").render(); + +var canvas4 = document.getElementById("theCanvas4"); + +function mouseDown4(event) { + lastX4 = event.clientX; + lastY4 = event.clientY; + dragging4 = true; +} + +function mouseUp4() { + dragging4 = false; +} + +/* On a mouse drag, we'll re-render the scene, passing in + * incremented angles in each time. + */ +function mouseMove4(event) { + if (dragging4) { + yaw4 += (event.clientX - lastX4) * 0.2; + pitch4 += (event.clientY - lastY4) * -0.2; + + SceneJS.withNode("yaw4").set("angle", yaw4); + SceneJS.withNode("pitch4").set("angle", pitch4); + + SceneJS.withNode("theScene4").render(); + + lastX4 = event.clientX; + lastY4 = event.clientY; + + SceneJS.withNode("yaw1").set("angle", yaw4); + SceneJS.withNode("roll1").set("angle", pitch4); + SceneJS.withNode("theScene1").render(); + + SceneJS.withNode("yaw2").set("angle", yaw4); + SceneJS.withNode("pitch2").set("angle", pitch4); + SceneJS.withNode("theScene2").render(); + + SceneJS.withNode("roll3").set("angle", yaw4); + SceneJS.withNode("yaw3").set("angle", pitch4); + SceneJS.withNode("theScene3").render(); + + } +} + +canvas4.addEventListener('mousedown', mouseDown4, true); +canvas4.addEventListener('mousemove', mouseMove4, true); +canvas4.addEventListener('mouseup', mouseUp4, true); From 9995446e9dced0b543aa58e82b9c126d3c729aa6 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Tue, 1 Feb 2011 09:35:08 -0500 Subject: [PATCH 08/29] canvas1's yaw should change canvas3's roll --- src/examples/multiple-canvases/multiple-canvases.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/examples/multiple-canvases/multiple-canvases.js b/src/examples/multiple-canvases/multiple-canvases.js index 84f1748c..ec568dec 100644 --- a/src/examples/multiple-canvases/multiple-canvases.js +++ b/src/examples/multiple-canvases/multiple-canvases.js @@ -1,5 +1,5 @@ /* - Multiple Canvases SceneJS scene which renders the venerable OpenGL teapot. + Multiple Canvases SceneJS scene which renders the venerable OpenGL teapot into four canvases. Stephen Bannasch sbannasch@concord.org @@ -212,7 +212,7 @@ function mouseMove1(event) { SceneJS.withNode("roll2").set("angle", pitch1); SceneJS.withNode("theScene2").render(); - SceneJS.withNode("yaw3").set("angle", yaw1); + SceneJS.withNode("roll3").set("angle", yaw1); SceneJS.withNode("pitch3").set("angle", pitch1); SceneJS.withNode("theScene3").render(); From d183ca50924979a2596518adfd2359ecbcfc00da Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Wed, 2 Feb 2011 18:16:11 -0500 Subject: [PATCH 09/29] add Z-buffer depth to console info on scene creation example: SceneJS V0.7.9.0 initialised SceneJS.Scene binding to canvas 'theCanvas' SceneJS.Scene using webgl context with Z-buffer depth of: 24 bits SceneJS.Scene logging to element with ID 'theLoggingDiv' - logging to browser console also Scene defined: s0 ... --- src/scenejs/scene/sceneModule.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/scenejs/scene/sceneModule.js b/src/scenejs/scene/sceneModule.js index 2e2813ab..c0d95b25 100644 --- a/src/scenejs/scene/sceneModule.js +++ b/src/scenejs/scene/sceneModule.js @@ -131,6 +131,11 @@ SceneJS._sceneModule = new (function() { + canvasId + '\' failed to provide a supported WebGL context')); } + + var zBufferDepth; + zBufferDepth = context.getParameter(context.DEPTH_BITS); + SceneJS._loggingModule.info("SceneJS.Scene using webgl context with Z-buffer depth of: " + zBufferDepth + " bits"); + context.clearColor(0.0, 0.0, 0.0, 1.0); context.clearDepth(1.0); context.enable(context.DEPTH_TEST); From c978ff8375abbd038ee019f3a6a9ba0be919c277 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Wed, 2 Feb 2011 18:20:25 -0500 Subject: [PATCH 10/29] add ZBufferDepth readable attribute to scene node example: SceneJS.withNode("theScene").get("ZBufferDepth") => 24 --- src/scenejs/scene/scene.js | 11 +++++++++++ src/scenejs/scene/sceneModule.js | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/scenejs/scene/scene.js b/src/scenejs/scene/scene.js index a53c203b..0e685c5d 100755 --- a/src/scenejs/scene/scene.js +++ b/src/scenejs/scene/scene.js @@ -176,6 +176,17 @@ SceneJS.Scene.prototype.getCanvasId = function() { return this._canvasId; }; +/** Returns the Z-buffer depth in bits of the webgl context that this scene is to bound to. + */ +SceneJS.Scene.prototype.getZBufferDepth = function() { + var context; + if (this._sceneId) { + context = SceneJS._sceneModule.getSceneContext(this._sceneId); + return context.getParameter(context.DEPTH_BITS) + } + return context; +}; + /** Sets which layers are included in the next render of this scene, along with their priorities (default priority is 0) @param {{String:Number}} layers - render priority for each layer defined in scene diff --git a/src/scenejs/scene/sceneModule.js b/src/scenejs/scene/sceneModule.js index c0d95b25..7076f520 100644 --- a/src/scenejs/scene/sceneModule.js +++ b/src/scenejs/scene/sceneModule.js @@ -230,6 +230,17 @@ SceneJS._sceneModule = new (function() { return scene.canvas.canvas; }; + /** Returns the webgl context element the given scene is bound to + * @private + */ + this.getSceneContext = function(sceneId) { + var scene = scenes[sceneId]; + if (!scene) { + throw SceneJS._errorModule.fatalError("Scene not defined: '" + sceneId + "'"); + } + return scene.canvas.context; + }; + /** Returns all registered scenes * @private */ From 5711b70bd2666b394e6a895c6a2dee3799691d35 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Wed, 2 Feb 2011 23:02:41 -0500 Subject: [PATCH 11/29] reset canvas size for webgl when specified with css When the size of a canvas element is set with css styles instead of specifying the size in the element itself the canvas displays using the css styles but reports a default height and width (300 x 150). When creating a webgl context the canvas attributes height and width are used so if the canvas size is specified with a css style the resulting webgl viewport will be incorrect. --- src/scenejs/scene/sceneModule.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/scenejs/scene/sceneModule.js b/src/scenejs/scene/sceneModule.js index 2e2813ab..722c1c95 100644 --- a/src/scenejs/scene/sceneModule.js +++ b/src/scenejs/scene/sceneModule.js @@ -97,6 +97,12 @@ SceneJS._sceneModule = new (function() { } } } + + // If the canvas uses css styles to specify the sizes make sure the basic + // width and height attributes match or the WebGL context will use 300 x 150 + canvas.width = canvas.clientWidth; + canvas.height = canvas.clientHeight; + var context; var contextNames = SceneJS.SUPPORTED_WEBGL_CONTEXT_NAMES; for (var i = 0; (!context) && i < contextNames.length; i++) { From 02b3abe6b379140c2aece93e30318b11e97205a1 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Fri, 4 Feb 2011 00:46:23 -0500 Subject: [PATCH 12/29] new SceneJS.Disk geometry primitive Example: Definition of solid disk that extends 6 units radially from the Y-axis, is 2 units high in the Y-axis and is made up of 48 longitudinal slices: var c = new SceneJS.Disk({ radius: 6, // Optional radius (1 is default) height: 2, // Optional height (1 is default) rings: 48 // Optional number of longitudinal slices (30 is default) }) --- build.xml | 2 + src/scenejs/geometry/objects/disk.js | 126 +++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 src/scenejs/geometry/objects/disk.js diff --git a/build.xml b/build.xml index 4b40e396..784588b3 100755 --- a/build.xml +++ b/build.xml @@ -94,6 +94,7 @@ + @@ -221,6 +222,7 @@ + diff --git a/src/scenejs/geometry/objects/disk.js b/src/scenejs/geometry/objects/disk.js new file mode 100644 index 00000000..b07495a2 --- /dev/null +++ b/src/scenejs/geometry/objects/disk.js @@ -0,0 +1,126 @@ +SceneJS._namespace("SceneJS.objects"); + +/** + * @class A scene node that defines a disk geometry. + *

The geometry is complete with normals for shading and one layer of UV coordinates for + * texture-mapping. It can also be configured as solid (default), to construct it from + * triangles with normals for shading and one layer of UV coordinates for texture-mapping + * When not solid, it will be a wireframe drawn as line segments.

+ *

Example Usage

Definition of solid disk that extends 6 units radially from the Y-axis, + * is 2 units high in the Y-axis and is made up of 48 longitudinal slices:


+ * var c = new SceneJS.Disk({
+ *          radius: 6,      // Optional radius (1 is default)
+ *          height: 2,      // Optional height (1 is default)
+ *          rings: 48       // Optional number of longitudinal slices (30 is default)
+ *     })
+ * 
+ * @extends SceneJS.Geometry + * @since Version 0.7.9 + * @constructor + * Create a new SceneJS.Disk + * @param {Object} [cfg] Static configuration object + * @param {float} [cfg.radius=1.0] radius extending from Y-axis + * @param {float} [cfg.height=1.0] height on Y-axis + * @param {float} [cfg.rings=30] number of longitudinal slices + * @param {...SceneJS.Node} [childNodes] Child nodes + */ +SceneJS.Disk = SceneJS.createNodeType("disk", "geometry"); + +// @private +SceneJS.Disk.prototype._init = function(params) { + this._attr.nodeType = "disk"; + + var radius = params.radius || 1; + var height = params.height || 1; + var rings = params.rings || 30; + var slices = 2; + + /* Resource ID ensures that we reuse any sphere that has already been created with + * these parameters instead of wasting memory + */ + this._resource = "disk_" + radius + "_" + height + "_" + slices; + + /* Callback that does the creation in case we can't find matching sphere to reuse + */ + this._create = function() { + var positions = []; + var normals = []; + var uv = []; + + var ybot = height * -0.5; + var ytop = height * 0.5; + + for (var ringNum = 0; ringNum <= rings; ringNum++) { + var phi = ringNum * 2 * Math.PI / rings; + var sinPhi = Math.sin(phi); + var cosPhi = Math.cos(phi); + + var x = cosPhi; + var z = sinPhi; + var u = 1 - (ringNum / rings); + var v = 0.5; + + normals.push(-x); + normals.push(-ybot); + normals.push(-z); + uv.push(u); + uv.push(v); + positions.push(radius * x); + positions.push(ybot); + positions.push(radius * z); + + normals.push(-x); + normals.push(-ytop); + normals.push(-z); + uv.push(u); + uv.push(v); + positions.push(radius * x); + positions.push(ytop); + positions.push(radius * z); + } + + var centerBot = rings * 2 + 2; + + normals.push(0, -1.0, 0); + uv.push(1, 0.5); + positions.push(0, ybot, 0); + + var centerTop = rings * 2 + 3; + + normals.push(0, 1.0, 0); + uv.push(1, 0.5); + positions.push(0, ytop, 0); + + var indices = []; + + for (var ringNum = 0; ringNum < rings; ringNum++) { + var index = ringNum * 2; + indices.push(index); + indices.push(index + 1); + indices.push(index + 2); + + indices.push(index + 1); + indices.push(index + 2); + indices.push(index + 3); + } + + for (var ringNum = 0; ringNum < rings; ringNum++) { + var index = ringNum * 2; + indices.push(index); + indices.push(index + 2); + indices.push(centerBot); + + indices.push(index + 1); + indices.push(index + 3); + indices.push(centerTop); + } + + return { + primitive : "triangles", + positions : positions, + normals: normals, + uv : uv, + indices : indices + }; + }; +}; From 80c58d31e0a02f160d0152e7e77be1a3306a8cb6 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Fri, 4 Feb 2011 00:47:19 -0500 Subject: [PATCH 13/29] primitive-objects example: sphere, box, and disk solid and wireframe renderings --- src/examples/primitive-objects/index.html | 52 +++ .../primitive-objects/primitive-objects.js | 300 ++++++++++++++++++ 2 files changed, 352 insertions(+) create mode 100644 src/examples/primitive-objects/index.html create mode 100644 src/examples/primitive-objects/primitive-objects.js diff --git a/src/examples/primitive-objects/index.html b/src/examples/primitive-objects/index.html new file mode 100644 index 00000000..498a23ae --- /dev/null +++ b/src/examples/primitive-objects/index.html @@ -0,0 +1,52 @@ + + + + + + + + +
+ +
+ +

This example requires a browser that supports the + HTML5 + <canvas> feature.

+
+
+

Primitive Objects: Sphere, Box, Disk

+ +

This example shows three of the basic primitive renderable objects: sphere, box, and disk + rendered in both solid and wireframe.

+ +
+
+

Log

+ +
+
+
+
+ + + \ No newline at end of file diff --git a/src/examples/primitive-objects/primitive-objects.js b/src/examples/primitive-objects/primitive-objects.js new file mode 100644 index 00000000..2acb1607 --- /dev/null +++ b/src/examples/primitive-objects/primitive-objects.js @@ -0,0 +1,300 @@ +/** + * SceneJS Example - Primitive objects: sphere, box, disk + * + * Lindsay Kay + * lindsay.kay AT xeolabs.com + * March 2010 + * + */ +SceneJS.createNode({ + + type: "scene", + id: "theScene", + canvasId: 'theCanvas', + loggingElementId: "theLoggingDiv", + + nodes: [ + { + type: "lookAt", + eye : { x: 0, y: 2, z: -22}, + look : { x : 0.0, y : -1.0, z : 0 }, + up : { x: 0.0, y: 1.0, z: 0.0 }, + + nodes: [ + { + type: "camera", + optics: { + type: "perspective", + fovy : 25.0, + aspect : 1.47, + near : 0.10, + far : 300.0 + }, + + nodes: [ + { + type: "light", + mode: "dir", + color: { r: 1.0, g: 1.0, b: 1.0 }, + diffuse: true, + specular: true, + dir: { x: 1.0, y: 1.0, z: -1.0 } + }, + { + type: "light", + mode: "dir", + color: {r: 1.0, g: 1.0, b: 1.0}, + diffuse: true, + specular: true, + dir: { x: 0.0, y: 1.0, z: -1.0 } + }, + { + type: "light", + mode: "dir", + color: {r: 1.0, g: 1.0, b: 1.0}, + diffuse: true, + specular: true, + dir: { x: -1.0, y: 0.0, z: -1.0 } + }, + + { + type: "translate", + x: -4.0, + y: 2.25, + nodes: [ + + { + type: "rotate", + id: "sphere-rotate", + angle: 0, + x: 0.2, + y: 1.0, + + nodes: [ + + { + type: "material", + baseColor: { r: 0.3, g: 0.3, b: 0.9 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + { + type: "sphere", + slices: 6, + rings: 12 + } + ] + } + ] + } + ] + }, + + { + type: "translate", + x: 4.0, + y: 2.25, + + nodes: [ + + { + type: "rotate", + id: "disk-rotate", + angle: 0, + z: 0.2, + x: 1.0, + + nodes: [ + + { + type: "material", + baseColor: { r: 0.3, g: 0.9, b: 0.3 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + { + type: "disk", + rings: 12, + } + ] + } + ] + } + ] + }, + + { + type: "translate", + x: 0.0, + y: 0.5, + + nodes: [ + + { + type: "rotate", + id: "box-rotate", + angle: 0, + x: 0.2, + z: 1.0, + + nodes: [ + + { + type: "material", + baseColor: { r: 0.9, g: 0.3, b: 0.3 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + { + type: "box" + } + ] + } + ] + } + ] + }, + + + { + type: "renderer", + + wireframe: true, + lineWidth: 1, + + nodes: [ + + { + type: "scale", + x: 1.5, + y: 1.5, + z: 1.5, + + nodes: [ + + { + type: "material", + baseColor: { r: 1.0, g: 1.0, b: 1.0 }, + specularColor: { r: 1.0, g: 1.0, b: 1.0 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + + { + type: "translate", + x: -3.0, + y: -0.5, + nodes: [ + + { + type: "sphere", + slices: 6, + rings: 12 + } + ] + }, + + { + type: "translate", + x: 3.25, + y: -0.5, + nodes: [ + + { + type: "disk", + rings: 12, + } + ] + }, + + { + type: "translate", + x: 0, + y: -2.0, + + nodes: [ + + { + type: "box" + } + ] + } + ] + } + ] + } + ] + } + + // + // { + // type: "translate", + // x: 2.5, + // y: 1.5, + // z: 1, + // + // nodes: [ + // + // { + // type: "material", + // baseColor: { r: 0.3, g: 0.9, b: 0.3 }, + // specularColor: { r: 0.2, g: 0.4, b: 0.3 }, + // specular: 0.9, + // shine: 6.0, + // + // nodes: [ + // + // { + // type: "rotate", + // angle: 30.0, + // x : 1.0, + // y : 1.5, + // + // nodes: [ + // + // { + // type: "disk" + // } + // ] + // } + // ] + // } + // ] + // } + ] + } + ] + } + ] +}); + +SceneJS.withNode("theScene").render(); + +var disk_rotate = SceneJS.withNode("disk-rotate") +var sphere_rotate = SceneJS.withNode("sphere-rotate") +var box_rotate = SceneJS.withNode("box-rotate") + +window.render = function() { + var angle = disk_rotate.get("angle") + 0.3; + disk_rotate.set("angle", angle); + sphere_rotate.set("angle", angle); + box_rotate.set("angle", angle); + SceneJS.withNode("theScene").render(); +}; + +SceneJS.bind("error", function() { + window.clearInterval(pInterval); +}); + +SceneJS.bind("reset", function() { + window.clearInterval(pInterval); +}); + +var pInterval = setInterval("window.render()", 30); From 08e76edc23d55baac4308eb88d10c49883993407 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Fri, 4 Feb 2011 02:36:11 -0500 Subject: [PATCH 14/29] add optional inner_radius param to SceneJS.disk Example json: { type: "disk", radius: 1.0, inner_radius: 0.5, rings: 12, } --- src/scenejs/geometry/objects/disk.js | 138 ++++++++++++++++++++------- 1 file changed, 103 insertions(+), 35 deletions(-) diff --git a/src/scenejs/geometry/objects/disk.js b/src/scenejs/geometry/objects/disk.js index b07495a2..4d7ee088 100644 --- a/src/scenejs/geometry/objects/disk.js +++ b/src/scenejs/geometry/objects/disk.js @@ -7,11 +7,11 @@ SceneJS._namespace("SceneJS.objects"); * triangles with normals for shading and one layer of UV coordinates for texture-mapping * When not solid, it will be a wireframe drawn as line segments.

*

Example Usage

Definition of solid disk that extends 6 units radially from the Y-axis, - * is 2 units high in the Y-axis and is made up of 48 longitudinal slices:


+ * is 2 units high in the Y-axis and is made up of 48 longitudinal rings:


  * var c = new SceneJS.Disk({
  *          radius: 6,      // Optional radius (1 is default)
  *          height: 2,      // Optional height (1 is default)
- *          rings: 48       // Optional number of longitudinal slices (30 is default)
+ *          rings: 48       // Optional number of longitudinal rings (30 is default)
  *     })
  * 
* @extends SceneJS.Geometry @@ -21,7 +21,7 @@ SceneJS._namespace("SceneJS.objects"); * @param {Object} [cfg] Static configuration object * @param {float} [cfg.radius=1.0] radius extending from Y-axis * @param {float} [cfg.height=1.0] height on Y-axis - * @param {float} [cfg.rings=30] number of longitudinal slices + * @param {float} [cfg.rings=30] number of longitudinal rings * @param {...SceneJS.Node} [childNodes] Child nodes */ SceneJS.Disk = SceneJS.createNodeType("disk", "geometry"); @@ -33,14 +33,17 @@ SceneJS.Disk.prototype._init = function(params) { var radius = params.radius || 1; var height = params.height || 1; var rings = params.rings || 30; - var slices = 2; + var inner_radius = params.inner_radius || 0; + if (inner_radius > radius) { + inner_radius = radius + } /* Resource ID ensures that we reuse any sphere that has already been created with * these parameters instead of wasting memory */ - this._resource = "disk_" + radius + "_" + height + "_" + slices; + this._resource = "disk_" + radius + "_" + height + "_" + rings + "_" + inner_radius; - /* Callback that does the creation in case we can't find matching sphere to reuse + /* Callback that does the creation in case we can't find matching disk to reuse */ this._create = function() { var positions = []; @@ -77,44 +80,109 @@ SceneJS.Disk.prototype._init = function(params) { positions.push(radius * x); positions.push(ytop); positions.push(radius * z); + + if (inner_radius > 0) { + + normals.push(-x); + normals.push(-ytop); + normals.push(-z); + uv.push(u); + uv.push(v); + positions.push(inner_radius * x); + positions.push(ytop); + positions.push(inner_radius * z); + + normals.push(-x); + normals.push(-ybot); + normals.push(-z); + uv.push(u); + uv.push(v); + positions.push(inner_radius * x); + positions.push(ybot); + positions.push(inner_radius * z); + } + } - var centerBot = rings * 2 + 2; + var indices = []; - normals.push(0, -1.0, 0); - uv.push(1, 0.5); - positions.push(0, ybot, 0); + if (inner_radius > 0) { + + for (var ringNum = 0; ringNum < rings; ringNum++) { + var index = ringNum * 4; - var centerTop = rings * 2 + 3; - - normals.push(0, 1.0, 0); - uv.push(1, 0.5); - positions.push(0, ytop, 0); + indices.push(index + 0); + indices.push(index + 1); + indices.push(index + 4); - var indices = []; - - for (var ringNum = 0; ringNum < rings; ringNum++) { - var index = ringNum * 2; - indices.push(index); - indices.push(index + 1); - indices.push(index + 2); - - indices.push(index + 1); - indices.push(index + 2); - indices.push(index + 3); - } + indices.push(index + 1); + indices.push(index + 4); + indices.push(index + 5); + + indices.push(index + 1); + indices.push(index + 2); + indices.push(index + 5); + + indices.push(index + 2); + indices.push(index + 5); + indices.push(index + 6); + + indices.push(index + 2); + indices.push(index + 3); + indices.push(index + 6); + + indices.push(index + 3); + indices.push(index + 6); + indices.push(index + 7); - for (var ringNum = 0; ringNum < rings; ringNum++) { - var index = ringNum * 2; - indices.push(index); - indices.push(index + 2); - indices.push(centerBot); + indices.push(index + 3); + indices.push(index + 0); + indices.push(index + 7); + + indices.push(index + 0); + indices.push(index + 7); + indices.push(index + 4); + } + + } else { + + var centerBot = rings * 2 + 2; + + normals.push(0, -1.0, 0); + uv.push(1, 0.5); + positions.push(0, ybot, 0); + + var centerTop = rings * 2 + 3; + + normals.push(0, 1.0, 0); + uv.push(1, 0.5); + positions.push(0, ytop, 0); + + for (var ringNum = 0; ringNum < rings; ringNum++) { + var index = ringNum * 2; + indices.push(index); + indices.push(index + 1); + indices.push(index + 2); + + indices.push(index + 1); + indices.push(index + 2); + indices.push(index + 3); + } + + for (var ringNum = 0; ringNum < rings; ringNum++) { + var index = ringNum * 2; + indices.push(index); + indices.push(index + 2); + indices.push(centerBot); + + indices.push(index + 1); + indices.push(index + 3); + indices.push(centerTop); + } - indices.push(index + 1); - indices.push(index + 3); - indices.push(centerTop); } + return { primitive : "triangles", positions : positions, From d924b63a745fae8795f66cd09b2b9f28146c2b9b Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Fri, 4 Feb 2011 02:38:01 -0500 Subject: [PATCH 15/29] show ring-type disc in primitive-objects example Example json: { type: "disk", radius: 1.0, inner_radius: 0.5, rings: 12, } --- src/examples/primitive-objects/primitive-objects.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/examples/primitive-objects/primitive-objects.js b/src/examples/primitive-objects/primitive-objects.js index 2acb1607..f3feb4e1 100644 --- a/src/examples/primitive-objects/primitive-objects.js +++ b/src/examples/primitive-objects/primitive-objects.js @@ -118,6 +118,8 @@ SceneJS.createNode({ nodes: [ { type: "disk", + radius: 1.0, + inner_radius: 0.5, rings: 12, } ] @@ -209,6 +211,8 @@ SceneJS.createNode({ { type: "disk", + radius: 1.0, + inner_radius: 0.5, rings: 12, } ] From 247c6bbb7c3dc0a9f59edfb9a7699f8896af0334 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Fri, 4 Feb 2011 02:47:10 -0500 Subject: [PATCH 16/29] update documentation for ring usage of SceneJS.disk --- src/scenejs/geometry/objects/disk.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/scenejs/geometry/objects/disk.js b/src/scenejs/geometry/objects/disk.js index 4d7ee088..20b30906 100644 --- a/src/scenejs/geometry/objects/disk.js +++ b/src/scenejs/geometry/objects/disk.js @@ -9,9 +9,10 @@ SceneJS._namespace("SceneJS.objects"); *

Example Usage

Definition of solid disk that extends 6 units radially from the Y-axis, * is 2 units high in the Y-axis and is made up of 48 longitudinal rings:


  * var c = new SceneJS.Disk({
- *          radius: 6,      // Optional radius (1 is default)
- *          height: 2,      // Optional height (1 is default)
- *          rings: 48       // Optional number of longitudinal rings (30 is default)
+ *          radius: 6,       // Optional radius (1 is default)
+ *          inner_radius: 3  // Optional inner_radius results in ring (default is 0)
+ *          height: 2,       // Optional height (1 is default)
+ *          rings: 48        // Optional number of longitudinal rings (30 is default)
  *     })
  * 
* @extends SceneJS.Geometry @@ -20,6 +21,7 @@ SceneJS._namespace("SceneJS.objects"); * Create a new SceneJS.Disk * @param {Object} [cfg] Static configuration object * @param {float} [cfg.radius=1.0] radius extending from Y-axis + * @param {float} [cfg.inner_radius=0] inner radius extending from Y-axis * @param {float} [cfg.height=1.0] height on Y-axis * @param {float} [cfg.rings=30] number of longitudinal rings * @param {...SceneJS.Node} [childNodes] Child nodes From 3d9d8745637583a114eeea681eb22f99e284739f Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Fri, 4 Feb 2011 14:47:13 -0500 Subject: [PATCH 17/29] SceneJS.disk supports optional semiMajorAxis attribute The optional semiMajorAxis attribute is used to create elliptical disks. The default value for the semiMajorAxis attribute is 1 which results in a circular shape. The semiMajorAxis attribute is normalized to a unit sized radius. To create an elliptical disk with a real semi-major-axis of 9 units use the following node attributes: { node: "disk", radius: 6, semiMajorAxis: 1.5 } --- .../primitive-objects/primitive-objects.js | 2 ++ src/scenejs/geometry/objects/disk.js | 22 ++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/examples/primitive-objects/primitive-objects.js b/src/examples/primitive-objects/primitive-objects.js index f3feb4e1..cb1496d0 100644 --- a/src/examples/primitive-objects/primitive-objects.js +++ b/src/examples/primitive-objects/primitive-objects.js @@ -120,6 +120,7 @@ SceneJS.createNode({ type: "disk", radius: 1.0, inner_radius: 0.5, + semiMajorAxis: 1.5, rings: 12, } ] @@ -213,6 +214,7 @@ SceneJS.createNode({ type: "disk", radius: 1.0, inner_radius: 0.5, + semiMajorAxis: 1.5, rings: 12, } ] diff --git a/src/scenejs/geometry/objects/disk.js b/src/scenejs/geometry/objects/disk.js index 20b30906..d58e5bb4 100644 --- a/src/scenejs/geometry/objects/disk.js +++ b/src/scenejs/geometry/objects/disk.js @@ -7,12 +7,14 @@ SceneJS._namespace("SceneJS.objects"); * triangles with normals for shading and one layer of UV coordinates for texture-mapping * When not solid, it will be a wireframe drawn as line segments.

*

Example Usage

Definition of solid disk that extends 6 units radially from the Y-axis, - * is 2 units high in the Y-axis and is made up of 48 longitudinal rings:


+ * is elliptical in shape with a normalized semiMajorAxis of 1.5, is 2 units high in the Y-axis and 
+ * is made up of 48 longitudinal rings:


  * var c = new SceneJS.Disk({
- *          radius: 6,       // Optional radius (1 is default)
- *          inner_radius: 3  // Optional inner_radius results in ring (default is 0)
- *          height: 2,       // Optional height (1 is default)
- *          rings: 48        // Optional number of longitudinal rings (30 is default)
+ *          radius: 6,          // Optional radius (1 is default)
+ *          inner_radius: 3     // Optional inner_radius results in ring (default is 0)
+ *          semiMajorAxis: 1.5  // Optional semiMajorAxis results in ellipse (default is 1 which is a circle)
+ *          height: 2,          // Optional height (1 is default)
+ *          rings: 48           // Optional number of longitudinal rings (30 is default)
  *     })
  * 
* @extends SceneJS.Geometry @@ -22,7 +24,8 @@ SceneJS._namespace("SceneJS.objects"); * @param {Object} [cfg] Static configuration object * @param {float} [cfg.radius=1.0] radius extending from Y-axis * @param {float} [cfg.inner_radius=0] inner radius extending from Y-axis - * @param {float} [cfg.height=1.0] height on Y-axis + * @param {float} [cfg.inner_radius=0] inner radius extending from Y-axis + * @param {float} [cfg.semiMajorAxis=1.0] values other than one generate an ellipse * @param {float} [cfg.rings=30] number of longitudinal rings * @param {...SceneJS.Node} [childNodes] Child nodes */ @@ -39,6 +42,9 @@ SceneJS.Disk.prototype._init = function(params) { if (inner_radius > radius) { inner_radius = radius } + + var semiMajorAxis = params.semiMajorAxis || 1; + var semiMinorAxis = 1 / semiMajorAxis; /* Resource ID ensures that we reuse any sphere that has already been created with * these parameters instead of wasting memory @@ -57,8 +63,8 @@ SceneJS.Disk.prototype._init = function(params) { for (var ringNum = 0; ringNum <= rings; ringNum++) { var phi = ringNum * 2 * Math.PI / rings; - var sinPhi = Math.sin(phi); - var cosPhi = Math.cos(phi); + var sinPhi = semiMinorAxis * Math.sin(phi); + var cosPhi = semiMajorAxis * Math.cos(phi); var x = cosPhi; var z = sinPhi; From ee43f8f91041a72f4ed0cc70eb00d696357a3eb7 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Sun, 6 Feb 2011 23:40:40 -0500 Subject: [PATCH 18/29] SceneJS.disk attribute inner_radius => innerRadius to follow convention in rest of codebase. --- src/scenejs/geometry/objects/disk.js | 39 ++++++++++++++++++---------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/scenejs/geometry/objects/disk.js b/src/scenejs/geometry/objects/disk.js index d58e5bb4..af3832bd 100644 --- a/src/scenejs/geometry/objects/disk.js +++ b/src/scenejs/geometry/objects/disk.js @@ -11,7 +11,7 @@ SceneJS._namespace("SceneJS.objects"); * is made up of 48 longitudinal rings:


  * var c = new SceneJS.Disk({
  *          radius: 6,          // Optional radius (1 is default)
- *          inner_radius: 3     // Optional inner_radius results in ring (default is 0)
+ *          innerRadius: 3     // Optional innerRadius results in ring (default is 0)
  *          semiMajorAxis: 1.5  // Optional semiMajorAxis results in ellipse (default is 1 which is a circle)
  *          height: 2,          // Optional height (1 is default)
  *          rings: 48           // Optional number of longitudinal rings (30 is default)
@@ -23,8 +23,8 @@ SceneJS._namespace("SceneJS.objects");
  * Create a new SceneJS.Disk
  * @param {Object} [cfg] Static configuration object
  * @param {float} [cfg.radius=1.0] radius extending from Y-axis
- * @param {float} [cfg.inner_radius=0] inner radius extending from Y-axis
- * @param {float} [cfg.inner_radius=0] inner radius extending from Y-axis
+ * @param {float} [cfg.innerRadius=0] inner radius extending from Y-axis
+ * @param {float} [cfg.innerRadius=0] inner radius extending from Y-axis
  * @param {float} [cfg.semiMajorAxis=1.0] values other than one generate an ellipse
  * @param {float} [cfg.rings=30]  number of longitudinal rings
  * @param {...SceneJS.Node} [childNodes] Child nodes
@@ -38,9 +38,9 @@ SceneJS.Disk.prototype._init = function(params) {
     var radius = params.radius || 1;
     var height = params.height || 1;
     var rings =  params.rings || 30;
-    var inner_radius = params.inner_radius || 0;
-    if (inner_radius > radius) {
-        inner_radius = radius
+    var innerRadius = params.innerRadius || 0;
+    if (innerRadius > radius) {
+        innerRadius = radius
     }
     
     var semiMajorAxis =  params.semiMajorAxis || 1;
@@ -89,35 +89,46 @@ SceneJS.Disk.prototype._init = function(params) {
              positions.push(ytop);
              positions.push(radius * z);
              
-             if (inner_radius > 0) {
+             if (innerRadius > 0) {
             
                  normals.push(-x);
                  normals.push(-ytop);
                  normals.push(-z);
                  uv.push(u);
                  uv.push(v);
-                 positions.push(inner_radius * x);
+                 positions.push(innerRadius * x);
                  positions.push(ytop);
-                 positions.push(inner_radius * z);
+                 positions.push(innerRadius * z);
                  
                  normals.push(-x);
                  normals.push(-ybot);
                  normals.push(-z);
                  uv.push(u);
                  uv.push(v);
-                 positions.push(inner_radius * x);
+                 positions.push(innerRadius * x);
                  positions.push(ybot);
-                 positions.push(inner_radius * z);
+                 positions.push(innerRadius * z);
             }              
                 
          }
          
          var indices = [];
          
-         if (inner_radius > 0) {
-             
+         if (innerRadius > 0) {
+             var index;
              for (var ringNum = 0; ringNum < rings; ringNum++) {
-                 var index = ringNum * 4;
+                 if (ringNum >= ringLimit) {
+                     // We aren't sweeping the whole way around so create triangles to cap the ends. 
+                     // Example: indices for a disk with fours ring-segments when only two are drawn.
+                     //   0,1,2   0,2,3  8,9,10  8,10,11
+                     indices.push(0, 1, 2);
+                     indices.push(0, 2, 3);                     
+                     index = ringLimit * 4;
+                     indices.push(index, index+ 1, index + 2);
+                     indices.push(index, index+ 2, index + 3);
+                     break;
+                 }
+                 index = ringNum * 4;
 
                  indices.push(index + 0);
                  indices.push(index + 1);

From da9dbac5f3052249bf4c191fd1e481d213b7b4a6 Mon Sep 17 00:00:00 2001
From: Stephen Bannasch 
Date: Sun, 6 Feb 2011 23:47:04 -0500
Subject: [PATCH 19/29] new: SceneJS.disk sweep attribute

The sweep attribute is normalized to 1 and specifies
an optional rotational extrusion (1 is default).
---
 src/scenejs/geometry/objects/disk.js | 41 ++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 11 deletions(-)

diff --git a/src/scenejs/geometry/objects/disk.js b/src/scenejs/geometry/objects/disk.js
index af3832bd..e13d2bf5 100644
--- a/src/scenejs/geometry/objects/disk.js
+++ b/src/scenejs/geometry/objects/disk.js
@@ -10,11 +10,12 @@ SceneJS._namespace("SceneJS.objects");
  * is elliptical in shape with a normalized semiMajorAxis of 1.5, is 2 units high in the Y-axis and 
  * is made up of 48 longitudinal rings:


  * var c = new SceneJS.Disk({
- *          radius: 6,          // Optional radius (1 is default)
- *          innerRadius: 3     // Optional innerRadius results in ring (default is 0)
- *          semiMajorAxis: 1.5  // Optional semiMajorAxis results in ellipse (default is 1 which is a circle)
- *          height: 2,          // Optional height (1 is default)
- *          rings: 48           // Optional number of longitudinal rings (30 is default)
+ *          radius: 6,           // Optional radius (1 is default)
+ *          innerRadius: 4,      // Optional innerRadius results in ring (default is 0)
+ *          semiMajorAxis: 1.5,  // Optional semiMajorAxis results in ellipse (default of 1 creates circle)
+ *          height: 2,           // Optional height (1 is default)
+ *          rings: 48,           // Optional number of longitudinal rings (30 is default)
+ *          sweep: 0.75,         // Optional rotational extrusion (1 is default)
  *     })
  * 
* @extends SceneJS.Geometry @@ -27,6 +28,7 @@ SceneJS._namespace("SceneJS.objects"); * @param {float} [cfg.innerRadius=0] inner radius extending from Y-axis * @param {float} [cfg.semiMajorAxis=1.0] values other than one generate an ellipse * @param {float} [cfg.rings=30] number of longitudinal rings + * @param {float} [cfg.sweep=1] rotational extrusion default is 1 * @param {...SceneJS.Node} [childNodes] Child nodes */ SceneJS.Disk = SceneJS.createNodeType("disk", "geometry"); @@ -46,10 +48,17 @@ SceneJS.Disk.prototype._init = function(params) { var semiMajorAxis = params.semiMajorAxis || 1; var semiMinorAxis = 1 / semiMajorAxis; + var sweep = params.sweep || 1; + if (sweep > 1) { + sweep = 1 + } + + var ringLimit = rings * sweep; + /* Resource ID ensures that we reuse any sphere that has already been created with * these parameters instead of wasting memory */ - this._resource = "disk_" + radius + "_" + height + "_" + rings + "_" + inner_radius; + this._resource = "disk_" + radius + "_" + height + "_" + rings + "_" + innerRadius + "_" + semiMajorAxis + "_" + sweep; /* Callback that does the creation in case we can't find matching disk to reuse */ @@ -60,8 +69,9 @@ SceneJS.Disk.prototype._init = function(params) { var ybot = height * -0.5; var ytop = height * 0.5; - + for (var ringNum = 0; ringNum <= rings; ringNum++) { + if (ringNum > ringLimit) break; var phi = ringNum * 2 * Math.PI / rings; var sinPhi = semiMinorAxis * Math.sin(phi); var cosPhi = semiMajorAxis * Math.cos(phi); @@ -165,19 +175,18 @@ SceneJS.Disk.prototype._init = function(params) { } else { - var centerBot = rings * 2 + 2; - normals.push(0, -1.0, 0); uv.push(1, 0.5); positions.push(0, ybot, 0); - - var centerTop = rings * 2 + 3; + var centerBot = ringLimit * 2 + 2; normals.push(0, 1.0, 0); uv.push(1, 0.5); positions.push(0, ytop, 0); + var centerTop = ringLimit * 2 + 3; for (var ringNum = 0; ringNum < rings; ringNum++) { + if (ringNum >= ringLimit) break; var index = ringNum * 2; indices.push(index); indices.push(index + 1); @@ -189,6 +198,7 @@ SceneJS.Disk.prototype._init = function(params) { } for (var ringNum = 0; ringNum < rings; ringNum++) { + if (ringNum >= ringLimit) break; var index = ringNum * 2; indices.push(index); indices.push(index + 2); @@ -199,6 +209,15 @@ SceneJS.Disk.prototype._init = function(params) { indices.push(centerTop); } + if (rings >= ringLimit) { + // We aren't sweeping the whole way around so create triangles to cap the ends. + // Example: indices for a disk with fours ring-segments when only two are drawn. + // 0,1,2 0,2,3 8,9,10 8,10,11 + index = ringLimit * 2; + indices.push(0, 1, index); + indices.push(1, index + 1, index); + } + } From 4093782c65106b983fa3408d899aacff7b265c52 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Sun, 6 Feb 2011 23:52:30 -0500 Subject: [PATCH 20/29] new: SceneJS.sphere sweep and semiMajorAxis attributes The optional sweep attribute is normalized to 1 and specifies an optional rotational extrusion (1 is default). The optional semiMajorAxis attribute results in elliptical sphere when changed from the default of 1. --- src/scenejs/geometry/objects/sphere.js | 46 ++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/scenejs/geometry/objects/sphere.js b/src/scenejs/geometry/objects/sphere.js index 392a0f84..9ba3e446 100644 --- a/src/scenejs/geometry/objects/sphere.js +++ b/src/scenejs/geometry/objects/sphere.js @@ -5,8 +5,10 @@ *

Example Usage

Definition of sphere with a radius of 6 units:


  * var c = new SceneJS.Sphere({
  *			radius: 6
- *          slices: 30,     // Optional number of longitudinal slices (30 is default)
- *          rings: 30      // Optional number of latitudinal slices (30 is default)
+ *          slices: 30,          // Optional number of longitudinal slices (30 is default)
+ *          rings: 30,           // Optional number of latitudinal slices (30 is default)
+ *          semiMajorAxis: 1.5,  // Optional semiMajorAxis results in elliptical sphere (default of 1 creates sphere)
+ *          sweep: 0.75,         // Optional rotational extrusion (1 is default)
  *     })
  * 
* @extends SceneJS.Geometry @@ -16,6 +18,8 @@ * @param {Object} [cfg] Static configuration object * @param {float} [cfg.slices=30] Number of longitudinal slices * @param {float} [cfg.rings=30] Number of longitudinal slices + * @param {float} [cfg.semiMajorAxis=1.0] values other than one generate an elliptical sphere + * @param {float} [cfg.sweep=1] rotational extrusion default is 1 * @param {function(SceneJS.Data):Object} [fn] Dynamic configuration function * @param {...SceneJS.Node} [childNodes] Child nodes */ @@ -26,11 +30,22 @@ SceneJS.Sphere.prototype._init = function(params) { var slices = params.slices || 30; var rings = params.rings || 30; var radius = params.radius || 1; + + var semiMajorAxis = params.semiMajorAxis || 1; + var semiMinorAxis = 1 / semiMajorAxis; + + var sweep = params.sweep || 1; + if (sweep > 1) { + sweep = 1 + } + + var ringLimit = rings * sweep; + /* Resource ID ensures that we reuse any sphere that has already been created with * these parameters instead of wasting memory */ - this._resource = "sphere_" + radius + "_" + rings + "_" + slices; + this._resource = "sphere_" + radius + "_" + rings + "_" + slices + "_" + innerRadius + "_" + semiMajorAxis + "_" + sweep; /* Callback that does the creation in case we can't find matching sphere to reuse */ @@ -44,9 +59,10 @@ SceneJS.Sphere.prototype._init = function(params) { var cosTheta = Math.cos(theta); for (var ringNum = 0; ringNum <= rings; ringNum++) { + if (ringNum > ringLimit) break; var phi = ringNum * 2 * Math.PI / rings; - var sinPhi = Math.sin(phi); - var cosPhi = Math.cos(phi); + var sinPhi = semiMinorAxis * Math.sin(phi); + var cosPhi = semiMajorAxis * Math.cos(phi); var x = cosPhi * sinTheta; var y = cosTheta; @@ -66,10 +82,17 @@ SceneJS.Sphere.prototype._init = function(params) { } var indices = []; + + positions.push(0, 0, 0); + normals.push(1, 1, 1); + uv.push(1, 1); + var center = (ringLimit + 1) * (slices + 1); + for (var sliceNum = 0; sliceNum < slices; sliceNum++) { for (var ringNum = 0; ringNum < rings; ringNum++) { - var first = (sliceNum * (rings + 1)) + ringNum; - var second = first + rings + 1; + if (ringNum >= ringLimit) break; + var first = (sliceNum * (ringLimit + 1)) + ringNum; + var second = first + ringLimit + 1; indices.push(first); indices.push(second); indices.push(first + 1); @@ -78,6 +101,15 @@ SceneJS.Sphere.prototype._init = function(params) { indices.push(second + 1); indices.push(first + 1); } + if (rings >= ringLimit) { + // We aren't sweeping the whole way around so ... + // indices for a sphere with fours ring-segments when only two are drawn. + index = (ringLimit + 1) * sliceNum; + // 0,3,15 2,5,15 3,6,15 5,8,15 ... + indices.push(index, index + ringLimit + 1, center); + indices.push(index + ringLimit, index + ringLimit * 2 + 1, center); + } + } return { From 2bc19b4b5620c863a4ead05a8695fe5bc6ed06ab Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Sun, 6 Feb 2011 23:53:16 -0500 Subject: [PATCH 21/29] example: select which primitive-objects types to display --- resources/web/style.css | 13 +- src/examples/primitive-objects/index.html | 18 + .../primitive-objects/primitive-objects.js | 1050 +++++++++++++---- 3 files changed, 874 insertions(+), 207 deletions(-) diff --git a/resources/web/style.css b/resources/web/style.css index 4adbdd2b..b63ebd0e 100644 --- a/resources/web/style.css +++ b/resources/web/style.css @@ -200,9 +200,18 @@ h4 { #content ul.hlist li { line-height: 1.4em; color: #444444 !important; - margin-left: 5px; - display: inline; + margin: 0px 8px 5px 10px; + padding-bottom: 10px; + display: inline-block; list-style-type: none; + vertical-align: middle; +} + +#content fieldset { + overflow: auto; + text-align: left; + margin: 0 auto; + padding: 3px 10px 5px 10px; } #content p.intro { diff --git a/src/examples/primitive-objects/index.html b/src/examples/primitive-objects/index.html index 498a23ae..8d0c8b9b 100644 --- a/src/examples/primitive-objects/index.html +++ b/src/examples/primitive-objects/index.html @@ -26,6 +26,24 @@

SceneJS > Exampl
+
    +
  • +
    +
    + Look at + + + +
    +
    +
  • +
  • +
    + State + + +
    +
  • This example requires a browser that supports the HTML5 diff --git a/src/examples/primitive-objects/primitive-objects.js b/src/examples/primitive-objects/primitive-objects.js index cb1496d0..bb2dcd32 100644 --- a/src/examples/primitive-objects/primitive-objects.js +++ b/src/examples/primitive-objects/primitive-objects.js @@ -14,6 +14,7 @@ SceneJS.createNode({ loggingElementId: "theLoggingDiv", nodes: [ + { type: "lookAt", eye : { x: 0, y: 2, z: -22}, @@ -21,214 +22,758 @@ SceneJS.createNode({ up : { x: 0.0, y: 1.0, z: 0.0 }, nodes: [ - { - type: "camera", - optics: { - type: "perspective", - fovy : 25.0, - aspect : 1.47, - near : 0.10, - far : 300.0 - }, + { + type: "rotate", + id: "all-rotate", + angle: 0, + y: 1.0, + nodes: [ { - type: "light", - mode: "dir", - color: { r: 1.0, g: 1.0, b: 1.0 }, - diffuse: true, - specular: true, - dir: { x: 1.0, y: 1.0, z: -1.0 } - }, - { - type: "light", - mode: "dir", - color: {r: 1.0, g: 1.0, b: 1.0}, - diffuse: true, - specular: true, - dir: { x: 0.0, y: 1.0, z: -1.0 } - }, - { - type: "light", - mode: "dir", - color: {r: 1.0, g: 1.0, b: 1.0}, - diffuse: true, - specular: true, - dir: { x: -1.0, y: 0.0, z: -1.0 } - }, - - { - type: "translate", - x: -4.0, - y: 2.25, + type: "camera", + optics: { + type: "perspective", + fovy : 25.0, + aspect : 1.47, + near : 0.10, + far : 300.0 + }, + nodes: [ - { - type: "rotate", - id: "sphere-rotate", - angle: 0, - x: 0.2, - y: 1.0, - + type: "light", + id: "light1", + mode: "dir", + color: { r: 1.0, g: 1.0, b: 1.0 }, + diffuse: true, + specular: true, + dir: { x: 1.0, y: 1.0, z: 1.0 } + }, + { + type: "light", + id: "light1", + mode: "dir", + color: { r: 1.0, g: 1.0, b: 1.0 }, + diffuse: true, + specular: true, + dir: { x: -1.0, y: -1.0, z: -1.0 } + }, + { + type: "light", + id: "light2", + mode: "dir", + color: {r: 1.0, g: 1.0, b: 1.0}, + diffuse: true, + specular: true, + dir: { x: 0.0, y: 1.0, z: -1.0 } + }, + { + type: "light", + id: "light3", + mode: "dir", + color: {r: 1.0, g: 1.0, b: 1.0}, + diffuse: true, + specular: true, + dir: { x: -1.0, y: 0.0, z: -1.0 } + }, + + { + + type: "selector", + id: "filledObjectsSelector", + selection: [1], nodes: [ + + // Boxes { - type: "material", - baseColor: { r: 0.3, g: 0.3, b: 0.9 }, - specularColor: { r: 0.9, g: 0.9, b: 0.9 }, - specular: 0.9, - shine: 6.0, - - nodes: [ - { - type: "sphere", - slices: 6, - rings: 12 - } - ] - } - ] - } - ] - }, - - { - type: "translate", - x: 4.0, - y: 2.25, + type: "translate", + x: 0.0, + y: 0.5, + z: 4.0, - nodes: [ + nodes: [ - { - type: "rotate", - id: "disk-rotate", - angle: 0, - z: 0.2, - x: 1.0, + { + type: "rotate", + id: "box-rotate", + angle: 0, + x: 0.2, + y: 0.8, + z: 1.0, - nodes: [ + nodes: [ - { - type: "material", - baseColor: { r: 0.3, g: 0.9, b: 0.3 }, - specularColor: { r: 0.9, g: 0.9, b: 0.9 }, - specular: 0.9, - shine: 6.0, + { + type: "material", + baseColor: { r: 0.9, g: 0.3, b: 0.3 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 6.0, - nodes: [ - { - type: "disk", - radius: 1.0, - inner_radius: 0.5, - semiMajorAxis: 1.5, - rings: 12, + nodes: [ + { + type: "box" + } + ] + } + ] } ] - } - ] - } - ] - }, - - { - type: "translate", - x: 0.0, - y: 0.5, - - nodes: [ - - { - type: "rotate", - id: "box-rotate", - angle: 0, - x: 0.2, - z: 1.0, - - nodes: [ - + }, + + // spheres + { - type: "material", - baseColor: { r: 0.9, g: 0.3, b: 0.3 }, - specularColor: { r: 0.9, g: 0.9, b: 0.9 }, - specular: 0.9, - shine: 6.0, - + type: "node", + nodes: [ + { - type: "box" - } - ] - } - ] - } - ] - }, - + type: "translate", + x: -4.0, + y: 2.25, + z: 1.0, + nodes: [ - { - type: "renderer", - - wireframe: true, - lineWidth: 1, - - nodes: [ - - { - type: "scale", - x: 1.5, - y: 1.5, - z: 1.5, + { + type: "rotate", + id: "sphere1-rotate", + angle: 0, + x: 0.2, + y: 1.0, - nodes: [ + nodes: [ - { - type: "material", - baseColor: { r: 1.0, g: 1.0, b: 1.0 }, - specularColor: { r: 1.0, g: 1.0, b: 1.0 }, - specular: 0.9, - shine: 6.0, + { + type: "material", + baseColor: { r: 0.3, g: 0.3, b: 0.9 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 6.0, - nodes: [ + nodes: [ + { + type: "sphere", + id: "sphere1", + slices: 6, + rings: 12 + } + ] + } + ] + } + ] + }, { type: "translate", x: -3.0, - y: -0.5, + y: 1.25, + z: -3.0, + nodes: [ - + + { + type: "scale", + x: 1.2, + y: 1.2, + z: 1.2, + + nodes: [ + + { + type: "rotate", + id: "sphere2-rotate", + angle: 0, + x: 0.2, + y: 1.0, + + nodes: [ + + { + type: "material", + baseColor: { r: 0.9, g: 0.3, b: 0.6 }, + specularColor: { r: 0.9, g: 0.3, b: 0.6 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + { + type: "sphere", + id: "sphere2", + slices: 24, + rings: 16, + sweep: 0.5, + semiMajorAxis: 1.0 + } + ] + } + ] + } + ] + } + ] + }, + + { + type: "translate", + x: 2.5, + y: 1.0, + z: 2.0, + + nodes: [ + { - type: "sphere", - slices: 6, - rings: 12 + type: "scale", + x: 1.5, + y: 1.5, + z: 1.5, + + nodes: [ + + { + type: "rotate", + id: "sphere3-rotate", + angle: 90, + x: 0.2, + z: 1.0, + + nodes: [ + + { + type: "material", + baseColor: { r: 0.2, g: 0.8, b: 0.6 }, + specularColor: { r: 0.9, g: 0.3, b: 0.6 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + { + type: "sphere", + id: "sphere3", + slices: 24, + rings: 24, + sweep: 0.25, + semiMajorAxis: 1.6 + } + ] + } + ] + } + ] } ] }, + + { + type: "translate", + x: 1.5, + y: 0.5, + z: -2.0, + + nodes: [ + + { + type: "scale", + x: 1.5, + y: 1.5, + z: 1.5, + + nodes: [ + + { + type: "rotate", + id: "sphere4-rotate", + angle: 90, + x: 0.2, + z: 1.0, + + nodes: [ + + { + type: "material", + baseColor: { r: 0.8, g: 0.7, b: 0.4 }, + specularColor: { r: 0.9, g: 0.3, b: 0.6 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + { + type: "sphere", + id: "sphere4", + slices: 24, + rings: 4, + sweep: 1.0, + semiMajorAxis: 1.0 + } + ] + } + ] + } + ] + } + ] + } + ] + }, + // Disks + + { + type: "node", + + nodes: [ + { type: "translate", - x: 3.25, - y: -0.5, + x: -3.5, + y: 1.75, + z: -0.5, + nodes: [ { - type: "disk", - radius: 1.0, - inner_radius: 0.5, - semiMajorAxis: 1.5, - rings: 12, + type: "scale", + x: 0.3, + y: 0.3, + z: 0.3, + + nodes: [ + + { + type: "rotate", + id: "disk1-rotate", + angle: 60, + z: 0.4, + x: 1.0, + + nodes: [ + + { + type: "material", + baseColor: { r: 0.8, g: 0.5, b: 0.2 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + + { + type: "disk", + id: "disk1", + radius: 5, + height: 2, + rings: 24, + }, + + ] + } + ] + } + ] } ] }, - + { type: "translate", - x: 0, - y: -2.0, + x: 4.0, + y: 1.5, + + nodes: [ + + { + type: "scale", + x: 0.3, + y: 0.3, + z: 0.3, + + nodes: [ + + { + type: "rotate", + id: "disk2-rotate", + angle: 0, + z: 0.2, + x: 1.0, + + nodes: [ + + { + type: "material", + baseColor: { r: 0.3, g: 0.9, b: 0.3 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + + { + type: "disk", + id: "disk2", + radius: 6, // Optional radius (1 is default) + innerRadius: 4, // Optional innerRadius results in ring (default is 0) + semiMajorAxis: 1.5, // Optional semiMajorAxis results in ellipse (default of 1 creates circle) + height: 2, // Optional height (1 is default) + rings: 48, // Optional number of longitudinal rings (30 is default) + sweep: 0.75, // Optional rotational extrusion (1 is default) + }, + + ] + } + ] + } + ] + } + ] + }, + + { + type: "translate", + x: -0.5, + y: 1.0, + z: -5, nodes: [ { - type: "box" + type: "scale", + x: 0.3, + y: 0.3, + z: 0.3, + + nodes: [ + + { + type: "rotate", + id: "disk-triangle-rotate", + angle: 60, + z: 0.4, + x: 1.0, + + nodes: [ + + { + type: "material", + baseColor: { r: 0.9, g: 0.2, b: 0.1 }, + specularColor: { r: 0.9, g: 0.9, b: 0.9 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + + { + type: "disk", + id: "disk-triangle", + radius: 5, // Optional radius (1 is default) + innerRadius: 4, // Optional innerRadius results in ring (default is 0) + semiMajorAxis: 1.0, // Optional semiMajorAxis results in ellipse (default of 1 creates circle) + height: 2, // Optional height (1 is default) + rings: 3, // Optional number of longitudinal rings (30 is default) + sweep: 1.0, // Optional rotational extrusion (1 is default) + } + ] + } + ] + } + ] + } + ] + } + ] + }, + ] + }, + + { + type: "renderer", + + wireframe: true, + lineWidth: 1, + + nodes: [ + + { + type: "scale", + x: 1.2, + y: 1.2, + z: 1.2, + + nodes: [ + + { + type: "material", + baseColor: { r: 1.0, g: 1.0, b: 1.0 }, + specularColor: { r: 1.0, g: 1.0, b: 1.0 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + + { + + type: "selector", + id: "wireframeObjectsSelector", + selection: [1], + + nodes: [ + + // Boxes + + { + type: "translate", + x: 0, + y: -2.5, + z: 4.0, + nodes: [ + + { + type: "rotate", + id: "wireframe-box-rotate", + angle: -45, + x: 1.0, + y: 1.0, + z: 1.0, + nodes: [ + + { + type: "box" + } + ] + } + ] + }, + + // Spheres + + { + type: "node", + + nodes: [ + + { + type: "translate", + x: -3.5, + y: -0.5, + z: 1.0, + + nodes: [ + + { + type: "rotate", + id: "wireframe-sphere1-rotate", + angle: 0, + x: 0.2, + z: 1.0, + + nodes: [ + + { + type: "instance", + target: "sphere1", + } + ] + } + ] + }, + + { + type: "translate", + x: -2.5, + y: -1.5, + z: -2.5, + + nodes: [ + + { + type: "rotate", + id: "wireframe-sphere2-rotate", + angle: 0, + x: 0.2, + z: 1.0, + + nodes: [ + + { + type: "instance", + target: "sphere2" + } + ] + } + ] + }, + + { + type: "translate", + x: 2.5, + y: -0.75, + z: 2.5, + + nodes: [ + + { + type: "rotate", + id: "wireframe-sphere3-rotate", + angle: 0, + x: 0.2, + z: 1.0, + + nodes: [ + + { + type: "instance", + target: "sphere3" + } + ] + } + ] + }, + + { + type: "translate", + x: 1.25, + y: -2.0, + z: -3.0, + + nodes: [ + + { + type: "rotate", + id: "wireframe-sphere4-rotate", + angle: 0, + x: 0.2, + z: 1.0, + + nodes: [ + + { + type: "instance", + target: "sphere4" + } + ] + } + ] + } + ] + }, + + // Disks + + { + type: "node", + + nodes: [ + { + type: "translate", + x: -3.75, + y: -1.0, + z: -0.75, + + nodes: [ + + { + type: "rotate", + id: "wireframe-disk1-rotate", + angle: -45, + x: 1.0, + y: 1.0, + z: 1.0, + nodes: [ + + { + type: "scale", + x: 0.2, + y: 0.2, + z: 0.2, + + nodes: [ + + { + type: "instance", + target: "disk1" + } + ] + } + ] + } + ] + }, + + { + type: "translate", + x: 3.25, + y: -1.75, + + nodes: [ + + { + type: "scale", + x: 0.3, + y: 0.3, + z: 0.3, + + nodes: [ + + { + type: "rotate", + id: "wireframe-disk2-rotate", + angle: 60, + z: 0.4, + x: 1.0, + + nodes: [ + + { + type: "instance", + target: "disk2" + } + ] + } + ] + } + ] + }, + + { + type: "translate", + x: -0.75, + y: -1.5, + z: -4.5, + + nodes: [ + + { + type: "scale", + x: 0.3, + y: 0.3, + z: 0.3, + + nodes: [ + + { + type: "rotate", + id: "wireframe-disk-triangle-rotate", + angle: 60, + z: 0.4, + x: 1.0, + + nodes: [ + + { + type: "instance", + target: "disk-triangle" + } + ] + } + ] + } + ] + } + ] + } + ] } ] } @@ -238,42 +783,6 @@ SceneJS.createNode({ } ] } - - // - // { - // type: "translate", - // x: 2.5, - // y: 1.5, - // z: 1, - // - // nodes: [ - // - // { - // type: "material", - // baseColor: { r: 0.3, g: 0.9, b: 0.3 }, - // specularColor: { r: 0.2, g: 0.4, b: 0.3 }, - // specular: 0.9, - // shine: 6.0, - // - // nodes: [ - // - // { - // type: "rotate", - // angle: 30.0, - // x : 1.0, - // y : 1.5, - // - // nodes: [ - // - // { - // type: "disk" - // } - // ] - // } - // ] - // } - // ] - // } ] } ] @@ -283,15 +792,146 @@ SceneJS.createNode({ SceneJS.withNode("theScene").render(); -var disk_rotate = SceneJS.withNode("disk-rotate") -var sphere_rotate = SceneJS.withNode("sphere-rotate") -var box_rotate = SceneJS.withNode("box-rotate") +var rotation = document.getElementById("rotation"); + +// Specular light + +var specular_light = document.getElementById("specular-light"); +var light1 = SceneJS.withNode("light1"); +var light2 = SceneJS.withNode("light2"); +var light3 = SceneJS.withNode("light3"); + +function specularLightChange() { + if (specular_light.checked) { + light1.set({ specular: true }); + light2.set({ specular: true }); + light3.set({ specular: true }); + } else { + light1.set({ specular: false }); + light2.set({ specular: false }); + light3.set({ specular: false }); + } +} + +specular_light.onchange = specularLightChange; +specular_light.onchange(); + +var filled_objects_selector = SceneJS.withNode("filledObjectsSelector"); +var wireframe_objects_selector = SceneJS.withNode("wireframeObjectsSelector"); + + +var choose_object_type = document.getElementById("choose-object-type"); +var object_type_selection; + +for(var i = 0; i < choose_object_type.elements.length; i++) + if (choose_object_type.elements[i].checked) object_type_selection = choose_object_type.elements[i].value; + +function chooseObjectType() { + for(var i = 0; i < this.elements.length; i++) + if (this.elements[i].checked) object_type_selection = this.elements[i].value; + switch(object_type_selection) { + case "boxes": + filled_objects_selector.set("selection", [0]); + wireframe_objects_selector.set("selection", [0]); + break; + case 'spheres': + filled_objects_selector.set("selection", [1]); + wireframe_objects_selector.set("selection", [1]); + break; + case "disks": + filled_objects_selector.set("selection", [2]); + wireframe_objects_selector.set("selection", [2]); + break; + } +} + +choose_object_type.onchange = chooseObjectType; +choose_object_type.onchange(); + +var all_rotate = SceneJS.withNode("all-rotate"); + +var disk1_rotate = SceneJS.withNode("disk1-rotate"); +var disk2_rotate = SceneJS.withNode("disk2-rotate"); +var disk_triangle_rotate = SceneJS.withNode("disk-triangle-rotate"); +var wireframe_disk1_rotate = SceneJS.withNode("wireframe-disk1-rotate"); +var wireframe_disk2_rotate = SceneJS.withNode("wireframe-disk2-rotate"); +var wireframe_disk_triangle_rotate = SceneJS.withNode("wireframe-disk-triangle-rotate"); + +var sphere1_rotate = SceneJS.withNode("sphere1-rotate"); +var sphere2_rotate = SceneJS.withNode("sphere2-rotate"); +var sphere3_rotate = SceneJS.withNode("sphere3-rotate"); +var sphere4_rotate = SceneJS.withNode("sphere4-rotate"); +var wireframe_sphere1_rotate = SceneJS.withNode("wireframe-sphere1-rotate"); +var wireframe_sphere2_rotate = SceneJS.withNode("wireframe-sphere2-rotate"); +var wireframe_sphere3_rotate = SceneJS.withNode("wireframe-sphere3-rotate"); +var wireframe_sphere4_rotate = SceneJS.withNode("wireframe-sphere4-rotate"); + +var box_rotate = SceneJS.withNode("box-rotate"); +var wireframe_box_rotate = SceneJS.withNode("wireframe-box-rotate"); + +var yaw = all_rotate.get("angle"); + +var lastX; +var lastY; +var dragging = false; + +var canvas = document.getElementById("theCanvas"); + +function mouseDown(event) { + lastX = event.clientX; + lastY = event.clientY; + dragging = true; +} + +function mouseUp() { + dragging = false; +} + +/* On a mouse drag, we'll re-render the scene, passing in + * incremented angles in each time. + */ +function mouseMove(event) { + if (dragging) { + yaw += (event.clientX - lastX) * -0.5; + + all_rotate.set("angle", yaw); + // SceneJS.withNode("theScene").render(); + + lastX = event.clientX; + lastY = event.clientY; + } +} + +canvas.addEventListener('mousedown', mouseDown, true); +canvas.addEventListener('mousemove', mouseMove, true); +canvas.addEventListener('mouseup', mouseUp, true); window.render = function() { - var angle = disk_rotate.get("angle") + 0.3; - disk_rotate.set("angle", angle); - sphere_rotate.set("angle", angle); - box_rotate.set("angle", angle); + if (rotation.checked) { + var angle = disk1_rotate.get("angle") + 0.3; + disk1_rotate.set("angle", angle); + disk2_rotate.set("angle", angle); + disk_triangle_rotate.set("angle", angle); + wireframe_disk1_rotate.set("angle", angle); + wireframe_disk2_rotate.set("angle", angle); + wireframe_disk_triangle_rotate.set("angle", angle); + + sphere1_rotate.set("angle", angle); + sphere2_rotate.set("angle", angle); + sphere3_rotate.set("angle", angle); + sphere4_rotate.set("angle", angle); + wireframe_sphere1_rotate.set("angle", angle); + wireframe_sphere2_rotate.set("angle", angle); + wireframe_sphere3_rotate.set("angle", angle); + wireframe_sphere4_rotate.set("angle", angle); + + box_rotate.set("angle", angle); + wireframe_box_rotate.set("angle", angle); + + yaw = all_rotate.get("angle"); + yaw += + 0.1; + all_rotate.set("angle", yaw); + } SceneJS.withNode("theScene").render(); }; From 424db5b744f56865b11e151950662e62a28fa3fa Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Mon, 7 Feb 2011 00:37:09 -0500 Subject: [PATCH 22/29] bug fix: SceneJS.sphere does NOT use innerRadius! at least not yet ... --- src/scenejs/geometry/objects/sphere.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scenejs/geometry/objects/sphere.js b/src/scenejs/geometry/objects/sphere.js index 9ba3e446..f7956f2e 100644 --- a/src/scenejs/geometry/objects/sphere.js +++ b/src/scenejs/geometry/objects/sphere.js @@ -45,7 +45,7 @@ SceneJS.Sphere.prototype._init = function(params) { /* Resource ID ensures that we reuse any sphere that has already been created with * these parameters instead of wasting memory */ - this._resource = "sphere_" + radius + "_" + rings + "_" + slices + "_" + innerRadius + "_" + semiMajorAxis + "_" + sweep; + this._resource = "sphere_" + radius + "_" + rings + "_" + slices + "_" + semiMajorAxis + "_" + sweep; /* Callback that does the creation in case we can't find matching sphere to reuse */ From 725feca1d0154a5b965007e69b797bdfd500c7c0 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Wed, 9 Feb 2011 11:10:30 -0500 Subject: [PATCH 23/29] optional sliceDepth attribute for SceneJS.sphere Sets depth percentage of slices to generate from top to bottom (1 is default). Example: { type: "sphere", slices: 48, rings: 48, radius: 4, sliceDepth: 0.25, } --- src/scenejs/geometry/objects/sphere.js | 65 +++++++++++++++++++------- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/src/scenejs/geometry/objects/sphere.js b/src/scenejs/geometry/objects/sphere.js index f7956f2e..4eaafaaa 100644 --- a/src/scenejs/geometry/objects/sphere.js +++ b/src/scenejs/geometry/objects/sphere.js @@ -9,6 +9,8 @@ * rings: 30, // Optional number of latitudinal slices (30 is default) * semiMajorAxis: 1.5, // Optional semiMajorAxis results in elliptical sphere (default of 1 creates sphere) * sweep: 0.75, // Optional rotational extrusion (1 is default) + * sliceDepth: 0.25, // Optional depth of slices to generate from top to bottom (1 is default) + (1 is default) * }) *

* @extends SceneJS.Geometry @@ -19,7 +21,8 @@ * @param {float} [cfg.slices=30] Number of longitudinal slices * @param {float} [cfg.rings=30] Number of longitudinal slices * @param {float} [cfg.semiMajorAxis=1.0] values other than one generate an elliptical sphere - * @param {float} [cfg.sweep=1] rotational extrusion default is 1 + * @param {float} [cfg.sweep=1] rotational extrusion, default is 1 + * @param {float} [cfg.sliceDepth=1] depth of slices to generate, default is 1 * @param {function(SceneJS.Data):Object} [fn] Dynamic configuration function * @param {...SceneJS.Node} [childNodes] Child nodes */ @@ -29,7 +32,7 @@ SceneJS.Sphere = SceneJS.createNodeType("sphere", "geometry"); SceneJS.Sphere.prototype._init = function(params) { var slices = params.slices || 30; var rings = params.rings || 30; - var radius = params.radius || 1; + var radius = params.radius || 1; var semiMajorAxis = params.semiMajorAxis || 1; var semiMinorAxis = 1 / semiMajorAxis; @@ -38,14 +41,19 @@ SceneJS.Sphere.prototype._init = function(params) { if (sweep > 1) { sweep = 1 } - + + var sliceDepth = params.sliceDepth || 1; + if (sliceDepth > 1) { + sliceDepth = 1 + } + var ringLimit = rings * sweep; - + var sliceLimit = slices * sliceDepth; /* Resource ID ensures that we reuse any sphere that has already been created with * these parameters instead of wasting memory */ - this._resource = "sphere_" + radius + "_" + rings + "_" + slices + "_" + semiMajorAxis + "_" + sweep; + this._resource = "sphere_" + radius + "_" + rings + "_" + slices + "_" + semiMajorAxis + "_" + sweep + "_" + sliceDepth; /* Callback that does the creation in case we can't find matching sphere to reuse */ @@ -53,12 +61,15 @@ SceneJS.Sphere.prototype._init = function(params) { var positions = []; var normals = []; var uv = []; - for (var sliceNum = 0; sliceNum <= slices; sliceNum++) { + var ringNum, sliceNum, index; + + for (sliceNum = 0; sliceNum <= slices; sliceNum++) { + if (sliceNum > sliceLimit) break; var theta = sliceNum * Math.PI / slices; var sinTheta = Math.sin(theta); var cosTheta = Math.cos(theta); - for (var ringNum = 0; ringNum <= rings; ringNum++) { + for (ringNum = 0; ringNum <= rings; ringNum++) { if (ringNum > ringLimit) break; var phi = ringNum * 2 * Math.PI / rings; var sinPhi = semiMinorAxis * Math.sin(phi); @@ -81,15 +92,27 @@ SceneJS.Sphere.prototype._init = function(params) { } } - var indices = []; + // create a center point which is only used when sweep or sliceDepth are less than one + if (sliceDepth < 1) { + var yPos = Math.cos((sliceNum - 1) * Math.PI / slices) * radius; + positions.push(0, yPos, 0); + normals.push(1, 1, 1); + uv.push(1, 1); + } else { + positions.push(0, 0, 0); + normals.push(1, 1, 1); + uv.push(1, 1); + } + + // index of the center position point in the positions array + // var centerIndex = (ringLimit + 1) * (sliceLimit); + var centerIndex = positions.length / 3 - 1; - positions.push(0, 0, 0); - normals.push(1, 1, 1); - uv.push(1, 1); - var center = (ringLimit + 1) * (slices + 1); + var indices = []; - for (var sliceNum = 0; sliceNum < slices; sliceNum++) { - for (var ringNum = 0; ringNum < rings; ringNum++) { + for (sliceNum = 0; sliceNum < slices; sliceNum++) { + if (sliceNum >= sliceLimit) break; + for (ringNum = 0; ringNum < rings; ringNum++) { if (ringNum >= ringLimit) break; var first = (sliceNum * (ringLimit + 1)) + ringNum; var second = first + ringLimit + 1; @@ -106,12 +129,20 @@ SceneJS.Sphere.prototype._init = function(params) { // indices for a sphere with fours ring-segments when only two are drawn. index = (ringLimit + 1) * sliceNum; // 0,3,15 2,5,15 3,6,15 5,8,15 ... - indices.push(index, index + ringLimit + 1, center); - indices.push(index + ringLimit, index + ringLimit * 2 + 1, center); + indices.push(index, index + ringLimit + 1, centerIndex); + indices.push(index + ringLimit, index + ringLimit * 2 + 1, centerIndex); } - } + if (slices > sliceLimit) { + // We aren't sweeping from the top all the way to the bottom so ... + for (ringNum = 1; ringNum <= ringLimit; ringNum++) { + index = sliceNum * ringLimit + ringNum; + indices.push(index, index + 1, centerIndex); + } + indices.push(index + 1, sliceNum * ringLimit + 1, centerIndex); + } + return { primitive : "triangles", positions : positions, From cf00194a330a87357f5a0619462601960c9460f4 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Wed, 9 Feb 2011 11:11:20 -0500 Subject: [PATCH 24/29] add sphere w/sliceDepth to primitive-objects example --- src/examples/primitive-objects/index.html | 4 +- .../primitive-objects/primitive-objects.js | 115 +++++++++++++++++- 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/src/examples/primitive-objects/index.html b/src/examples/primitive-objects/index.html index 8d0c8b9b..1075366c 100644 --- a/src/examples/primitive-objects/index.html +++ b/src/examples/primitive-objects/index.html @@ -32,8 +32,8 @@

SceneJS > Exampl
Look at - - + +
diff --git a/src/examples/primitive-objects/primitive-objects.js b/src/examples/primitive-objects/primitive-objects.js index bb2dcd32..a878788c 100644 --- a/src/examples/primitive-objects/primitive-objects.js +++ b/src/examples/primitive-objects/primitive-objects.js @@ -219,9 +219,9 @@ SceneJS.createNode({ { type: "translate", - x: 2.5, + x: 3.0, y: 1.0, - z: 2.0, + z: 1.5, nodes: [ @@ -315,6 +315,66 @@ SceneJS.createNode({ ] } ] + }, + + { + type: "translate", + x: -0.5, + y: -3.0, + z: 4.0, + + nodes: [ + + { + type: "scale", + x: 1.0, + y: 1.0, + z: 1.0, + + nodes: [ + + { + type: "rotate", + angle: -20, + x: 1.0, + + nodes: [ + + { + type: "rotate", + id: "sphere5-rotate", + angle: 10, + y: 1.0, + + nodes: [ + + { + type: "material", + baseColor: { r: 0.8, g: 0.3, b: 0.1 }, + specularColor: { r: 0.9, g: 0.3, b: 0.6 }, + specular: 0.9, + shine: 6.0, + + nodes: [ + { + type: "sphere", + id: "sphere5", + slices: 48, + rings: 48, + radius: 4, + sweep: 0.5, + sliceDepth: 0.25, + semiMajorAxis: 1.5 + } + ] + } + ] + } + ] + } + ] + } + ] } ] }, @@ -607,9 +667,14 @@ SceneJS.createNode({ { type: "translate", - x: 2.5, - y: -0.75, - z: 2.5, + + x: 3.0, + y: 1.0, + z: 1.5, + + x: 3.25, + y: -2.0, + z: 2.0, nodes: [ @@ -655,6 +720,42 @@ SceneJS.createNode({ ] } ] + }, + + { + type: "translate", + + x: -0.5, + y: -4.0, + z: 5.0, + + nodes: [ + + { + type: "scale", + x: 0.75, + y: 0.75, + z: 0.75, + + nodes: [ + + { + type: "rotate", + id: "wireframe-sphere5-rotate", + angle: -10, + y: 1.0, + + nodes: [ + + { + type: "instance", + target: "sphere5" + } + ] + } + ] + } + ] } ] }, @@ -861,10 +962,12 @@ var sphere1_rotate = SceneJS.withNode("sphere1-rotate"); var sphere2_rotate = SceneJS.withNode("sphere2-rotate"); var sphere3_rotate = SceneJS.withNode("sphere3-rotate"); var sphere4_rotate = SceneJS.withNode("sphere4-rotate"); +var sphere5_rotate = SceneJS.withNode("sphere5-rotate"); var wireframe_sphere1_rotate = SceneJS.withNode("wireframe-sphere1-rotate"); var wireframe_sphere2_rotate = SceneJS.withNode("wireframe-sphere2-rotate"); var wireframe_sphere3_rotate = SceneJS.withNode("wireframe-sphere3-rotate"); var wireframe_sphere4_rotate = SceneJS.withNode("wireframe-sphere4-rotate"); +var wireframe_sphere5_rotate = SceneJS.withNode("wireframe-sphere5-rotate"); var box_rotate = SceneJS.withNode("box-rotate"); var wireframe_box_rotate = SceneJS.withNode("wireframe-box-rotate"); @@ -920,10 +1023,12 @@ window.render = function() { sphere2_rotate.set("angle", angle); sphere3_rotate.set("angle", angle); sphere4_rotate.set("angle", angle); + sphere5_rotate.set("angle", angle); wireframe_sphere1_rotate.set("angle", angle); wireframe_sphere2_rotate.set("angle", angle); wireframe_sphere3_rotate.set("angle", angle); wireframe_sphere4_rotate.set("angle", angle); + wireframe_sphere5_rotate.set("angle", angle); box_rotate.set("angle", angle); wireframe_box_rotate.set("angle", angle); From ea2d3a3eda7537b61af0ef69b3725604c7362723 Mon Sep 17 00:00:00 2001 From: Stephen Bannasch Date: Wed, 9 Feb 2011 11:30:42 -0500 Subject: [PATCH 25/29] simplify the sphere sliceDepth example Rendering a sphere with sliceDepth works with the sweep and semiMajorAxis attributes but the example is more pleasing without combining them. This version also matches the Sphere wiki page example: http://scenejs.wikispaces.com/sphere --- src/examples/primitive-objects/primitive-objects.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/examples/primitive-objects/primitive-objects.js b/src/examples/primitive-objects/primitive-objects.js index a878788c..1d7b1a4a 100644 --- a/src/examples/primitive-objects/primitive-objects.js +++ b/src/examples/primitive-objects/primitive-objects.js @@ -362,9 +362,9 @@ SceneJS.createNode({ slices: 48, rings: 48, radius: 4, - sweep: 0.5, + sweep: 1.0, sliceDepth: 0.25, - semiMajorAxis: 1.5 + semiMajorAxis: 1.0 } ] } From 23bf13f1812b50962f6ebc212d576274576da7a1 Mon Sep 17 00:00:00 2001 From: Terrance Mok Date: Thu, 17 Feb 2011 15:31:51 -0700 Subject: [PATCH 26/29] Set oldState and newState properly when state-changed is fired. --- src/scenejs/boundary/boundingBox.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scenejs/boundary/boundingBox.js b/src/scenejs/boundary/boundingBox.js index 5696132e..e2544fa1 100644 --- a/src/scenejs/boundary/boundingBox.js +++ b/src/scenejs/boundary/boundingBox.js @@ -142,10 +142,11 @@ SceneJS.BoundingBox.STATE_INTERSECTING_FRUSTUM = "visible"; // @private SceneJS.BoundingBox.prototype._changeState = function(newState, params) { + var oldState = this._state; this._state = newState; if (this._listeners["state-changed"]) { params = params || {}; - params.oldState = this._state; + params.oldState = oldState; params.newState = newState; this._fireEvent("state-changed", params); } From 1d476ca70e2c1c1c5f41439373d3f7d74029075b Mon Sep 17 00:00:00 2001 From: Lindsay Kay Date: Sun, 20 Feb 2011 12:35:33 +0100 Subject: [PATCH 27/29] Fix - SceneJS.withNode incorrectly threw "param null or undefined" when attribute was 0 --- src/scenejs/core/withNode.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/scenejs/core/withNode.js b/src/scenejs/core/withNode.js index 4eb586e2..aeab2af2 100644 --- a/src/scenejs/core/withNode.js +++ b/src/scenejs/core/withNode.js @@ -174,7 +174,7 @@ SceneJS._WithNode.prototype.numInstances = function() { /** Sets an attribute of the selected node */ SceneJS._WithNode.prototype.set = function(attr, value) { - if (!attr) { + if (attr == null || attr == undefined) { throw "set param 'attr' null or undefined"; } if (typeof attr == "string") { @@ -188,7 +188,7 @@ SceneJS._WithNode.prototype.set = function(attr, value) { /** Adds an attribute to the selected node */ SceneJS._WithNode.prototype.add = function(attr, value) { - if (!attr) { + if (attr == null || attr == undefined) { throw "add param 'attr' null or undefined"; } if (typeof attr == "string") { @@ -202,7 +202,7 @@ SceneJS._WithNode.prototype.add = function(attr, value) { /** Increments an attribute to the selected node */ SceneJS._WithNode.prototype.inc = function(attr, value) { - if (!attr) { + if (attr == null || attr == undefined) { throw "inc param 'attr' null or undefined"; } if (typeof attr == "string") { @@ -216,7 +216,7 @@ SceneJS._WithNode.prototype.inc = function(attr, value) { /** Inserts an attribute or child node into the selected node */ SceneJS._WithNode.prototype.insert = function(attr, value) { - if (!attr) { + if (attr == null || attr == undefined) { throw "insert param 'attr' null or undefined"; } if (typeof attr == "string") { @@ -230,7 +230,7 @@ SceneJS._WithNode.prototype.insert = function(attr, value) { /** Removes an attribute from the selected node */ SceneJS._WithNode.prototype.remove = function(attr, value) { - if (!attr) { + if (attr == null || attr == undefined) { throw "remove param 'attr' null or undefined"; } if (typeof attr == "string") { @@ -244,7 +244,7 @@ SceneJS._WithNode.prototype.remove = function(attr, value) { /** Returns the value of an attribute of the selected node */ SceneJS._WithNode.prototype.get = function(attr) { - if (!attr) { + if (attr == null || attr == undefined) { return this._targetNode.getJSON(); } var funcName = "get" + attr.substr(0, 1).toUpperCase() + attr.substr(1); From 4e77b072efc592f4bb518a78792b16d4d518131e Mon Sep 17 00:00:00 2001 From: Lindsay Kay Date: Sun, 20 Feb 2011 12:49:58 +0100 Subject: [PATCH 28/29] Undo fix - SceneJS.withNode does correctly throw "param null or undefined" when attribute is null --- src/scenejs/core/withNode.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/scenejs/core/withNode.js b/src/scenejs/core/withNode.js index aeab2af2..4eb586e2 100644 --- a/src/scenejs/core/withNode.js +++ b/src/scenejs/core/withNode.js @@ -174,7 +174,7 @@ SceneJS._WithNode.prototype.numInstances = function() { /** Sets an attribute of the selected node */ SceneJS._WithNode.prototype.set = function(attr, value) { - if (attr == null || attr == undefined) { + if (!attr) { throw "set param 'attr' null or undefined"; } if (typeof attr == "string") { @@ -188,7 +188,7 @@ SceneJS._WithNode.prototype.set = function(attr, value) { /** Adds an attribute to the selected node */ SceneJS._WithNode.prototype.add = function(attr, value) { - if (attr == null || attr == undefined) { + if (!attr) { throw "add param 'attr' null or undefined"; } if (typeof attr == "string") { @@ -202,7 +202,7 @@ SceneJS._WithNode.prototype.add = function(attr, value) { /** Increments an attribute to the selected node */ SceneJS._WithNode.prototype.inc = function(attr, value) { - if (attr == null || attr == undefined) { + if (!attr) { throw "inc param 'attr' null or undefined"; } if (typeof attr == "string") { @@ -216,7 +216,7 @@ SceneJS._WithNode.prototype.inc = function(attr, value) { /** Inserts an attribute or child node into the selected node */ SceneJS._WithNode.prototype.insert = function(attr, value) { - if (attr == null || attr == undefined) { + if (!attr) { throw "insert param 'attr' null or undefined"; } if (typeof attr == "string") { @@ -230,7 +230,7 @@ SceneJS._WithNode.prototype.insert = function(attr, value) { /** Removes an attribute from the selected node */ SceneJS._WithNode.prototype.remove = function(attr, value) { - if (attr == null || attr == undefined) { + if (!attr) { throw "remove param 'attr' null or undefined"; } if (typeof attr == "string") { @@ -244,7 +244,7 @@ SceneJS._WithNode.prototype.remove = function(attr, value) { /** Returns the value of an attribute of the selected node */ SceneJS._WithNode.prototype.get = function(attr) { - if (attr == null || attr == undefined) { + if (!attr) { return this._targetNode.getJSON(); } var funcName = "get" + attr.substr(0, 1).toUpperCase() + attr.substr(1); From bc8c36b4ed2f119cafc28c87f9fdfbd9b3c3342f Mon Sep 17 00:00:00 2001 From: xeolabs Date: Wed, 3 Jun 2015 10:05:39 +0200 Subject: [PATCH 29/29] Merge remote-tracking branch 'origin/master' into shader-optimizations Conflicts: .gitignore README.markdown build.xml resources/web/style.css src/scenejs/boundary/boundingBox.js src/scenejs/geometry/objects/sphere.js src/scenejs/interpolation/interpolator.js src/scenejs/scene/scene.js src/scenejs/scene/sceneModule.js --- examples/features.json | 8 + examples/index.html | 2 +- examples/physics_balls.html | 399 +++++++++++++++++------------------- index.html | 2 +- package.json | 18 +- 5 files changed, 212 insertions(+), 217 deletions(-) diff --git a/examples/features.json b/examples/features.json index 2c5f2435..85ef90ab 100644 --- a/examples/features.json +++ b/examples/features.json @@ -195,6 +195,14 @@ "page": "optimization_uintIndex" } ] + }, + { + "nodes": [ + { + "title": "Super sample anti-aliasing", + "page": "canvas_SSAA" + } + ] } ] }, diff --git a/examples/index.html b/examples/index.html index fbb94f13..26f6b6eb 100644 --- a/examples/index.html +++ b/examples/index.html @@ -2,7 +2,7 @@ - SceneJS v4.0 - Examples + SceneJS v4.2.0 - Examples diff --git a/examples/physics_balls.html b/examples/physics_balls.html index 5b67953e..3e065b03 100644 --- a/examples/physics_balls.html +++ b/examples/physics_balls.html @@ -26,219 +26,206 @@
physics system in its own web worker
- learn more in
this tutorial + learn more in this tutorial diff --git a/index.html b/index.html index d4938d7e..2b2191bd 100644 --- a/index.html +++ b/index.html @@ -181,7 +181,7 @@
-

Features in V4.1.0

+

Features in V4.2.0

diff --git a/package.json b/package.json index 97edd207..c626bc86 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "scenejs", "title": "SceneJS", - "version": "4.1.0", + "version": "4.2.0", "description": "A WebGL-based 3D scene graph from xeoLabs", "homepage": "http://scenejs.org/", "author": { @@ -17,15 +17,15 @@ "grunt-contrib-yuidoc": "~0.7.0" }, "devDependencies": { - "grunt": "~0.4.5", - "grunt-contrib-concat": "~0.5.1", - "grunt-contrib-uglify": "~0.8.0", - "grunt-contrib-yuidoc": "~0.7.0", - "grunt-contrib-jshint": "~0.11.1", - "grunt-contrib-clean": "~0.6.0", - "grunt-contrib-copy": "~0.8.0", + "grunt": "^0.4.5", + "grunt-contrib-clean": "^0.6.0", + "grunt-contrib-concat": "^0.5.1", + "grunt-contrib-copy": "^0.8.0", "grunt-contrib-jasmine": "~0.8.2", - "grunt-contrib-qunit": "~0.5.2" + "grunt-contrib-jshint": "~0.11.1", + "grunt-contrib-qunit": "~0.5.2", + "grunt-contrib-uglify": "^0.9.1", + "grunt-contrib-yuidoc": "~0.7.0" }, "engines": { "node": ">=0.10.17",