Skip to content

Commit

Permalink
Merge pull request cocos#38 from dabingnn/3d_work
Browse files Browse the repository at this point in the history
add immediate renderer in scene
  • Loading branch information
jwu authored Feb 27, 2017
2 parents ff8ef36 + 90adf20 commit b3ccc53
Showing 1 changed file with 233 additions and 0 deletions.
233 changes: 233 additions & 0 deletions cocos2d/core/CCScene3D.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,238 @@

var NIL = function () {};

var Immediate = function (scene_) {
var scene = scene_;
var graphicDevice = cc.renderer.device;
var lineVertexFormat = null;
var lineBatches = [];
var quadMesh = null;
var cubeLocalPos = null;
var cubeWorldPos = null;

var lineBatch = function () {
// Sensible default value; buffers will be doubled and reallocated when it's not enough
this.numLinesAllocated = 128;

this.vb = null;
this.vbRam = null;
this.mesh = null;
this.linesUsed = 0;
this.material = null;
this.meshInstance = null;
};

lineBatch.prototype = {
init: function (device, linesToAdd) {
// Allocate basic stuff once per batch
if (!this.mesh) {
this.mesh = new cc3d.Mesh();
this.mesh.primitive[0].type = cc3d.PRIMITIVE_LINES;
this.mesh.primitive[0].base = 0;
this.mesh.primitive[0].indexed = false;

this.material = new cc3d.BasicMaterial();
this.material.vertexColors = true;
this.material.blend = true;
this.material.blendType = cc3d.BLEND_NORMAL;
this.material.update();
}

// Increase buffer size, if it's not enough
while ((this.linesUsed + linesToAdd) > this.numLinesAllocated) {
this.vb = null;
this.numLinesAllocated *= 2;
}

// (Re)allocate line buffer
if (!this.vb) {
this.vb = new cc3d.VertexBuffer(device, lineVertexFormat, this.numLinesAllocated * 2, cc3d.BUFFER_DYNAMIC);
this.mesh.vertexBuffer = this.vb;
this.vbRam = new DataView(this.vb.lock());

if (!this.meshInstance) {
var node = {_worldTransform: cc.Mat4.IDENTITY};
this.meshInstance = new cc3d.MeshInstance(node, this.mesh, this.material);
}
}
},

addLines: function (position, color) {
// Append lines to buffer
var multiColor = !!color.length;
var offset = this.linesUsed * 2 * lineVertexFormat.size;
var clr;
for (var i = 0; i < position.length; i++) {
this.vbRam.setFloat32(offset, position[i].x, true);
offset += 4;
this.vbRam.setFloat32(offset, position[i].y, true);
offset += 4;
this.vbRam.setFloat32(offset, position[i].z, true);
offset += 4;
clr = multiColor ? color[i] : color;
this.vbRam.setUint8(offset, clr.r * 255);
offset += 1;
this.vbRam.setUint8(offset, clr.g * 255);
offset += 1;
this.vbRam.setUint8(offset, clr.b * 255);
offset += 1;
this.vbRam.setUint8(offset, clr.a * 255);
offset += 1;
}
this.linesUsed += position.length / 2;
},

finalize: function (drawCalls) {
// Update batch vertex buffer/issue drawcall if there are any lines
if (this.linesUsed > 0) {
this.vb.setData(this.vbRam.buffer);
this.mesh.primitive[0].count = this.linesUsed * 2;
drawCalls.push(this.meshInstance);
this.linesUsed = 0;
}
}
};

this._addLines = function (batchId, position, color) {
// Init global line drawing data once
if (!lineVertexFormat) {
lineVertexFormat = new cc3d.VertexFormat(graphicDevice, [
{semantic: cc3d.SEMANTIC_POSITION, components: 3, type: cc3d.ELEMENTTYPE_FLOAT32},
{semantic: cc3d.SEMANTIC_COLOR, components: 4, type: cc3d.ELEMENTTYPE_UINT8, normalize: true}
]);

cc.director.on(cc.Director.EVENT_BEFORE_VISIT, this._preRenderImmediate, this);
}
if (!lineBatches[batchId]) {
// Init used batch once
lineBatches[batchId] = new lineBatch();
lineBatches[batchId].init(graphicDevice, position.length / 2);
if (batchId === cc3d.LINEBATCH_OVERLAY) {
lineBatches[batchId].material.depthTest = false;
lineBatches[batchId].meshInstance.layer = cc3d.LAYER_GIZMO;
}
else if (batchId === cc3d.LINEBATCH_GIZMO) {
lineBatches[batchId].meshInstance.layer = cc3d.LAYER_GIZMO;
}
} else {
// Possibly reallocate buffer if it's small
lineBatches[batchId].init(graphicDevice, position.length / 2);
}
// Append
lineBatches[batchId].addLines(position, color);
}

this.renderLine = function (start, end, color, arg3, arg4) {
var endColor = color;
var lineType = cc3d.LINEBATCH_WORLD;
if (arg3) {
if (typeof(arg3) === 'number') {
lineType = arg3;
} else {
endColor = arg3;
if (arg4) lineType = arg4;
}
}
this._addLines(lineType, [start, end], [color, endColor]);
}

this.renderLines = function (position, color, lineType) {
if (lineType === undefined) lineType = cc3d.LINEBATCH_WORLD;
var multiColor = !!color.length;
if (multiColor) {
if (position.length !== color.length) {
cc.error("renderLines: position/color arrays have different lengths");
return;
}
}
if (position.length % 2 !== 0) {
cc.error("renderLines: array length is not divisible by 2");
return;
}
this._addLines(lineType, position, color);
}

this.renderWireCube = function (matrix, color, lineType) {
if (lineType === undefined) lineType = cc3d.LINEBATCH_WORLD;
var i;
// Init cube data once
if (!cubeLocalPos) {
var x = 0.5;
cubeLocalPos = [new cc.Vec3(-x, -x, -x), new cc.Vec3(-x, x, -x), new cc.Vec3(x, x, -x), new cc.Vec3(x, -x, -x),
new cc.Vec3(-x, -x, x), new cc.Vec3(-x, x, x), new cc.Vec3(x, x, x), new cc.Vec3(x, -x, x)];
cubeWorldPos = [new cc.Vec3(), new cc.Vec3(), new cc.Vec3(), new cc.Vec3(),
new cc.Vec3(), new cc.Vec3(), new cc.Vec3(), new cc.Vec3()];
}
// Transform and append lines
for (i = 0; i < 8; i++) {
matrix.transformPoint(cubeLocalPos[i], cubeWorldPos[i]);
}
this.renderLines([cubeWorldPos[0], cubeWorldPos[1],
cubeWorldPos[1], cubeWorldPos[2],
cubeWorldPos[2], cubeWorldPos[3],
cubeWorldPos[3], cubeWorldPos[0],

cubeWorldPos[4], cubeWorldPos[5],
cubeWorldPos[5], cubeWorldPos[6],
cubeWorldPos[6], cubeWorldPos[7],
cubeWorldPos[7], cubeWorldPos[4],

cubeWorldPos[0], cubeWorldPos[4],
cubeWorldPos[1], cubeWorldPos[5],
cubeWorldPos[2], cubeWorldPos[6],
cubeWorldPos[3], cubeWorldPos[7]
], color, lineType);
}

this._preRenderImmediate = function () {
for (var i = 0; i < 3; i++) {
if (lineBatches[i]) {
lineBatches[i].finalize(scene.immediateDrawCalls);
}
}
}

this.renderMeshInstance = function (meshInstance) {
scene.immediateDrawCalls.push(meshInstance);
}

this.renderMesh = function (mesh, material, matrix) {
var node = {_worldTransform: matrix};
var instance = new cc3d.MeshInstance(node, mesh, material);
scene.immediateDrawCalls.push(instance);
}

this.renderQuad = function (matrix, material, layer) {
// Init quad data once
if (!quadMesh) {
var format = new cc3d.VertexFormat(graphicDevice, [
{semantic: cc3d.SEMANTIC_POSITION, components: 3, type: cc3d.ELEMENTTYPE_FLOAT32}
]);
var quadVb = new cc3d.VertexBuffer(graphicDevice, format, 4);
var iterator = new cc3d.VertexIterator(quadVb);
iterator.element[cc3d.SEMANTIC_POSITION].set(-0.5, -0.5, 0);
iterator.next();
iterator.element[cc3d.SEMANTIC_POSITION].set(0.5, -0.5, 0);
iterator.next();
iterator.element[cc3d.SEMANTIC_POSITION].set(-0.5, 0.5, 0);
iterator.next();
iterator.element[cc3d.SEMANTIC_POSITION].set(0.5, 0.5, 0);
iterator.end();
quadMesh = new cc3d.Mesh();
quadMesh.vertexBuffer = quadVb;
quadMesh.primitive[0].type = cc3d.PRIMITIVE_TRISTRIP;
quadMesh.primitive[0].base = 0;
quadMesh.primitive[0].count = 4;
quadMesh.primitive[0].indexed = false;
}
// Issue quad drawcall
var node = {_worldTransform: matrix};
var quad = new cc3d.MeshInstance(node, quadMesh, material);
if (layer) quad.layer = layer;
scene.immediateDrawCalls.push(quad);
}
};

/**
* !#en
* cc.Scene3D is a subclass of cc.Node that is used only as an abstract concept.<br/>
Expand Down Expand Up @@ -59,6 +291,7 @@ cc.Scene3D = cc.Class({
this.dependAssets = null;

this._cameras = [];
this.immediateRenderer = new Immediate(this._sgScene);
},

destroy: function () {
Expand Down

0 comments on commit b3ccc53

Please sign in to comment.