八 动态添加物体(基于投射基础上)
if (isShiftDown) {
//例子用shift按下与否判断增加减少物体
if ( intersect.object != plane ) {
scene.remove(intersect.object);
//如果按下 投射的物体不是平面 删除物体
objects.splice( objects.indexOf( intersect.object ), 1 );
//貌似是删除后 将剩余物体连接起来..
}
} else {
normalMatrix.getNormalMatrix(intersect.object.matrixWorld);
//获取点击物体的 法矩阵?
var normal = intersect.face.normal.clone();
//获取点击物体的 法向量
normal.applyMatrix3( normalMatrix ).normalize();
//用法矩阵矩阵 单位化法向量? 数学不太好
var voxel = new THREE.Mesh( cubeGeometry, cubeMaterial );
voxel.position.addVectors( intersect.point, normal );
//新建物体 按照向量定位位置
voxel.position.divideScalar( 50 ).floor().multiplyScalar( 50 ).addScalar( 25 );
scene.add( voxel );
objects.push( voxel );
}
九 渐变色做法
var geometry3 = new THREE.Geometry(),
points = hilbert3D( new THREE.Vector3( 0,0,0 ), 200.0, 2, 0, 1, 2, 3, 4, 5, 6, 7 ),
//返回一系列的点
colors3 = [];
for ( i = 0; i < points.length; i ++ ) {
geometry3.vertices.push( points[ i ] );
//将点压进geometry
colors3[i] = new THREE.Color(0xffffff);
colors3[ i ].setHSL( i / points.length, 1.0, 0.5 );
//设置颜色数组的颜色 和 hsl
}
geometry3.colors = colors3;
//设置geometry的颜色数组是color3
十 各种material
参见canvas_materials.html..太多了
十一 用一个canvas浮动在three.js canvas上 标记物体和观察点的位置
meshdepthmaterial 貌似是通过距离决定物体的颜色,,不用添加灯光...
var material = new THREE.MeshDepthMaterial( { side: THREE.DoubleSide, overdraw: true } );
十二 倒影的做法
image = document.createElement( 'canvas' );
image.width = 480;
image.height = 204;
//视频canvas
imageContext = image.getContext( '2d' );
imageContext.fillStyle = '#000000';
imageContext.fillRect(0, 0, 480, 204);
texture = new THREE.Texture( image );
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
//视频纹理 (以canvas为参数)
var material = new THREE.MeshBasicMaterial({ map: texture, overdraw: true });
//视频纹理material
imageReflection = document.createElement( 'canvas' );
imageReflection.width = 480;
imageReflection.height = 204;
imageReflectionContext = imageReflection.getContext( '2d' );
imageReflectionContext.fillStyle = '#000000';
imageReflectionContext.fillRect(0, 0, 480, 204);
//倒影canvas
imageReflectionGradient = imageReflectionContext.createLinearGradient( 0, 0, 0, 204 );
imageReflectionGradient.addColorStop( 0.2, 'rgba(240, 240, 240, 1)' );
imageReflectionGradient.addColorStop(1, 'rgba(240, 240, 240, 0.8)');
//倒影canvas的fillstyle 调用倒影context.createLinearGradient
textureReflection = new THREE.Texture( imageReflection );
textureReflection.minFilter = THREE.LinearFilter;
textureReflection.magFilter = THREE.LinearFilter;
//倒影 纹理
var materialReflection = new THREE.MeshBasicMaterial( { map: textureReflection, side: THREE.BackSide, overdraw: true } );
//倒影material
var plane = new THREE.PlaneGeometry( 480, 204, 4, 4 );
mesh = new THREE.Mesh( plane, material );
mesh.scale.x = mesh.scale.y = mesh.scale.z = 1.5;
scene.add(mesh);
mesh = new THREE.Mesh( plane, materialReflection );
mesh.position.y = -306;
mesh.rotation.x = - Math.PI;
mesh.scale.x = mesh.scale.y = mesh.scale.z = 1.5;
scene.add( mesh );
注意:需要在render函数里面调用canvas.context.drawimage
if ( video.readyState === video.HAVE_ENOUGH_DATA ) {
imageContext.drawImage( video, 0, 0 );
if ( texture ) texture.needsUpdate = true;
if ( textureReflection ) textureReflection.needsUpdate = true;
}
//用以更新视频canvas 视频canvas context drawimage用video为参数
//video = document.getElementById( 'video' );
imageReflectionContext.drawImage( image, 0, 0 );
imageReflectionContext.fillStyle = imageReflectionGradient;
imageReflectionContext.fillRect(0, 0, 480, 204);
//倒影canvas content.drawimage用视频canvas做参数
//fillstyle为上面定义的渐变
十三 three.spritematerial
var material = new THREE.SpriteMaterial();
particle = new THREE.Sprite( material );
scene.add(particle);
//material 没有参数 但是生成的的particle是一个有宽度的点,用scale可以进行缩放
sparksEmitter = new SPARKS.Emitter(new SPARKS.SteadyCounter(160));
emitterpos = new THREE.Vector3();
sparksEmitter.addInitializer(new SPARKS.Position( new SPARKS.PointZone( emitterpos ) ) );
sparksEmitter.addInitializer(new SPARKS.Lifetime(0,2));
sparksEmitter.addInitializer(new SPARKS.Target(null, setTargetParticle));
sparksEmitter.addInitializer(new SPARKS.Velocity(new SPARKS.PointZone(new THREE.Vector3(0,-50,10))));
// TOTRY Set velocity to move away from centroid
sparksEmitter.addAction(new SPARKS.Age());
//貌似是定义了动画的生命周期,删除会出现大量的对象, 应该是默认了一个比较低的值
//sparksEmitter.addAction(new SPARKS.Accelerate(0.2));
sparksEmitter.addAction(new SPARKS.Move());
//貌似是控制动画对象的动作,删除不会对外扩散
sparksEmitter.addAction(new SPARKS.RandomDrift(50,50,2000));
//貌似是控制动画对象的某个轴运动 删除后例子中对象不会向摄像机方向扩散
sparksEmitter.addCallback("created", onParticleCreated);
//对象的创建函数
sparksEmitter.addCallback("dead", onParticleDead);
//对象的结束函数
sparksEmitter.start();
heartShape = new THREE.Shape();
heartShape.moveTo( x + 25, y + 25 );
heartShape.bezierCurveTo( x + 25, y + 25, x + 20, y, x, y );
heartShape.bezierCurveTo( x - 30, y, x - 30, y + 35,x - 30,y + 35 );
heartShape.bezierCurveTo( x - 30, y + 55, x - 10, y + 77, x + 25, y + 95 );
heartShape.bezierCurveTo( x + 60, y + 77, x + 80, y + 55, x + 80, y + 35 );
heartShape.bezierCurveTo( x + 80, y + 35, x + 80, y, x + 50, y );
heartShape.bezierCurveTo( x + 35, y, x + 25, y + 25, x + 25, y + 25 );
一个shape
var pointOnShape = heartShape.getPointAt( timeOnShapePath/*索引*/ );//获取点
emitterpos.x = pointOnShape.x * 5 - 100;
emitterpos.y = -pointOnShape.y * 5 + 400;//设置位置
render函数里面调用
十六 用tween来控制实体动画
//该函数是自己定义的 每次创建实体都将创建的实体传入函数 然后调用
function initParticle( particle, delay ) {
var particle = this instanceof THREE.Sprite ? this : particle;
var delay = delay !== undefined ? delay : 0;
particle.position.set( 0, 0, 0 )
particle.scale.x = particle.scale.y = Math.random() * 32 + 16;
new TWEEN.Tween( particle )
.delay( delay )
.to( {}, 10000 )
.onComplete( initParticle )
.start();
//设置动画结束后重新开始
new TWEEN.Tween( particle.position )
.delay( delay )
.to( { x: Math.random() * 4000 - 2000, y: Math.random() * 1000 - 500, z: Math.random() * 4000 - 2000 }, 10000 )
.start();
//设置物体的位置
new TWEEN.Tween( particle.scale )
.delay( delay )
.to( { x: 0, y: 0 }, 10000 )
.start();
//控制物体的缩放
//一个new tween 控制一种动画(位置 大小 也许一个tween也可以控制多种动画)要在render函数里调用 tween.update();
}
function generateSprite() {//调用spritematerial
var canvas = document.createElement( 'canvas' );
canvas.width = 16;
canvas.height = 16;
var context = canvas.getContext( '2d' );
var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 );
gradient.addColorStop( 0, 'rgba(255,255,255,1)' );
gradient.addColorStop( 0.2, 'rgba(0,255,255,1)' );
gradient.addColorStop( 0.4, 'rgba(0,0,64,1)' );
gradient.addColorStop( 1, 'rgba(0,0,0,1)' );
context.fillStyle = gradient;
context.fillRect( 0, 0, canvas.width, canvas.height );
return canvas;//返回canvas作为纹理
}
新建实体
for ( var ix = 0; ix < AMOUNTX; ix ++ ) {
for ( var iy = 0; iy < AMOUNTY; iy ++ ) {
particle = particles[ i ++ ] = new THREE.Sprite( material );//保存进数组
particle.position.x = ix * SEPARATION - ( ( AMOUNTX * SEPARATION ) / 2 );
particle.position.z = iy * SEPARATION - ( ( AMOUNTY * SEPARATION ) / 2 );
scene.add( particle );
}
}
render函数里调用
for ( var ix = 0; ix < AMOUNTX; ix ++ ) {
for ( var iy = 0; iy < AMOUNTY; iy ++ ) {
particle = particles[ i++ ];
particle.position.y = ( Math.sin( ( ix + count ) * 0.3 ) * 50 ) +
( Math.sin( ( iy + count ) * 0.5 ) * 50 );
particle.scale.x = particle.scale.y = ( Math.sin( ( ix + count ) * 0.3 ) + 1 ) * 4 +
( Math.sin( ( iy + count ) * 0.5 ) + 1 ) * 4;
}
} count += 0.1;
geometry = new THREE.IcosahedronGeometry( 100, 1 );//第一个参数是半径 第二个参数叫detial 貌似+1顶点数目就*2
material = new THREE.MeshBasicMaterial( { envMap: THREE.ImageUtils.loadTexture( 'textures/metal.jpg', new THREE.SphericalReflectionMapping() ), overdraw: true } );//之后mesh
包含 <script src="js/renderers/CSS3DRenderer.js"></script>
renderer = new THREE.CSS3DRenderer();
var side = sides[ i ];
var element = document.createElement( 'img' );
element.width = 1027; // 2 pixels extra to close the gap.
element.src = side.url;
var object = new THREE.CSS3DObject( element );//我有特殊的新建对象的方法
object.position.fromArray( side.position );//可以读取json数据设置位置 scale等等
object.rotation.fromArray( side.rotation );
scene.add( object );
通过设置html元素的css样式 添加成css3dobject 来控制html元素
二十一 trackballcontrol使用
<script src="js/controls/TrackballControls.js"></script>
controls = new THREE.TrackballControls( camera );//将camera传入当参数 控制摄像机(观察点)的移动
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = false;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
二十二 css3d sprite对象使用(css3drender 中的纹理使用方法吧 好像比较麻烦 )
var sprite = document.createElement('img');
//新建一个img对象
sprite.addEventListener( 'load', function ( event ) {
for ( var i = 0, j = 0; i < particlesTotal; i ++, j += 3 ) {
var canvas = document.createElement('canvas');
//新建canvas
canvas.width = sprite.width;
canvas.height = sprite.height;
var context = canvas.getContext( '2d' );
context.drawImage( sprite, 0, 0 );
//canvas用img元素来画图
var object = new THREE.CSS3DSprite(canvas);
//css3dsprite对象用canvas作为参数
object.position.x = Math.random() * 4000 - 2000,
object.position.y = Math.random() * 4000 - 2000,
object.position.z = Math.random() * 4000 - 2000
scene.add( object );
objects.push( object );
}
transition();
}, false );
sprite.src = 'textures/sprite.png';