提交 8cb2f9e2 编写于 作者: M Mr.doob

Merge remote branch 'alteredq/master'

<!DOCTYPE HTML>
<html lang="en">
<head>
<title>three.js - Large mesh test</title>
<meta charset="utf-8">
<style type="text/css">
body {
background:#000;
color:#fff;
padding:0;
margin:0;
overflow:hidden;
font-family:georgia;
text-align:center;
}
h1 { }
a { color:skyblue }
canvas { pointer-events:none; z-index:10; position:relative; }
#log { position:absolute; top:50px; text-align:left; display:block; z-index:100 }
#d { text-align:center; margin:1em 0 -18em 0; z-index:0; position:relative; display:block }
.button { background:orange; color:#fff; padding:0.2em 0.5em; cursor:pointer }
.inactive { background:#999; color:#eee }
</style>
</head>
<body>
<div id="d">
<h1>Large mesh test</h1>
<span id="rcanvas" class="button inactive">2d canvas renderer</span>
<span id="rwebgl" class="button">WebGL renderer</span>
<br/>
<p>Lucy model from <a href="http://graphics.stanford.edu/data/3Dscanrep/">Stanford 3d scanning repository</a>
(decimated with <a href="http://meshlab.sourceforge.net/">Meshlab</a>).
<p>Please be patient while the mesh is loading. It may take a while, it's 4.5MB file.
<p>Using a modified version of <a href="http://github.com/alteredq/three.js">Three.js</a> by mrdoob.
<br/>
<p>Best viewed in Chrome 8/9 or Firefox 4 using WebGL renderer.
<p>Canvas renderer is very slow for this demo and only diffuse material works there.
</div>
<pre id="log"></pre>
<script type="text/javascript" src="../build/Three.js"></script>
<!--
-->
<!--
<script type="text/javascript" src="../src/Three.js"></script>
<script type="text/javascript" src="../src/core/Color.js"></script>
<script type="text/javascript" src="../src/core/Vector2.js"></script>
<script type="text/javascript" src="../src/core/Vector3.js"></script>
<script type="text/javascript" src="../src/core/Vector4.js"></script>
<script type="text/javascript" src="../src/core/Rectangle.js"></script>
<script type="text/javascript" src="../src/core/Matrix3.js"></script>
<script type="text/javascript" src="../src/core/Matrix4.js"></script>
<script type="text/javascript" src="../src/core/Vertex.js"></script>
<script type="text/javascript" src="../src/core/Face3.js"></script>
<script type="text/javascript" src="../src/core/Face4.js"></script>
<script type="text/javascript" src="../src/core/UV.js"></script>
<script type="text/javascript" src="../src/core/Geometry.js"></script>
<script type="text/javascript" src="../src/cameras/Camera.js"></script>
<script type="text/javascript" src="../src/lights/Light.js"></script>
<script type="text/javascript" src="../src/lights/AmbientLight.js"></script>
<script type="text/javascript" src="../src/lights/DirectionalLight.js"></script>
<script type="text/javascript" src="../src/lights/PointLight.js"></script>
<script type="text/javascript" src="../src/objects/Object3D.js"></script>
<script type="text/javascript" src="../src/objects/Mesh.js"></script>
<script type="text/javascript" src="../src/objects/Particle.js"></script>
<script type="text/javascript" src="../src/objects/Line.js"></script>
<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshPhongMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshBitmapMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshColorStrokeMaterial.js"></script>
<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
<script type="text/javascript" src="../src/scenes/Scene.js"></script>
<script type="text/javascript" src="../src/renderers/Projector.js"></script>
<script type="text/javascript" src="../src/renderers/CanvasRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/SVGRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/WebGLRenderer.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableFace3.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableFace4.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
-->
<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
<script type="text/javascript" src="js/Stats.js"></script>
<script type="text/javascript">
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var FLOOR = -250;
var container;
var stats;
var camera;
var scene;
var canvasRenderer, webglRenderer;
var mesh, zmesh, lightMesh, geometry;
var directionalLight, pointLight;
var mouseX = 0;
var mouseY = 0;
var windowHalfX = window.innerWidth >> 1;
var windowHalfY = window.innerHeight >> 1;
var render_canvas = 1, render_gl = 1;
var has_gl = 0;
var bcanvas = document.getElementById("rcanvas");
var bwebgl = document.getElementById("rwebgl");
document.addEventListener('mousemove', onDocumentMouseMove, false);
init();
loop();
render_canvas = !has_gl;
bwebgl.style.display = has_gl ? "inline" : "none";
bcanvas.className = render_canvas ? "button" : "button inactive";
setInterval(loop, 1000/60);
function addMesh( geometry, scale, x, y, z, rx, ry, rz, material ) {
mesh = new THREE.Mesh( geometry, material );
mesh.scale.x = mesh.scale.y = mesh.scale.z = scale;
mesh.position.x = x;
mesh.position.y = y;
mesh.position.z = z;
mesh.rotation.x = rx;
mesh.rotation.y = ry;
mesh.rotation.z = rz;
mesh.overdraw = true;
mesh.updateMatrix();
scene.addObject(mesh);
}
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.Camera( 50, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 100000 );
camera.position.z = 1500;
camera.updateMatrix();
scene = new THREE.Scene();
// LIGHTS
var ambient = new THREE.AmbientLight( 0x101010 );
scene.addLight( ambient );
directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.x = 1;
directionalLight.position.y = 1;
directionalLight.position.z = 2;
directionalLight.position.normalize();
scene.addLight( directionalLight );
pointLight = new THREE.PointLight( 0xffaa00 );
pointLight.position.x = 0;
pointLight.position.y = 0;
pointLight.position.z = 0;
scene.addLight( pointLight );
// light representation
sphere = new Sphere( 100, 16, 8, 1 );
lightMesh = new THREE.Mesh( sphere, new THREE.MeshColorFillMaterial( 0xffaa00 ) );
lightMesh.scale.x = lightMesh.scale.y = lightMesh.scale.z = 0.05;
lightMesh.position = pointLight.position;
lightMesh.overdraw = true;
lightMesh.updateMatrix();
scene.addObject(lightMesh);
if ( render_gl ) {
try {
webglRenderer = new THREE.WebGLRenderer( scene );
webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
container.appendChild( webglRenderer.domElement );
has_gl = 1;
}
catch (e) {
}
}
if( render_canvas ) {
canvasRenderer = new THREE.CanvasRenderer();
canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
container.appendChild( canvasRenderer.domElement );
}
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
bcanvas.addEventListener("click", toggleCanvas, false);
bwebgl.addEventListener("click", toggleWebGL, false);
function createModel() {
geometry = new Lucy100k( );
addMesh( geometry, 0.75, 900, 0, 0, 0,0,0, new THREE.MeshPhongMaterial( 0x030303, 0x030303, 0x990000, 30, 1.0 ) );
addMesh( geometry, 0.75, 300, 0, 0, 0,0,0, new THREE.MeshFaceMaterial( ) );
addMesh( geometry, 0.75, -300, 0, 0, 0,0,0, new THREE.MeshPhongMaterial( 0x030303, 0x111111, 0xffaa00, 10, 1.0 ) );
addMesh( geometry, 0.75, -900, 0, 0, 0,0,0, new THREE.MeshPhongMaterial( 0x030303, 0x555555, 0x666666, 10, 1.0 ) );
/*
log( "geometry.vertices: " + geometry.vertices.length );
log( "geometry.faces: " + geometry.faces.length );
*/
}
loadAsync( "obj/lucy/Lucy100k.js", createModel );
}
function loadAsync( url, callback ) {
var el = document.createElement( 'script' );
el.type = 'text/javascript';
el.onload = callback;
el.src = url;
document.getElementsByTagName("head")[0].appendChild(el);
}
function onDocumentMouseMove(event) {
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY );
}
var r = 0;
function loop() {
camera.position.x += ( mouseX - camera.position.x ) * .05;
camera.position.y += ( - mouseY - camera.position.y ) * .05;
camera.updateMatrix();
lightMesh.position.x = 700*Math.cos(r);
lightMesh.position.z = 700*Math.sin(r);
lightMesh.updateMatrix();
r += 0.01;
if ( render_canvas ) canvasRenderer.render( scene, camera );
if ( render_gl && has_gl ) webglRenderer.render( scene, camera );
stats.update();
}
function log(text) {
var e = document.getElementById("log");
e.innerHTML = text + "<br/>" + e.innerHTML;
}
function toggleCanvas() {
render_canvas = !render_canvas;
bcanvas.className = render_canvas ? "button" : "button inactive";
render_gl = !render_canvas;
bwebgl.className = render_gl ? "button" : "button inactive";
if( has_gl )
webglRenderer.domElement.style.display = render_gl ? "block" : "none";
canvasRenderer.domElement.style.display = render_canvas ? "block" : "none";
}
function toggleWebGL() {
render_gl = !render_gl;
bwebgl.className = render_gl ? "button" : "button inactive";
render_canvas = !render_gl;
bcanvas.className = render_canvas ? "button" : "button inactive";
if( has_gl )
webglRenderer.domElement.style.display = render_gl ? "block" : "none";
canvasRenderer.domElement.style.display = render_canvas ? "block" : "none";
}
</script>
</body>
</html>
...@@ -39,10 +39,11 @@ ...@@ -39,10 +39,11 @@
<pre id="log"></pre> <pre id="log"></pre>
<!--
<script type="text/javascript" src="../build/Three.js"></script> <script type="text/javascript" src="../build/Three.js"></script>
<!--
--> -->
<!--
<script type="text/javascript" src="../src/Three.js"></script> <script type="text/javascript" src="../src/Three.js"></script>
<script type="text/javascript" src="../src/core/Color.js"></script> <script type="text/javascript" src="../src/core/Color.js"></script>
<script type="text/javascript" src="../src/core/Vector2.js"></script> <script type="text/javascript" src="../src/core/Vector2.js"></script>
...@@ -82,7 +83,6 @@ ...@@ -82,7 +83,6 @@
<script type="text/javascript" src="../src/renderers/renderables/RenderableFace4.js"></script> <script type="text/javascript" src="../src/renderers/renderables/RenderableFace4.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script> <script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script> <script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
<!--
--> -->
<script type="text/javascript" src="geometry/primitives/Sphere.js"></script> <script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
......
<Files *.js>
SetOutputFilter DEFLATE
</Files>
此差异已折叠。
...@@ -179,7 +179,6 @@ ...@@ -179,7 +179,6 @@
mesh.position.z = 0; mesh.position.z = 0;
mesh.rotation.x = 1.57; mesh.rotation.x = 1.57;
mesh.scale.x = mesh.scale.y = mesh.scale.z = 10; mesh.scale.x = mesh.scale.y = mesh.scale.z = 10;
mesh.doubleSided = true;
mesh.updateMatrix(); mesh.updateMatrix();
scene.addObject(mesh); scene.addObject(mesh);
...@@ -192,7 +191,6 @@ ...@@ -192,7 +191,6 @@
mesh.position.y = 300 * (Math.random() - 0) + FLOOR; mesh.position.y = 300 * (Math.random() - 0) + FLOOR;
mesh.position.z = 100 * (Math.random() - 1); mesh.position.z = 100 * (Math.random() - 1);
mesh.scale.x = mesh.scale.y = mesh.scale.z = 0.25 * (Math.random() + 0.5); mesh.scale.x = mesh.scale.y = mesh.scale.z = 0.25 * (Math.random() + 0.5);
//mesh.doubleSided = true;
mesh.overdraw = true; mesh.overdraw = true;
mesh.updateMatrix(); mesh.updateMatrix();
scene.addObject(mesh); scene.addObject(mesh);
...@@ -217,6 +215,7 @@ ...@@ -217,6 +215,7 @@
if ( render_gl ) { if ( render_gl ) {
try { try {
webglRenderer = new THREE.WebGLRenderer(); webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setFaceCulling(0);
webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
container.appendChild( webglRenderer.domElement ); container.appendChild( webglRenderer.domElement );
has_gl = 1; has_gl = 1;
......
...@@ -41,10 +41,11 @@ ...@@ -41,10 +41,11 @@
<pre id="log"></pre> <pre id="log"></pre>
<!--
<script type="text/javascript" src="../build/Three.js"></script> <script type="text/javascript" src="../build/Three.js"></script>
<!--
--> -->
<!--
<script type="text/javascript" src="../src/Three.js"></script> <script type="text/javascript" src="../src/Three.js"></script>
<script type="text/javascript" src="../src/core/Color.js"></script> <script type="text/javascript" src="../src/core/Color.js"></script>
<script type="text/javascript" src="../src/core/Vector2.js"></script> <script type="text/javascript" src="../src/core/Vector2.js"></script>
...@@ -84,7 +85,6 @@ ...@@ -84,7 +85,6 @@
<script type="text/javascript" src="../src/renderers/renderables/RenderableFace4.js"></script> <script type="text/javascript" src="../src/renderers/renderables/RenderableFace4.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script> <script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script> <script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
<!--
--> -->
<script type="text/javascript" src="geometry/primitives/Sphere.js"></script> <script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
......
...@@ -32,11 +32,11 @@ THREE.Mesh.prototype.sortFacesByMaterial = function () { ...@@ -32,11 +32,11 @@ THREE.Mesh.prototype.sortFacesByMaterial = function () {
// which could then use vertex color attributes instead of each being // which could then use vertex color attributes instead of each being
// in its separate VBO // in its separate VBO
var i, l, f, fl, face, material, hash_array; var i, l, f, fl, face, material, vertices, mhash, ghash, hash_map = {};
function materialHash( material ) { function materialHash( material ) {
hash_array = []; var hash_array = [];
for ( i = 0, l = material.length; i < l; i++ ) { for ( i = 0, l = material.length; i < l; i++ ) {
...@@ -61,19 +61,43 @@ THREE.Mesh.prototype.sortFacesByMaterial = function () { ...@@ -61,19 +61,43 @@ THREE.Mesh.prototype.sortFacesByMaterial = function () {
face = this.geometry.faces[ f ]; face = this.geometry.faces[ f ];
material = face.material; material = face.material;
hash = materialHash( material); mhash = materialHash( material );
if ( this.materialFaceGroup[ hash ] == undefined ) { if ( hash_map[ mhash ] == undefined ) {
this.materialFaceGroup[ hash ] = { 'faces': [], 'material': material }; hash_map[ mhash ] = { 'hash': mhash, 'counter': 0 };
}
ghash = hash_map[ mhash ].hash + "_" + hash_map[ mhash ].counter;
if ( this.materialFaceGroup[ ghash ] == undefined ) {
this.materialFaceGroup[ ghash ] = { 'faces': [], 'material': material, 'vertices': 0 };
}
vertices = face instanceof THREE.Face3 ? 3 : 4;
if ( this.materialFaceGroup[ ghash ].vertices + vertices > 65535 ) {
hash_map[ mhash ].counter += 1;
ghash = hash_map[ mhash ].hash + "_" + hash_map[ mhash ].counter;
if ( this.materialFaceGroup[ ghash ] == undefined ) {
this.materialFaceGroup[ ghash ] = { 'faces': [], 'material': material, 'vertices': 0 };
}
} }
this.materialFaceGroup[ hash ].faces.push( f ); this.materialFaceGroup[ ghash ].faces.push( f );
this.materialFaceGroup[ ghash ].vertices += vertices;
} }
} };
THREE.Mesh.prototype.normalizeUVs = function () { THREE.Mesh.prototype.normalizeUVs = function () {
...@@ -95,4 +119,4 @@ THREE.Mesh.prototype.normalizeUVs = function () { ...@@ -95,4 +119,4 @@ THREE.Mesh.prototype.normalizeUVs = function () {
} }
} };
...@@ -4,9 +4,11 @@ ...@@ -4,9 +4,11 @@
How to use this converter How to use this converter
------------------------- -------------------------
python convert_obj_threejs.py -i filename.obj -o filename.js [-a center|top|bottom] python convert_obj_threejs.py -i filename.obj -o filename.js [-a center|top|bottom] [-s smooth|flat]
Note: by default, model is centered (middle of bounding box goes to 0,0,0). Note: by default, model is centered (middle of bounding box goes to 0,0,0)
and uses smooth shading (if there were vertex normals in the original
model).
-------------------------------------------------- --------------------------------------------------
How to use generated JS file in your HTML document How to use generated JS file in your HTML document
...@@ -41,19 +43,16 @@ Current limitations ...@@ -41,19 +43,16 @@ Current limitations
- for the moment, only diffuse color and texture are used - for the moment, only diffuse color and texture are used
(will need to extend shaders / renderers / materials in Three) (will need to extend shaders / renderers / materials in Three)
- models cannot have more than 65,536 vertices - models can have more than 65,536 vertices,
(this comes from WebGL using just 16-bit indices, but in most cases it will not work well with browsers,
could be worked around by expanding indexed which currently seem to have troubles with handling
faces into full vertex definitions) large JS files
- texture coordinates can be wrong in canvas renderer - texture coordinates can be wrong in canvas renderer
(there is crude normalization, but it doesn't (there is crude normalization, but it doesn't
work for all cases) work for all cases)
- everything is using smoothing - smoothing can be turned on/off only for the whole mesh
(if you want flat shading for whole mesh,
don't export normals, then Three will
compute own normals)
---------------------------------------------- ----------------------------------------------
How to get proper OBJ + MTL files with Blender How to get proper OBJ + MTL files with Blender
...@@ -113,6 +112,8 @@ import sys ...@@ -113,6 +112,8 @@ import sys
# ##################################################### # #####################################################
ALIGN = "center" # center bottom top none ALIGN = "center" # center bottom top none
SHADING = "smooth" # flat smooth
# default colors for debugging (each material gets one distinct color): # default colors for debugging (each material gets one distinct color):
# white, red, green, blue, yellow, cyan, magenta # white, red, green, blue, yellow, cyan, magenta
COLORS = [0xffeeeeee, 0xffee0000, 0xff00ee00, 0xff0000ee, 0xffeeee00, 0xff00eeee, 0xffee00ee] COLORS = [0xffeeeeee, 0xffee0000, 0xff00ee00, 0xff0000ee, 0xffeeee00, 0xff00eeee, 0xffee00ee]
...@@ -651,7 +652,7 @@ def generate_uv(f, uvs): ...@@ -651,7 +652,7 @@ def generate_uv(f, uvs):
def generate_face(f): def generate_face(f):
vi = f['vertex'] vi = f['vertex']
if f["normal"]: if f["normal"] and SHADING == "smooth":
ni = f['normal'] ni = f['normal']
if len(vi) == 3: if len(vi) == 3:
return TEMPLATE_FACE3N % (vi[0]-1, vi[1]-1, vi[2]-1, f['material'], ni[0]-1, ni[1]-1, ni[2]-1) return TEMPLATE_FACE3N % (vi[0]-1, vi[1]-1, vi[2]-1, f['material'], ni[0]-1, ni[1]-1, ni[2]-1)
...@@ -756,8 +757,10 @@ def convert(infile, outfile): ...@@ -756,8 +757,10 @@ def convert(infile, outfile):
# default materials with debug colors for when # default materials with debug colors for when
# there is no specified MTL, if loading failed # there is no specified MTL / MTL loading failed,
# or there were null materials # or if there were no materials / null materials
if not materials:
materials = { 'default':0 }
mtl = generate_mtl(materials) mtl = generate_mtl(materials)
if mtllib: if mtllib:
...@@ -773,12 +776,16 @@ def convert(infile, outfile): ...@@ -773,12 +776,16 @@ def convert(infile, outfile):
else: else:
print "Couldn't find [%s]" % fname print "Couldn't find [%s]" % fname
normals_string = ""
if SHADING == "smooth":
normals_string = ",".join(generate_normal(n) for n in normals)
text = TEMPLATE_FILE % { text = TEMPLATE_FILE % {
"name" : get_name(outfile), "name" : get_name(outfile),
"vertices" : "\n".join([generate_vertex(v) for v in vertices]), "vertices" : "\n".join([generate_vertex(v) for v in vertices]),
"faces" : "\n".join([generate_face(f) for f in faces]), "faces" : "\n".join([generate_face(f) for f in faces]),
"uvs" : uv_string, "uvs" : uv_string,
"normals" : ",".join(generate_normal(n) for n in normals), "normals" : normals_string,
"materials" : generate_materials(mtl, materials), "materials" : generate_materials(mtl, materials),
...@@ -798,7 +805,7 @@ def convert(infile, outfile): ...@@ -798,7 +805,7 @@ def convert(infile, outfile):
# Helpers # Helpers
# ############################################################################# # #############################################################################
def usage(): def usage():
print "Usage: %s -i filename.obj -o filename.js [-a center|top|bottom]" % os.path.basename(sys.argv[0]) print "Usage: %s -i filename.obj -o filename.js [-a center|top|bottom] [-s flat|smooth]" % os.path.basename(sys.argv[0])
# ##################################################### # #####################################################
# Main # Main
...@@ -807,7 +814,7 @@ if __name__ == "__main__": ...@@ -807,7 +814,7 @@ if __name__ == "__main__":
# get parameters from the command line # get parameters from the command line
try: try:
opts, args = getopt.getopt(sys.argv[1:], "hi:o:a:", ["help", "input=", "output=", "align="]) opts, args = getopt.getopt(sys.argv[1:], "hi:o:a:s:", ["help", "input=", "output=", "align=", "shading="])
except getopt.GetoptError: except getopt.GetoptError:
usage() usage()
...@@ -830,6 +837,10 @@ if __name__ == "__main__": ...@@ -830,6 +837,10 @@ if __name__ == "__main__":
if a in ("top", "bottom", "center"): if a in ("top", "bottom", "center"):
ALIGN = a ALIGN = a
elif o in ("-s", "--shading"):
if a in ("flat", "smooth"):
SHADING = a
if infile == "" or outfile == "": if infile == "" or outfile == "":
usage() usage()
sys.exit(2) sys.exit(2)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册