mirror of
https://github.com/wahyd4/three.js.git
synced 2026-08-11 22:16:05 +10:00
If you want to refresh VBOs (and thus have geometry changes reflected in renderer), you need to set dirty flags on geometry object.
There are separate flags for different buffers (as not always all buffers need to be updated and oh my is updating costly):
mesh.geometry.__dirtyVertices = true;
mesh.geometry.__dirtyNormals = true;
mesh.geometry.__dirtyUvs = true;
mesh.geometry.__dirtyTangents = true;
mesh.geometry.__dirtyElements = true;
That was quite tough feature, a lot of refactoring, yet performance is still quite bad :(
The biggest remaining bottleneck seems to be translation between Three.js internal data formats and buffers. I removed as much per-frame arrays creation as I could, but even just iterating through existing data and setting of values is still very costly. Also per-frame normals computation is expensive.
300 lines
7.1 KiB
HTML
300 lines
7.1 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="en">
|
|
<head>
|
|
<title>three.js - geometry - dynamic - webgl</title>
|
|
<meta charset="utf-8">
|
|
<style type="text/css">
|
|
body {
|
|
color: #61443e;
|
|
font-family:Monospace;
|
|
font-size:13px;
|
|
text-align:center;
|
|
|
|
background-color: #aaccff;
|
|
margin: 0px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
#info {
|
|
color: #ffffff;
|
|
position: absolute;
|
|
top: 0px; width: 100%;
|
|
padding: 5px;
|
|
}
|
|
|
|
a {
|
|
|
|
color: yellow;
|
|
}
|
|
|
|
#oldie {
|
|
font-family:monospace;
|
|
font-size:13px;
|
|
|
|
text-align:center;
|
|
background:rgb(0,0,50);
|
|
color:#fff;
|
|
padding:1em;
|
|
|
|
width:475px;
|
|
margin:5em auto 0;
|
|
|
|
display:none;
|
|
}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div id="container"><br /><br /><br /><br /><br />Generating world...</div>
|
|
<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - dynamic geometry demo - webgl<br />(left click: forward, right click: backward)</div>
|
|
|
|
<center>
|
|
<div id="oldie">
|
|
Sorry, your browser doesn't support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation">WebGL</a>.<br/>
|
|
<br/>
|
|
Please try in
|
|
<a href="http://www.chromium.org/getting-involved/dev-channel">Chrome 9+</a> /
|
|
<a href="http://www.mozilla.com/en-US/firefox/all-beta.html">Firefox 4+</a> /
|
|
<a href="http://nightly.webkit.org/">Safari OSX 10.6+</a>
|
|
</div>
|
|
</center>
|
|
|
|
<script type="text/javascript" src="../build/ThreeExtras.js"></script>
|
|
<script type="text/javascript" src="js/Stats.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
|
|
if ( !is_browser_compatible() ) {
|
|
|
|
document.getElementById( "oldie" ).style.display = "block";
|
|
|
|
}
|
|
|
|
var container, stats;
|
|
|
|
var camera, scene, renderer;
|
|
|
|
var mesh, texture,geometry, material;
|
|
|
|
var worldWidth = 128, worldDepth = 128,
|
|
worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2;
|
|
|
|
var mouseX = 0, mouseY = 0,
|
|
lat = 0, lon = 0, phy = 0, theta = 0;
|
|
|
|
var direction = new THREE.Vector3(),
|
|
moveForward = false, moveBackward = false, moveLeft = false, moveRight = false;
|
|
|
|
var windowHalfX = window.innerWidth / 2;
|
|
var windowHalfY = window.innerHeight / 2;
|
|
|
|
|
|
init();
|
|
setInterval( loop, 1000 / 60 );
|
|
|
|
|
|
function init() {
|
|
|
|
container = document.getElementById( 'container' );
|
|
|
|
camera = new THREE.Camera( 60, window.innerWidth / window.innerHeight, 1, 20000 );
|
|
camera.target.position.z = - 100;
|
|
|
|
scene = new THREE.Scene();
|
|
scene.fog = new THREE.FogExp2( 0xaaccff, 0.0007 );
|
|
|
|
//var light = new THREE.PointLight( 0xffffff, 2 );
|
|
//light.position.y = 500;
|
|
//scene.addLight( light );
|
|
|
|
camera.position.y = 200;
|
|
camera.target.position.y = camera.position.y;
|
|
|
|
geometry = new Plane( 20000, 20000, worldWidth - 1, worldDepth - 1 );
|
|
|
|
var i, j, il, jl;
|
|
|
|
for ( i = 0, il = geometry.vertices.length; i < il; i ++ ) {
|
|
|
|
geometry.vertices[ i ].position.z = 35 * Math.sin( i/2 );
|
|
|
|
}
|
|
|
|
for( i = 0; i < geometry.uvs.length; i++ ) {
|
|
|
|
var uvs = geometry.uvs[ i ];
|
|
for ( j = 0, jl = uvs.length; j < jl; j++ ) {
|
|
|
|
uvs[ j ].u *= 5;
|
|
uvs[ j ].v *= 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//console.log( "triangles: " + geometry.faces.length * 2 + " faces: " + geometry.faces.length + " vertices: " + geometry.vertices.length );
|
|
|
|
geometry.computeFaceNormals();
|
|
geometry.computeVertexNormals();
|
|
|
|
var texture = ImageUtils.loadTexture( "textures/water.jpg" );
|
|
texture.wrap_s = texture.wrap_t = THREE.RepeatWrapping;
|
|
material = new THREE.MeshBasicMaterial( { color:0x0044ff, opacity:1, map: texture } );
|
|
|
|
mesh = new THREE.Mesh( geometry, material );
|
|
mesh.rotation.x = - 90 * Math.PI / 180;
|
|
scene.addObject( mesh );
|
|
|
|
renderer = new THREE.WebGLRenderer( { clearColor:0xaaccff, clearAlpha: 1 } );
|
|
renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
|
container.innerHTML = "";
|
|
|
|
container.appendChild( renderer.domElement );
|
|
|
|
stats = new Stats();
|
|
stats.domElement.style.position = 'absolute';
|
|
stats.domElement.style.top = '0px';
|
|
container.appendChild( stats.domElement );
|
|
|
|
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
|
|
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
|
|
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
|
|
document.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
|
|
|
|
document.addEventListener( 'keydown', onDocumentKeyDown, false );
|
|
document.addEventListener( 'keyup', onDocumentKeyUp, false );
|
|
|
|
}
|
|
|
|
|
|
function onDocumentMouseDown( event ) {
|
|
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
switch ( event.button ) {
|
|
|
|
case 0: moveForward = true; break;
|
|
case 2: moveBackward = true; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function onDocumentMouseUp( event ) {
|
|
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
switch ( event.button ) {
|
|
|
|
case 0: moveForward = false; break;
|
|
case 2: moveBackward = false; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function onDocumentMouseMove(event) {
|
|
|
|
mouseX = event.clientX - windowHalfX;
|
|
mouseY = event.clientY - windowHalfY;
|
|
|
|
}
|
|
|
|
function onDocumentKeyDown( event ) {
|
|
|
|
switch( event.keyCode ) {
|
|
|
|
case 38: /*up*/
|
|
case 87: /*W*/ moveForward = true; break;
|
|
|
|
case 37: /*left*/
|
|
case 65: /*A*/ moveLeft = true; break;
|
|
|
|
case 40: /*down*/
|
|
case 83: /*S*/ moveBackward = true; break;
|
|
|
|
case 39: /*right*/
|
|
case 68: /*D*/ moveRight = true; break;
|
|
}
|
|
|
|
}
|
|
|
|
function onDocumentKeyUp( event ) {
|
|
|
|
switch( event.keyCode ) {
|
|
|
|
case 38: /*up*/
|
|
case 87: /*W*/ moveForward = false; break;
|
|
|
|
case 37: /*left*/
|
|
case 65: /*A*/ moveLeft = false; break;
|
|
|
|
case 40: /*down*/
|
|
case 83: /*S*/ moveBackward = false; break;
|
|
|
|
case 39: /*right*/
|
|
case 68: /*D*/ moveRight = false; break;
|
|
}
|
|
|
|
}
|
|
|
|
function loop() {
|
|
|
|
var time = new Date().getTime() * 0.01;
|
|
|
|
if ( moveForward ) camera.translateZ( - 10 );
|
|
if ( moveBackward ) camera.translateZ( 10 );
|
|
if ( moveLeft ) camera.translateX( - 10 );
|
|
if ( moveRight ) camera.translateX( 10 );
|
|
|
|
lon += mouseX * 0.004;
|
|
lat -= mouseY * 0.004;
|
|
|
|
lat = Math.max( - 85, Math.min( 85, lat ) );
|
|
phi = ( 90 - lat ) * Math.PI / 180;
|
|
theta = lon * Math.PI / 180;
|
|
|
|
camera.target.position.x = 100 * Math.sin( phi ) * Math.cos( theta ) + camera.position.x;
|
|
camera.target.position.y = 100 * Math.cos( phi ) + camera.position.y;
|
|
camera.target.position.z = 100 * Math.sin( phi ) * Math.sin( theta ) + camera.position.z;
|
|
|
|
|
|
for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
|
|
|
|
geometry.vertices[ i ].position.z = 35 * Math.sin( i/5 + (time + i)/7 );
|
|
|
|
}
|
|
|
|
//geometry.computeFaceNormals();
|
|
//geometry.computeVertexNormals();
|
|
|
|
mesh.geometry.__dirtyVertices = true;
|
|
//mesh.geometry.__dirtyNormals = true;
|
|
|
|
renderer.render(scene, camera);
|
|
|
|
stats.update();
|
|
|
|
}
|
|
|
|
function is_browser_compatible() {
|
|
|
|
// WebGL support
|
|
|
|
try { var test = new Float32Array(1); } catch(e) { return false; }
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|