Skip to content

Commit

Permalink
Merge pull request xeolabs#322 from NVIDIA/refactor-geometry-3
Browse files Browse the repository at this point in the history
Refactor geometry chunks so that vertex arrays are set in a single type of chunk
  • Loading branch information
xeolabs committed Jun 30, 2014
2 parents 7fcec6a + 963d61d commit 6d1b4ec
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 297 deletions.
3 changes: 1 addition & 2 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@
"src/core/display/chunks/listenersChunk.js",
"src/core/display/chunks/lookAtChunk.js",
"src/core/display/chunks/materialChunk.js",
"src/core/display/chunks/morphGeometryChunk.js",
"src/core/display/chunks/nameChunk.js",
"src/core/display/chunks/programChunk.js",
"src/core/display/chunks/rendererChunk.js",
Expand Down Expand Up @@ -318,4 +317,4 @@
});
});

})();
})();
4 changes: 3 additions & 1 deletion src/core/display/chunks/chunk.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ var SceneJS_Chunk = function() {};
* @param {String} id Chunk ID
* @param {SceneJS_Program} program Program to render the chunk
* @param {SceneJS_Core} core The state core rendered by this chunk
* @param {SceneJS_Core} core2 Another state core rendered by this chunk, only used for geometry
*/
SceneJS_Chunk.prototype.init = function(id, program, core) {
SceneJS_Chunk.prototype.init = function(id, program, core, core2) {

this.id = id;
this.program = program;
this.core = core;
this.core2 = core2;

if (this.build) {
this.build();
Expand Down
7 changes: 4 additions & 3 deletions src/core/display/chunks/chunkFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ SceneJS_ChunkFactory.createChunkType = function(params) {
/**
*
*/
SceneJS_ChunkFactory.prototype.getChunk = function(chunkId, type, program, core) {
SceneJS_ChunkFactory.prototype.getChunk = function(chunkId, type, program, core, core2) {

var chunkClass = SceneJS_ChunkFactory.chunkTypes[type]; // Check type supported

Expand All @@ -85,11 +85,12 @@ SceneJS_ChunkFactory.prototype.getChunk = function(chunkId, type, program, core)

if (chunk) { // Reinitialise the recycled chunk

chunk.init(chunkId, program, core);
chunk.init(chunkId, program, core, core2);

} else { // Instantiate a fresh chunk

chunk = new chunkClass(chunkId, program, core); // Create new chunk
chunk = new chunkClass(chunkId, program, core, core2); // Create new chunk

}

chunk.useCount = 1;
Expand Down
2 changes: 1 addition & 1 deletion src/core/display/chunks/drawChunk.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ SceneJS_ChunkFactory.createChunkType({

gl.drawElements(this.core.primitive, this.core.indexBuf.numItems, gl.UNSIGNED_SHORT, 0);
}
});
});
247 changes: 158 additions & 89 deletions src/core/display/chunks/geometryChunk.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,6 @@ SceneJS_ChunkFactory.createChunkType({

type:"geometry",

/**
* As we apply a list of state chunks in a {@link SceneJS_Display}, we track the ID of each chunk
* in order to avoid redundantly re-applying the same chunk.
*
* We don't want that for draw chunks however, because they contain GL drawElements calls,
* which we need to do for each object.
*/
unique:true,

build:function () {

var draw = this.program.draw;
Expand All @@ -24,130 +15,208 @@ SceneJS_ChunkFactory.createChunkType({
this._aUV2Draw = draw.getAttribute("SCENEJS_aUVCoord2");
this._aColorDraw = draw.getAttribute("SCENEJS_aVertexColor");

this.VAO = null;
this.VAOHasInterleavedBuf = false;
this._aMorphVertexDraw = draw.getAttribute("SCENEJS_aMorphVertex");
this._aMorphNormalDraw = draw.getAttribute("SCENEJS_aMorphNormal");
this._uMorphFactorDraw = draw.getUniformLocation("SCENEJS_uMorphFactor");

var pick = this.program.pick;

this._aVertexPick = pick.getAttribute("SCENEJS_aVertex");
this._aNormalPick = pick.getAttribute("SCENEJS_aNormal");
this._aUVPick = pick.getAttribute("SCENEJS_aUVCoord");
this._aUV2Pick = pick.getAttribute("SCENEJS_aUVCoord2");
this._aColorPick = pick.getAttribute("SCENEJS_aVertexColor");

this._aMorphVertexPick = pick.getAttribute("SCENEJS_aMorphVertex");
this._aMorphNormalPick = pick.getAttribute("SCENEJS_aMorphNormal");
this._uMorphFactorPick = pick.getUniformLocation("SCENEJS_uMorphFactor");

this.VAO = null;
this.VAOMorphKey1 = 0;
this.VAOMorphKey2 = 0;
this.VAOHasInterleavedBuf = false;
},

recycle:function () {
if (this.VAO) {
// Guarantee that the old VAO is deleted immediately when recycling the object.
var VAOExt = this.program.gl.getExtension("OES_vertex_array_object");
VAOExt.deleteVertexArrayOES(this.VAO);
this.VAO = null;
}
},

draw:function (ctx) {
morphDraw:function () {
this.VAOMorphKey1 = this.core.key1;
this.VAOMorphKey2 = this.core.key2;

var gl = this.program.gl;
var target1 = this.core.targets[this.core.key1]; // Keys will update
var target2 = this.core.targets[this.core.key2];

if (this._aMorphVertexDraw) {
this._aVertexDraw.bindFloatArrayBuffer(target1.vertexBuf);
this._aMorphVertexDraw.bindFloatArrayBuffer(target2.vertexBuf);
} else if (this._aVertexDraw) {
this._aVertexDraw.bindFloatArrayBuffer(this.core2.vertexBuf);
}

if (this._aMorphNormalDraw) {
this._aNormalDraw.bindFloatArrayBuffer(target1.normalBuf);
this._aMorphNormalDraw.bindFloatArrayBuffer(target2.normalBuf);
} else if (this._aNormalDraw) {
this._aNormalDraw.bindFloatArrayBuffer(this.core2.normalBuf);
}

if (this._aUVDraw) {
this._aUVDraw.bindFloatArrayBuffer(this.core2.uvBuf);
}

if (this._aUV2Draw) {
this._aUV2Draw.bindFloatArrayBuffer(this.core2.uvBuf2);
}

if (ctx.geoChunkId != this.id) { // HACK until we have distinct state chunks for VBOs and draw call
var ctxBufsActive = ctx.vertexBuf || ctx.normalBuf || ctx.uvBuf || ctx.uvBuf2 || ctx.colorBuf;
if (this.VAO && (ctxBufsActive ||
this.core.interleavedBuf && this.core.interleavedBuf.dirty && this.VAOHasInterleavedBuf)) {
// Need to recreate VAO to refer to separate buffers, or can't use VAO due to buffers
// specified outside.
ctx.VAO.deleteVertexArrayOES(this.VAO);
this.VAO = null;
if (this._aColorDraw) {
this._aColorDraw.bindFloatArrayBuffer(this.core2.colorBuf);
}

this.setDrawMorphFactor();
},

setDrawMorphFactor:function () {

if (this._uMorphFactorDraw) {
this.program.gl.uniform1f(this._uMorphFactorDraw, this.core.factor); // Bind LERP factor
}

},

draw:function (ctx) {
var doMorph = this.core.targets && this.core.targets.length;
var cleanInterleavedBuf = this.core2.interleavedBuf && !this.core2.interleavedBuf.dirty;

if (this.VAO) {
ctx.VAO.bindVertexArrayOES(this.VAO);
if (doMorph) {
if (this.VAOMorphKey1 == this.core.key1 && this.VAOMorphKey2 == this.core.key2) {
this.setDrawMorphFactor();
return;
}
} else if (cleanInterleavedBuf || !this.VAOHasInterleavedBuf) {
return;
}
if (this.VAO) {
ctx.VAO.bindVertexArrayOES(this.VAO);
} else if (ctx.VAO) {
// Start creating a new VAO by switching to the default VAO, which doesn't have attribs enabled.
ctx.VAO.bindVertexArrayOES(null);
this.VAO = ctx.VAO.createVertexArrayOES();
ctx.VAO.bindVertexArrayOES(this.VAO);
var gl = this.program.gl;
}

if (doMorph) {
this.morphDraw();
} else {
if (cleanInterleavedBuf) {
this.VAOHasInterleavedBuf = true;
this.core2.interleavedBuf.bind();
if (this._aVertexDraw) {
this._aVertexDraw.bindInterleavedFloatArrayBuffer(3, this.core2.interleavedStride, this.core2.interleavedPositionOffset);
}
if (this._aNormalDraw) {
this._aNormalDraw.bindInterleavedFloatArrayBuffer(3, this.core2.interleavedStride, this.core2.interleavedNormalOffset);
}
if (this._aUVDraw) {
this._aUVDraw.bindInterleavedFloatArrayBuffer(2, this.core2.interleavedStride, this.core2.interleavedUVOffset);
}
if (this._aUV2Draw) {
this._aUV2Draw.bindInterleavedFloatArrayBuffer(2, this.core2.interleavedStride, this.core2.interleavedUV2Offset);
}
if (this._aColorDraw) {
this._aColorDraw.bindInterleavedFloatArrayBuffer(4, this.core2.interleavedStride, this.core2.interleavedColorOffset);
}
} else {
var useInterleavedBuf = (this.core.interleavedBuf && !this.core.interleavedBuf.dirty);
if (ctx.VAO && !ctxBufsActive) {
this.VAO = ctx.VAO.createVertexArrayOES();
ctx.VAO.bindVertexArrayOES(this.VAO);
this.VAOHasInterleavedBuf = useInterleavedBuf;
this.VAOHasInterleavedBuf = false;
if (this._aVertexDraw) {
this._aVertexDraw.bindFloatArrayBuffer(this.core2.vertexBuf);
}

if (this._aNormalDraw) {
this._aNormalDraw.bindFloatArrayBuffer(this.core2.normalBuf);
}

if (this._aUVDraw) {
this._aUVDraw.bindFloatArrayBuffer(this.core2.uvBuf);
}

if (useInterleavedBuf) {
this.core.interleavedBuf.bind();
if (this._aVertexDraw && !ctx.vertexBuf) {
this._aVertexDraw.bindInterleavedFloatArrayBuffer(3, this.core.interleavedStride, this.core.interleavedPositionOffset);
}
if (this._aNormalDraw && !ctx.normalBuf) {
this._aNormalDraw.bindInterleavedFloatArrayBuffer(3, this.core.interleavedStride, this.core.interleavedNormalOffset);
}
if (this._aUVDraw && !ctx.uvBuf) {
this._aUVDraw.bindInterleavedFloatArrayBuffer(2, this.core.interleavedStride, this.core.interleavedUVOffset);
}
if (this._aUV2Draw && !ctx.uv2Buf) {
this._aUV2Draw.bindInterleavedFloatArrayBuffer(2, this.core.interleavedStride, this.core.interleavedUV2Offset);
}
if (this._aColorDraw && !ctx.colorBuf) {
this._aColorDraw.bindInterleavedFloatArrayBuffer(4, this.core.interleavedStride, this.core.interleavedColorOffset);
}
} else {
if (this._aVertexDraw && !ctx.vertexBuf) {
this._aVertexDraw.bindFloatArrayBuffer(this.core.vertexBuf);
}

if (this._aNormalDraw && !ctx.normalBuf) {
this._aNormalDraw.bindFloatArrayBuffer(this.core.normalBuf);
}

if (this._aUVDraw && !ctx.uvBuf) {
this._aUVDraw.bindFloatArrayBuffer(this.core.uvBuf);
}

if (this._aUV2Draw && !ctx.uvBuf2) {
this._aUV2Draw.bindFloatArrayBuffer(this.core.uvBuf2);
}

if (this._aColorDraw && !ctx.colorBuf) {
this._aColorDraw.bindFloatArrayBuffer(this.core.colorBuf);
}
if (this._aUV2Draw) {
this._aUV2Draw.bindFloatArrayBuffer(this.core2.uvBuf2);
}

this.core.indexBuf.bind();
if (this._aColorDraw) {
this._aColorDraw.bindFloatArrayBuffer(this.core2.colorBuf);
}
}
}

gl.drawElements(this.core.primitive, this.core.indexBuf.numItems, gl.UNSIGNED_SHORT, 0);
this.core2.indexBuf.bind();

if (this.VAO) {
// We don't want following nodes that don't use their own VAOs to muck up
// this node's VAO, so we need to unbind it.
ctx.VAO.bindVertexArrayOES(null);
} else {
ctx.geoChunkId = this.id;
},

morphPick:function () {

var target1 = this.core.targets[this.core.key1]; // Keys will update
var target2 = this.core.targets[this.core.key2];

if (this._aMorphVertexPick) {
this._aVertexPick.bindFloatArrayBuffer(target1.vertexBuf);
this._aMorphVertexPick.bindFloatArrayBuffer(target2.vertexBuf);
} else if (this._aVertexPick) {
this._aVertexPick.bindFloatArrayBuffer(this.core2.vertexBuf);
}

if (this._aMorphNormalPick) {
this._aNormalPick.bindFloatArrayBuffer(target1.normalBuf);
this._aMorphNormalPick.bindFloatArrayBuffer(target2.normalBuf);
} else if (this._aNormalPick) {
this._aNormalPick.bindFloatArrayBuffer(this.core2.normalBuf);
}

if (this._aUVPick) {
this._aUVPick.bindFloatArrayBuffer(this.core2.uvBuf);
}

if (this._aUV2Pick) {
this._aUV2Pick.bindFloatArrayBuffer(this.core2.uvBuf2);
}

if (this._uMorphFactorPick) {
this.program.gl.uniform1f(this._uMorphFactorPick, this.core.factor); // Bind LERP factor
}

},

pick:function (ctx) {

var gl = this.program.gl;

if (ctx.geoChunkId != this.id) { // HACK until we have distinct state chunks for VBOs and draw call
if (this.core.targets && this.core.targets.length) {
this.morphPick();
} else {

if (this._aVertexPick && !ctx.vertexBuf) {
this._aVertexPick.bindFloatArrayBuffer(this.core.vertexBuf);
if (this._aVertexPick) {
this._aVertexPick.bindFloatArrayBuffer(this.core2.vertexBuf);
}

if (this._aNormalPick && !ctx.normalBuf) {
this._aNormalPick.bindFloatArrayBuffer(this.core.normalBuf);
if (this._aNormalPick) {
this._aNormalPick.bindFloatArrayBuffer(this.core2.normalBuf);
}

if (this._aUVPick && !ctx.uvBuf) {
this._aUVPick.bindFloatArrayBuffer(this.core.uvBuf);
if (this._aUVPick) {
this._aUVPick.bindFloatArrayBuffer(this.core2.uvBuf);
}

if (this._aUV2Pick && !ctx.uvBuf2) {
this._aUV2Pick.bindFloatArrayBuffer(this.core.uvBuf2);
if (this._aUV2Pick) {
this._aUV2Pick.bindFloatArrayBuffer(this.core2.uvBuf2);
}

this.core.indexBuf.bind();

ctx.geoChunkId = this.id;
}

gl.drawElements(this.core.primitive, this.core.indexBuf.numItems, gl.UNSIGNED_SHORT, 0);
this.core2.indexBuf.bind();
}
});
Loading

0 comments on commit 6d1b4ec

Please sign in to comment.