提交 8ec6317e 编写于 作者: A alteredq

Added BufferGeometry for direct rendering from typed arrays.

Work in progress. For the moment works just with CTMLoader. Still not sure where some pieces of code would go.

Upsides:
	- initialization time cut down significantly (1.8 seconds => 0.7 seconds for CTM example)
	- much smaller GL buffers thanks to fully used indexing (Walt has 6x less vertices)
	- consequently much smaller memory footprint all around, both for main and GPU memories,
	  which means less swapping and better vertex caching

Downsides:
	- can't have anymore sharp per-face effects like flat shading (at least if mesh is not constructed in a way where each face has own vertices)
	- can't have multiple materials per mesh
	- no more easy manipulation of anything (for the moment actually no runtime manipulation at all, typed arrays are just thrown away, dynamic geometries code path not yet implemented)
上级 4a82869c
因为 它太大了无法显示 source diff 。你可以改为 查看blob
......@@ -89,7 +89,7 @@ d[c.b].addSelf(c.normal),d[c.c].addSelf(c.normal),d[c.d].addSelf(c.normal));a=0;
b,c,d,e,f,D){j=a.vertices[b].position;n=a.vertices[c].position;k=a.vertices[d].position;l=g[e];h=g[f];m=g[D];o=n.x-j.x;p=k.x-j.x;i=n.y-j.y;q=k.y-j.y;F=n.z-j.z;x=k.z-j.z;I=h.u-l.u;G=m.u-l.u;r=h.v-l.v;C=m.v-l.v;y=1/(I*C-G*r);E.set((C*o-r*p)*y,(C*i-r*q)*y,(C*F-r*x)*y);O.set((I*p-G*o)*y,(I*q-G*i)*y,(I*x-G*F)*y);t[b].addSelf(E);t[c].addSelf(E);t[d].addSelf(E);A[b].addSelf(O);A[c].addSelf(O);A[d].addSelf(O)}var b,c,d,e,f,g,j,n,k,l,h,m,o,p,i,q,F,x,I,G,r,C,y,D,t=[],A=[],E=new THREE.Vector3,O=new THREE.Vector3,
$=new THREE.Vector3,U=new THREE.Vector3,J=new THREE.Vector3;b=0;for(c=this.vertices.length;b<c;b++)t[b]=new THREE.Vector3,A[b]=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)f=this.faces[b],g=this.faceVertexUvs[0][b],f instanceof THREE.Face3?a(this,f.a,f.b,f.c,0,1,2):f instanceof THREE.Face4&&(a(this,f.a,f.b,f.c,0,1,2),a(this,f.a,f.b,f.d,0,1,3));var K=["a","b","c","d"];b=0;for(c=this.faces.length;b<c;b++){f=this.faces[b];for(d=0;d<f.vertexNormals.length;d++)J.copy(f.vertexNormals[d]),e=f[K[d]],
D=t[e],$.copy(D),$.subSelf(J.multiplyScalar(J.dot(D))).normalize(),U.cross(f.vertexNormals[d],D),e=U.dot(A[e]),e=e<0?-1:1,f.vertexTangents[d]=new THREE.Vector4($.x,$.y,$.z,e)}this.hasTangents=!0},computeBoundingBox:function(){if(this.vertices.length>0){var a;a=this.vertices[0].position;this.boundingBox?(this.boundingBox.min.copy(a),this.boundingBox.max.copy(a)):this.boundingBox={min:a.clone(),max:a.clone()};for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;d<e;d++){a=
this.vertices[d].position;if(a.x<b.x)b.x=a.x;else if(a.x>c.x)c.x=a.x;if(a.y<b.y)b.y=a.y;else if(a.y>c.y)c.y=a.y;if(a.z<b.z)b.z=a.z;else if(a.z>c.z)c.z=a.z}}},computeBoundingSphere:function(){for(var a=0,b=0,c=this.vertices.length;b<c;b++)a=Math.max(a,this.vertices[b].position.length());this.boundingSphere={radius:a}},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g;f=0;for(g=this.vertices.length;f<g;f++)d=this.vertices[f].position,d=[Math.round(d.x*e),Math.round(d.y*e),Math.round(d.z*
this.vertices[d].position;if(a.x<b.x)b.x=a.x;else if(a.x>c.x)c.x=a.x;if(a.y<b.y)b.y=a.y;else if(a.y>c.y)c.y=a.y;if(a.z<b.z)b.z=a.z;else if(a.z>c.z)c.z=a.z}}},computeBoundingSphere:function(){for(var a,b=0,c=0,d=this.vertices.length;c<d;c++)a=this.vertices[c].position.length(),a>b&&(b=a);this.boundingSphere={radius:b}},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g;f=0;for(g=this.vertices.length;f<g;f++)d=this.vertices[f].position,d=[Math.round(d.x*e),Math.round(d.y*e),Math.round(d.z*
e)].join("_"),a[d]===void 0?(a[d]=f,b.push(this.vertices[f]),c[f]=b.length-1):c[f]=c[a[d]];f=0;for(g=this.faces.length;f<g;f++)if(a=this.faces[f],a instanceof THREE.Face3)a.a=c[a.a],a.b=c[a.b],a.c=c[a.c];else if(a instanceof THREE.Face4)a.a=c[a.a],a.b=c[a.b],a.c=c[a.c],a.d=c[a.d];this.vertices=b}};THREE.GeometryCount=0;
THREE.Camera=function(){if(arguments.length)return console.warn("DEPRECATED: Camera() is now PerspectiveCamera() or OrthographicCamera()."),new THREE.PerspectiveCamera(arguments[0],arguments[1],arguments[2],arguments[3]);THREE.Object3D.call(this);this.matrixWorldInverse=new THREE.Matrix4;this.projectionMatrix=new THREE.Matrix4;this.projectionMatrixInverse=new THREE.Matrix4};THREE.Camera.prototype=new THREE.Object3D;THREE.Camera.prototype.constructor=THREE.Camera;
THREE.Camera.prototype.lookAt=function(a){this.matrix.lookAt(this.position,a,this.up);this.rotationAutoUpdate&&this.rotation.setRotationFromMatrix(this.matrix)};THREE.OrthographicCamera=function(a,b,c,d,e,f){THREE.Camera.call(this);this.left=a;this.right=b;this.top=c;this.bottom=d;this.near=e!==void 0?e:0.1;this.far=f!==void 0?f:2E3;this.updateProjectionMatrix()};THREE.OrthographicCamera.prototype=new THREE.Camera;THREE.OrthographicCamera.prototype.constructor=THREE.OrthographicCamera;
......
......@@ -29,6 +29,7 @@ THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,"v
THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n"),vertexShader:["attribute vec4 tangent;\nuniform vec2 uOffset;\nuniform vec2 uRepeat;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\nuniform float pointLightDistance[ MAX_POINT_LIGHTS ];\nvarying vec4 vPointLight[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;",
THREE.ShaderChunk.shadowmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvViewPosition = -mvPosition.xyz;\nvNormal = normalMatrix * normal;\nvTangent = normalMatrix * tangent.xyz;\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvUv = uv * uRepeat + uOffset;\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 lVector = lPosition.xyz - mvPosition.xyz;\nfloat lDistance = 1.0;\nif ( pointLightDistance[ i ] > 0.0 )\nlDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );\nlVector = normalize( lVector );\nvPointLight[ i ] = vec4( lVector, lDistance );\n}\n#endif\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( normalize( vNormal.xyz ) * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif",
THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:1,texture:null},tFlip:{type:"f",value:-1}},vertexShader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragmentShader:"uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );\n}"}}};
THREE.BufferGeometry=function(){this.id=THREE.GeometryCount++;this.vertexColorArray=this.vertexUvArray=this.vertexNormalArray=this.vertexPositionArray=this.vertexIndexArray=this.vertexColorBuffer=this.vertexUvBuffer=this.vertexNormalBuffer=this.vertexPositionBuffer=this.vertexIndexBuffer=null;this.dynamic=!1;this.boundingSphere=this.boundingBox=null;this.morphTargets=[]};THREE.BufferGeometry.prototype={constructor:THREE.BufferGeometry,computeBoundingBox:function(){},computeBoundingSphere:function(){}};
THREE.Curve=function(){};THREE.Curve.prototype.getPoint=function(){console.log("Warning, getPoint() not implemented!");return null};THREE.Curve.prototype.getPointAt=function(a){return this.getPoint(this.getUtoTmapping(a))};THREE.Curve.prototype.getPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPoint(b/a));return c};THREE.Curve.prototype.getSpacedPoints=function(a){a||(a=5);var b,c=[];for(b=0;b<=a;b++)c.push(this.getPointAt(b/a));return c};
THREE.Curve.prototype.getLength=function(){var a=this.getLengths();return a[a.length-1]};THREE.Curve.prototype.getLengths=function(a){a||(a=200);if(this.cacheArcLengths&&this.cacheArcLengths.length==a+1)return this.cacheArcLengths;var b=[],c,d=this.getPoint(0),e,g=0;b.push(0);for(e=1;e<=a;e++)c=this.getPoint(e/a),g+=c.distanceTo(d),b.push(g),d=c;return this.cacheArcLengths=b};
THREE.Curve.prototype.getUtoTmapping=function(a,b){var c=this.getLengths(),d=0,e=c.length,g;g=b?b:a*c[e-1];for(var f=0,h=e-1,i;f<=h;)if(d=Math.floor(f+(h-f)/2),i=c[d]-g,i<0)f=d+1;else if(i>0)h=d-1;else{h=d;break}d=h;if(c[d]==g)return d/(e-1);f=c[d];return c=(d+(g-f)/(c[d+1]-f))/(e-1)};THREE.Curve.prototype.getNormalVector=function(a){a=this.getTangent(a);return new THREE.Vector2(-a.y,a.x)};
......
......@@ -89,7 +89,7 @@ d[c.b].addSelf(c.normal),d[c.c].addSelf(c.normal),d[c.d].addSelf(c.normal));a=0;
b,c,d,e,f,A){h=a.vertices[b].position;l=a.vertices[c].position;i=a.vertices[d].position;k=g[e];j=g[f];n=g[A];m=l.x-h.x;o=i.x-h.x;p=l.y-h.y;u=i.y-h.y;F=l.z-h.z;v=i.z-h.z;D=j.u-k.u;s=n.u-k.u;t=j.v-k.v;B=n.v-k.v;x=1/(D*B-s*t);I.set((B*m-t*o)*x,(B*p-t*u)*x,(B*F-t*v)*x);z.set((D*o-s*m)*x,(D*u-s*p)*x,(D*v-s*F)*x);H[b].addSelf(I);H[c].addSelf(I);H[d].addSelf(I);C[b].addSelf(z);C[c].addSelf(z);C[d].addSelf(z)}var b,c,d,e,f,g,h,l,i,k,j,n,m,o,p,u,F,v,D,s,t,B,x,y,H=[],C=[],I=new THREE.Vector3,z=new THREE.Vector3,
L=new THREE.Vector3,J=new THREE.Vector3,M=new THREE.Vector3;b=0;for(c=this.vertices.length;b<c;b++)H[b]=new THREE.Vector3,C[b]=new THREE.Vector3;b=0;for(c=this.faces.length;b<c;b++)f=this.faces[b],g=this.faceVertexUvs[0][b],f instanceof THREE.Face3?a(this,f.a,f.b,f.c,0,1,2):f instanceof THREE.Face4&&(a(this,f.a,f.b,f.c,0,1,2),a(this,f.a,f.b,f.d,0,1,3));var N=["a","b","c","d"];b=0;for(c=this.faces.length;b<c;b++){f=this.faces[b];for(d=0;d<f.vertexNormals.length;d++)M.copy(f.vertexNormals[d]),e=f[N[d]],
y=H[e],L.copy(y),L.subSelf(M.multiplyScalar(M.dot(y))).normalize(),J.cross(f.vertexNormals[d],y),e=J.dot(C[e]),e=e<0?-1:1,f.vertexTangents[d]=new THREE.Vector4(L.x,L.y,L.z,e)}this.hasTangents=!0},computeBoundingBox:function(){if(this.vertices.length>0){var a;a=this.vertices[0].position;this.boundingBox?(this.boundingBox.min.copy(a),this.boundingBox.max.copy(a)):this.boundingBox={min:a.clone(),max:a.clone()};for(var b=this.boundingBox.min,c=this.boundingBox.max,d=1,e=this.vertices.length;d<e;d++){a=
this.vertices[d].position;if(a.x<b.x)b.x=a.x;else if(a.x>c.x)c.x=a.x;if(a.y<b.y)b.y=a.y;else if(a.y>c.y)c.y=a.y;if(a.z<b.z)b.z=a.z;else if(a.z>c.z)c.z=a.z}}},computeBoundingSphere:function(){for(var a=0,b=0,c=this.vertices.length;b<c;b++)a=Math.max(a,this.vertices[b].position.length());this.boundingSphere={radius:a}},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g;f=0;for(g=this.vertices.length;f<g;f++)d=this.vertices[f].position,d=[Math.round(d.x*e),Math.round(d.y*e),Math.round(d.z*
this.vertices[d].position;if(a.x<b.x)b.x=a.x;else if(a.x>c.x)c.x=a.x;if(a.y<b.y)b.y=a.y;else if(a.y>c.y)c.y=a.y;if(a.z<b.z)b.z=a.z;else if(a.z>c.z)c.z=a.z}}},computeBoundingSphere:function(){for(var a,b=0,c=0,d=this.vertices.length;c<d;c++)a=this.vertices[c].position.length(),a>b&&(b=a);this.boundingSphere={radius:b}},mergeVertices:function(){var a={},b=[],c=[],d,e=Math.pow(10,4),f,g;f=0;for(g=this.vertices.length;f<g;f++)d=this.vertices[f].position,d=[Math.round(d.x*e),Math.round(d.y*e),Math.round(d.z*
e)].join("_"),a[d]===void 0?(a[d]=f,b.push(this.vertices[f]),c[f]=b.length-1):c[f]=c[a[d]];f=0;for(g=this.faces.length;f<g;f++)if(a=this.faces[f],a instanceof THREE.Face3)a.a=c[a.a],a.b=c[a.b],a.c=c[a.c];else if(a instanceof THREE.Face4)a.a=c[a.a],a.b=c[a.b],a.c=c[a.c],a.d=c[a.d];this.vertices=b}};THREE.GeometryCount=0;
THREE.Camera=function(){if(arguments.length)return console.warn("DEPRECATED: Camera() is now PerspectiveCamera() or OrthographicCamera()."),new THREE.PerspectiveCamera(arguments[0],arguments[1],arguments[2],arguments[3]);THREE.Object3D.call(this);this.matrixWorldInverse=new THREE.Matrix4;this.projectionMatrix=new THREE.Matrix4;this.projectionMatrixInverse=new THREE.Matrix4};THREE.Camera.prototype=new THREE.Object3D;THREE.Camera.prototype.constructor=THREE.Camera;
THREE.Camera.prototype.lookAt=function(a){this.matrix.lookAt(this.position,a,this.up);this.rotationAutoUpdate&&this.rotation.setRotationFromMatrix(this.matrix)};THREE.OrthographicCamera=function(a,b,c,d,e,f){THREE.Camera.call(this);this.left=a;this.right=b;this.top=c;this.bottom=d;this.near=e!==void 0?e:0.1;this.far=f!==void 0?f:2E3;this.updateProjectionMatrix()};THREE.OrthographicCamera.prototype=new THREE.Camera;THREE.OrthographicCamera.prototype.constructor=THREE.OrthographicCamera;
......
此差异已折叠。
......@@ -8,7 +8,9 @@
* @author alteredq / http://alteredqualia.com/
*/
THREE.CTMLoader = function ( ) {
THREE.CTMLoader = function ( context ) {
this.context = context;
};
......@@ -21,7 +23,9 @@ THREE.CTMLoader.prototype.constructor = THREE.CTMLoader;
// - url (required)
// - callback (required)
THREE.CTMLoader.prototype.load = function( url, callback, useWorker ) {
THREE.CTMLoader.prototype.load = function( url, callback, useWorker, useBuffers ) {
var scope = this;
var xhr = new XMLHttpRequest(),
callbackProgress = null;
......@@ -45,7 +49,16 @@ THREE.CTMLoader.prototype.load = function( url, callback, useWorker ) {
worker.onmessage = function( event ) {
var ctmFile = event.data;
THREE.CTMLoader.prototype.createModel( ctmFile, callback );
if ( useBuffers ) {
scope.createModelBuffers( ctmFile, callback );
} else {
scope.createModelClassic( ctmFile, callback );
}
var e = Date.now();
console.log( "CTM data parse time [worker]: " + (e-s) + " ms" );
......@@ -57,7 +70,16 @@ THREE.CTMLoader.prototype.load = function( url, callback, useWorker ) {
} else {
var ctmFile = new CTM.File( new CTM.Stream( binaryData ) );
THREE.CTMLoader.prototype.createModel( ctmFile, callback );
if ( useBuffers ) {
scope.createModelBuffers( ctmFile, callback );
} else {
scope.createModelClassic( ctmFile, callback );
}
var e = Date.now();
console.log( "CTM data parse time [inline]: " + (e-s) + " ms" );
......@@ -99,9 +121,313 @@ THREE.CTMLoader.prototype.load = function( url, callback, useWorker ) {
};
THREE.CTMLoader.prototype.createModel = function ( file, callback ) {
THREE.CTMLoader.prototype.createModelBuffers = function ( file, callback ) {
var gl = this.context;
var Model = function ( ) {
var scope = this;
var dynamic = false,
computeNormals = true,
normalizeNormals = true;
scope.materials = [];
THREE.BufferGeometry.call( this );
// init GL buffers
var vertexIndexArray = file.body.indices,
vertexPositionArray = file.body.vertices,
vertexNormalArray = file.body.normals;
var vertexUvArray, vertexColorArray;
//console.log( "vertices", vertexPositionArray.length/3 );
//console.log( "triangles", vertexIndexArray.length/3 );
// compute face normals from scratch
// (must be done before computing offsets)
if ( vertexNormalArray === undefined && computeNormals ) {
var nElements = vertexPositionArray.length;
vertexNormalArray = new Float32Array( nElements );
var vA, vB, vC, x, y, z,
pA = new THREE.Vector3(),
pB = new THREE.Vector3(),
pC = new THREE.Vector3(),
cb = new THREE.Vector3(),
ab = new THREE.Vector3();
for ( var i = 0; i < vertexIndexArray.length; i += 3 ) {
vA = vertexIndexArray[ i ];
vB = vertexIndexArray[ i + 1 ];
vC = vertexIndexArray[ i + 2 ];
x = vertexPositionArray[ vA * 3 ];
y = vertexPositionArray[ vA * 3 + 1 ];
z = vertexPositionArray[ vA * 3 + 2 ];
pA.set( x, y, z );
x = vertexPositionArray[ vB * 3 ];
y = vertexPositionArray[ vB * 3 + 1 ];
z = vertexPositionArray[ vB * 3 + 2 ];
pB.set( x, y, z );
x = vertexPositionArray[ vC * 3 ];
y = vertexPositionArray[ vC * 3 + 1 ];
z = vertexPositionArray[ vC * 3 + 2 ];
pC.set( x, y, z );
cb.sub( pC, pB );
ab.sub( pA, pB );
cb.crossSelf( ab );
vertexNormalArray[ vA * 3 ] += cb.x;
vertexNormalArray[ vA * 3 + 1 ] += cb.y;
vertexNormalArray[ vA * 3 + 2 ] += cb.z;
vertexNormalArray[ vB * 3 ] += cb.x;
vertexNormalArray[ vB * 3 + 1 ] += cb.y;
vertexNormalArray[ vB * 3 + 2 ] += cb.z;
vertexNormalArray[ vC * 3 ] += cb.x;
vertexNormalArray[ vC * 3 + 1 ] += cb.y;
vertexNormalArray[ vC * 3 + 2 ] += cb.z;
}
if ( normalizeNormals ) {
for ( var i = 0; i < nElements; i += 3 ) {
x = vertexNormalArray[ i ];
y = vertexNormalArray[ i + 1 ];
z = vertexNormalArray[ i + 2 ];
var n = 1.0 / Math.sqrt( x * x + y * y + z * z );
vertexNormalArray[ i ] *= n;
vertexNormalArray[ i + 1 ] *= n;
vertexNormalArray[ i + 2 ] *= n;
}
}
}
// compute offsets
scope.offsets = [];
var indices = file.body.indices;
var start = 0,
min = file.body.vertices.length,
max = 0,
minPrev = min;
for ( var i = 0; i < indices.length; ) {
for ( var j = 0; j < 3; ++ j ) {
var idx = indices[ i ++ ];
if ( idx < min ) min = idx;
if ( idx > max ) max = idx;
}
if ( max - min > 65535 ) {
i -= 3;
for ( var k = start; k < i; ++ k ) {
indices[ k ] -= minPrev;
}
scope.offsets.push( { start: start, count: i - start, index: minPrev } );
start = i;
min = file.body.vertices.length;
max = 0;
}
minPrev = min;
}
for ( var k = start; k < i; ++ k ) {
indices[ k ] -= minPrev;
}
scope.offsets.push( { start: start, count: i - start, index: minPrev } );
// indices
scope.vertexIndexBuffer = gl.createBuffer();
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, scope.vertexIndexBuffer );
gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( vertexIndexArray ), gl.STATIC_DRAW );
scope.vertexIndexBuffer.itemSize = 1;
scope.vertexIndexBuffer.numItems = vertexIndexArray.length;
// vertices
scope.vertexPositionBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, scope.vertexPositionBuffer );
gl.bufferData( gl.ARRAY_BUFFER, vertexPositionArray, gl.STATIC_DRAW );
scope.vertexPositionBuffer.itemSize = 3;
scope.vertexPositionBuffer.numItems = vertexPositionArray.length;
// normals
if ( vertexNormalArray !== undefined ) {
scope.vertexNormalBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, scope.vertexNormalBuffer );
gl.bufferData( gl.ARRAY_BUFFER, vertexNormalArray, gl.STATIC_DRAW );
scope.vertexNormalBuffer.itemSize = 3;
scope.vertexNormalBuffer.numItems = vertexNormalArray.length;
}
// uvs
if ( file.body.uvMaps !== undefined && file.body.uvMaps.length > 0 ) {
vertexUvArray = file.body.uvMaps[ 0 ].uv;
// "fix" flipping
for ( var i = 0; i < vertexUvArray.length; i += 2 ) {
vertexUvArray[ i + 1 ] = 1 - vertexUvArray[ i + 1 ];
}
scope.vertexUvBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, scope.vertexUvBuffer );
gl.bufferData( gl.ARRAY_BUFFER, vertexUvArray, gl.STATIC_DRAW );
scope.vertexUvBuffer.itemSize = 2;
scope.vertexUvBuffer.numItems = vertexUvArray.length;
}
// colors
if ( file.body.attrMaps !== undefined && file.body.attrMaps.length > 0 && file.body.attrMaps[ 0 ].name === "Color" ) {
vertexColorArray = file.body.attrMaps[ 0 ].attr;
scope.vertexColorBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, scope.vertexColorBuffer );
gl.bufferData( gl.ARRAY_BUFFER, vertexColorArray, gl.STATIC_DRAW );
scope.vertexColorBuffer.itemSize = 4;
scope.vertexColorBuffer.numItems = vertexColorArray.length;
}
// compute bounding sphere and bounding box
// (must do it now as we don't keep typed arrays after setting GL buffers)
scope.boundingBox = { min: new THREE.Vector3( Infinity, Infinity, Infinity ), max: new THREE.Vector3( -Infinity, -Infinity, -Infinity ) };
var vertices = file.body.vertices,
bb = scope.boundingBox,
radius, maxRadius = 0,
x, y, z;
for ( var i = 0, il = vertices.length; i < il; i += 3 ) {
x = vertices[ i ];
y = vertices[ i + 1 ];
z = vertices[ i + 2 ];
// bounding sphere
radius = Math.sqrt( x * x + y * y + z * z );
if ( radius > maxRadius ) maxRadius = radius;
// bounding box
if ( x < bb.min.x ) {
var Model = function ( texture_path ) {
bb.min.x = x;
} else if ( x > bb.max.x ) {
bb.max.x = x;
}
if ( y < bb.min.y ) {
bb.min.y = y;
} else if ( y > bb.max.y ) {
bb.max.y = y;
}
if ( z < bb.min.z ) {
bb.min.z = z;
} else if ( z > bb.max.z ) {
bb.max.z = z;
}
}
scope.boundingSphere = { radius: maxRadius };
// keep references to typed arrays
if ( dynamic ) {
scope.vertexIndexArray = vertexIndexArray;
scope.vertexPositionArray = vertexPositionArray;
scope.vertexNormalArray = vertexNormalArray;
scope.vertexUvArray = vertexUvArray;
scope.vertexColorArray = vertexColorArray;
}
}
Model.prototype = new THREE.BufferGeometry();
Model.prototype.constructor = Model;
callback( new Model() );
};
THREE.CTMLoader.prototype.createModelClassic = function ( file, callback ) {
var Model = function ( ) {
var scope = this;
......@@ -217,11 +543,16 @@ THREE.CTMLoader.prototype.createModel = function ( file, callback ) {
b = buffer[ i + 1 ];
c = buffer[ i + 2 ];
if ( hasNormals )
if ( hasNormals ){
face = f3n( scope, normals, a, b, c, m, a, b, c );
else
} else {
face = f3( scope, a, b, c, m );
}
if ( hasColors ) {
face.vertexColors[ 0 ] = colors[ a ];
......
......@@ -141,9 +141,10 @@
}
var useWorker = true;
var useWorker = true
useBuffers = true;
var loader = new THREE.CTMLoader();
var loader = new THREE.CTMLoader( renderer.context );
loader.load( "ctm/ben.ctm", function( geometry ) {
......@@ -151,7 +152,7 @@
callbackModel( geometry, 450, material, 0, -200, 0, 0, 0 );
checkTime();
}, useWorker );
}, useWorker, useBuffers );
loader.load( "ctm/WaltHead.ctm", function( geometry ) {
......@@ -161,7 +162,7 @@
callbackModel( geometry, 5, material, -200, 0, 0, 0, 0 );
checkTime();
}, useWorker );
}, useWorker, useBuffers );
loader.load( "ctm/LeePerry.ctm", function( geometry ) {
......@@ -169,7 +170,7 @@
callbackModel( geometry, 1300, material, 200, 50, 0, 0, 0 );
checkTime();
}, useWorker );
}, useWorker, useBuffers );
}
......
......@@ -401,17 +401,16 @@ THREE.Geometry.prototype = {
computeBoundingSphere: function () {
// var radius = this.boundingSphere === null ? 0 : this.boundingSphere.radius;
var radius = 0;
var radius, maxRadius = 0;
for ( var v = 0, vl = this.vertices.length; v < vl; v ++ ) {
radius = Math.max( radius, this.vertices[ v ].position.length() );
radius = this.vertices[ v ].position.length();
if ( radius > maxRadius ) maxRadius = radius;
}
this.boundingSphere = { radius: radius };
this.boundingSphere = { radius: maxRadius };
},
......
/**
* @author alteredq / http://alteredqualia.com/
*/
THREE.BufferGeometry = function () {
this.id = THREE.GeometryCount ++;
// GL buffers
this.vertexIndexBuffer = null;
this.vertexPositionBuffer = null;
this.vertexNormalBuffer = null;
this.vertexUvBuffer = null;
this.vertexColorBuffer = null;
// typed arrays (kept only if dynamic flag is set)
this.vertexIndexArray = null;
this.vertexPositionArray = null;
this.vertexNormalArray = null;
this.vertexUvArray = null;
this.vertexColorArray = null;
this.dynamic = false;
// boundings
this.boundingBox = null;
this.boundingSphere = null;
// for compatibility
this.morphTargets = [];
};
THREE.BufferGeometry.prototype = {
constructor : THREE.BufferGeometry,
// for compatibility
computeBoundingBox: function () {
},
// for compatibility
computeBoundingSphere: function () {
}
};
......@@ -22,7 +22,7 @@ THREE.Mesh = function ( geometry, material ) {
// calc bound radius
if( !this.geometry.boundingSphere ) {
if( ! this.geometry.boundingSphere ) {
this.geometry.computeBoundingSphere();
......
......@@ -2703,6 +2703,98 @@ THREE.WebGLRenderer = function ( parameters ) {
};
this.renderBufferDirect = function ( camera, lights, fog, material, geometryGroup, object ) {
if ( material.opacity === 0 ) return;
var program, attributes, linewidth, primitives, a, attribute, i, il;
program = setProgram( camera, lights, fog, material, object );
attributes = program.attributes;
var updateBuffers = false,
wireframeBit = material.wireframe ? 1 : 0,
geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
if ( geometryGroupHash !== _currentGeometryGroupHash ) {
_currentGeometryGroupHash = geometryGroupHash;
updateBuffers = true;
}
// render mesh
if ( object instanceof THREE.Mesh ) {
var offsets = geometryGroup.offsets;
for ( var i = 0; i < offsets.length; ++ i ) {
if ( updateBuffers ) {
// vertices
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.vertexPositionBuffer );
_gl.vertexAttribPointer( attributes.position, geometryGroup.vertexPositionBuffer.itemSize, _gl.FLOAT, false, 0, offsets[ i ].index * 4 * 3 );
// normals
if ( attributes.normal >= 0 && geometryGroup.vertexNormalBuffer ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.vertexNormalBuffer );
_gl.vertexAttribPointer( attributes.normal, geometryGroup.vertexNormalBuffer.itemSize, _gl.FLOAT, false, 0, offsets[ i ].index * 4 * 3 );
}
// uvs
if ( attributes.uv >= 0 && geometryGroup.vertexUvBuffer ) {
if ( geometryGroup.vertexUvBuffer ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.vertexUvBuffer );
_gl.vertexAttribPointer( attributes.uv, geometryGroup.vertexUvBuffer.itemSize, _gl.FLOAT, false, 0, offsets[ i ].index * 4 * 2 );
_gl.enableVertexAttribArray( attributes.uv );
} else {
_gl.disableVertexAttribArray( attributes.uv );
}
}
// colors
if ( attributes.color >= 0 && geometryGroup.vertexColorBuffer ) {
_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.vertexColorBuffer );
_gl.vertexAttribPointer( attributes.color, geometryGroup.vertexColorBuffer.itemSize, _gl.FLOAT, false, 0, offsets[ i ].index * 4 * 4 );
}
_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.vertexIndexBuffer );
}
// render indexed triangles
_gl.drawElements( _gl.TRIANGLES, offsets[ i ].count, _gl.UNSIGNED_SHORT, offsets[ i ].start * 2 ); // 2 = Uint16
_this.info.render.calls ++;
_this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
_this.info.render.faces += offsets[ i ].count / 3;
}
}
};
this.renderBuffer = function ( camera, lights, fog, material, geometryGroup, object ) {
if ( material.opacity === 0 ) return;
......@@ -3253,7 +3345,16 @@ THREE.WebGLRenderer = function ( parameters ) {
}
_this.setObjectFaces( object );
_this.renderBuffer( camera, lights, fog, material, buffer, object );
if ( buffer instanceof THREE.BufferGeometry ) {
_this.renderBufferDirect( camera, lights, fog, material, buffer, object );
} else {
_this.renderBuffer( camera, lights, fog, material, buffer, object );
}
}
......@@ -3524,32 +3625,36 @@ THREE.WebGLRenderer = function ( parameters ) {
geometry = object.geometry;
if ( geometry.geometryGroups === undefined ) {
if ( geometry instanceof THREE.Geometry ) {
sortFacesByMaterial( geometry );
if ( geometry.geometryGroups === undefined ) {
}
sortFacesByMaterial( geometry );
// create separate VBOs per geometry chunk
}
// create separate VBOs per geometry chunk
for ( g in geometry.geometryGroups ) {
for ( g in geometry.geometryGroups ) {
geometryGroup = geometry.geometryGroups[ g ];
geometryGroup = geometry.geometryGroups[ g ];
// initialise VBO on the first access
// initialise VBO on the first access
if ( ! geometryGroup.__webglVertexBuffer ) {
if ( ! geometryGroup.__webglVertexBuffer ) {
createMeshBuffers( geometryGroup );
initMeshBuffers( geometryGroup, object );
createMeshBuffers( geometryGroup );
initMeshBuffers( geometryGroup, object );
geometry.__dirtyVertices = true;
geometry.__dirtyMorphTargets = true;
geometry.__dirtyElements = true;
geometry.__dirtyUvs = true;
geometry.__dirtyNormals = true;
geometry.__dirtyTangents = true;
geometry.__dirtyColors = true;
geometry.__dirtyVertices = true;
geometry.__dirtyMorphTargets = true;
geometry.__dirtyElements = true;
geometry.__dirtyUvs = true;
geometry.__dirtyNormals = true;
geometry.__dirtyTangents = true;
geometry.__dirtyColors = true;
}
}
......@@ -3607,11 +3712,19 @@ THREE.WebGLRenderer = function ( parameters ) {
geometry = object.geometry;
for ( g in geometry.geometryGroups ) {
if ( geometry instanceof THREE.BufferGeometry ) {
addBuffer( scene.__webglObjects, geometry, object );
} else {
for ( g in geometry.geometryGroups ) {
geometryGroup = geometry.geometryGroups[ g ];
geometryGroup = geometry.geometryGroups[ g ];
addBuffer( scene.__webglObjects, geometryGroup, object );
addBuffer( scene.__webglObjects, geometryGroup, object );
}
}
......@@ -3676,35 +3789,56 @@ THREE.WebGLRenderer = function ( parameters ) {
if ( object instanceof THREE.Mesh ) {
// check all geometry groups
if ( geometry instanceof THREE.BufferGeometry ) {
if ( geometry.__dirtyVertices || geometry.__dirtyElements ||
geometry.__dirtyUvs || geometry.__dirtyNormals ||
geometry.__dirtyColors ) {
for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
// TODO
// set buffers from typed arrays
geometryGroup = geometry.geometryGroupsList[ i ];
}
material = getBufferMaterial( object, geometryGroup );
geometry.__dirtyVertices = false;
geometry.__dirtyElements = false;
geometry.__dirtyUvs = false;
geometry.__dirtyNormals = false;
geometry.__dirtyColors = false;
customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
} else {
if ( geometry.__dirtyVertices || geometry.__dirtyMorphTargets || geometry.__dirtyElements ||
geometry.__dirtyUvs || geometry.__dirtyNormals ||
geometry.__dirtyColors || geometry.__dirtyTangents || customAttributesDirty ) {
// check all geometry groups
setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic, material );
for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
geometryGroup = geometry.geometryGroupsList[ i ];
material = getBufferMaterial( object, geometryGroup );
customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
if ( geometry.__dirtyVertices || geometry.__dirtyMorphTargets || geometry.__dirtyElements ||
geometry.__dirtyUvs || geometry.__dirtyNormals ||
geometry.__dirtyColors || geometry.__dirtyTangents || customAttributesDirty ) {
setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic, material );
}
}
}
geometry.__dirtyVertices = false;
geometry.__dirtyMorphTargets = false;
geometry.__dirtyElements = false;
geometry.__dirtyUvs = false;
geometry.__dirtyNormals = false;
geometry.__dirtyColors = false;
geometry.__dirtyTangents = false;
geometry.__dirtyVertices = false;
geometry.__dirtyMorphTargets = false;
geometry.__dirtyElements = false;
geometry.__dirtyUvs = false;
geometry.__dirtyNormals = false;
geometry.__dirtyColors = false;
geometry.__dirtyTangents = false;
material.attributes && clearCustomAttributes( material );
material.attributes && clearCustomAttributes( material );
}
} else if ( object instanceof THREE.Ribbon ) {
......
......@@ -91,6 +91,7 @@ EXTRAS_FILES = [
'extras/ImageUtils.js',
'extras/SceneUtils.js',
'extras/ShaderUtils.js',
'extras/core/BufferGeometry.js',
'extras/core/Curve.js',
'extras/core/CurvePath.js',
'extras/core/Path.js',
......@@ -335,6 +336,7 @@ WEBGL_FILES = [
'renderers/WebGLRenderer.js',
'renderers/WebGLRenderTarget.js',
'renderers/WebGLRenderTargetCube.js',
'extras/core/BufferGeometry.js',
'extras/objects/LensFlare.js',
'extras/plugins/LensFlarePlugin.js',
'extras/plugins/ShadowMapPlugin.js',
......@@ -425,7 +427,7 @@ def buildLib(files, debug, minified, filename):
def buildIncludes(files, filename):
template = '\t\t<script type="text/javascript" src="../src/%s"></script>'
template = '\t\t<script src="../src/%s"></script>'
text = "\n".join(template % f for f in files)
output(text, filename + '.js')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册