THREE.js 第三部分 canvas_geometry_birds.html
2017-10-20 14:56
387 查看
涉及到模拟鸟类飞行的状态,首先需要模拟鸟类的形态,代码如下:
var Bird = function () {
var scope = this;
THREE.Geometry.call(this);
v(5, 0, 0);
v(-5, -2, 1);
v(-5, 0, 0);
v(-5, -2, -1);
v(0, 2, -6);
v(0, 2, 6);
v(2, 0, 0);
v(-3, 0, 0);
f3(0, 2, 1);
f3(4, 7, 6);
f3(5, 6, 7);
this.computeFaceNormals();
function v(x, y, z) {
scope.vertices.push(new THREE.Vector3(x, y, z));
}
function f3(a, b, c) {
scope.faces.push(new THREE.Face3(a, b, c));
}
}
Bird.prototype = Object.create(THREE.Geometry.prototype);
Bird.prototype.constructor = Bird;
模拟出鸟类的样式。
同样需要模拟动态的鸟类飞行的状态,代码如下:
var Boid = function () {
var vector = new THREE.Vector3();
//加速
var _acceleration;
//宽度
var _width = 500;
//高度
var _height = 500;
//深度
var _depth = 200;
var _goal;
//相邻之间的距离
var _neighborhoodRedius = 100;
//最大速度
var _maxSpeed = 4;
var _maxSteerForce = 0.1;
//场景中是否有障碍
var _avoidWalls = false;
//位置
this.position = new THREE.Vector3();
//速率
this.velocity = new THREE.Vector3();
//加速
_acceleration = new THREE.Vector3();
//属性赋值
this.setGoal = function (target) {
_goal = target;
};
this.setAvoidWalls = function (value) {
_avoidWalls = value;
};
this.setWorldSize = function (width, height, depth) {
_width = width;
_height = height;
_depth = depth;
};
//运行
this.run = function (boids) {
if (_avoidWalls) {
vector.set(-_width, this.position.y, this.position.z);
vector = this.avoid(vector);
//vector中的xyz矩阵相乘倍数5 x=1 y=1 z=1 结果之后是 x=5 y=5 z=5
vector.multiplyScalar(5);
_acceleration.add(vector);
vector.set(_width, this.position.y, this.position.z);
vector = this.avoid(vector);
vector.multiplyScalar(5);
_acceleration.add(vector);
vector.set(this.position.x, -_height, this.position.z);
vector = this.avoid(vector);
vector.multiplyScalar(5);
_acceleration.add(vector);
vector.set(this.position.x, _height, this.position.z);
vector = this.avoid(vector);
vector.multiplyScalar(5);
_acceleration.add(vector);
vector.set(this.position.x, this.position.y, -_depth);
vector = this.avoid(vector);
vector.multiplyScalar(5);
_acceleration.add(vector);
vector.set(this.position.x, this.position.y, _depth);
vector = this.avoid(vector);
vector.multiplyScalar(5);
_acceleration.add(vector);
} else {
this.checkBounds();
}
if (Math.random() > 0.5) {
this.flock(boids);
}
this.move();
};
this.flock = function (boids) {
if (_goal) {
_acceleration.add(this.reach(_goal, 0.005));
}
_acceleration.add(this.alignment(boids));
_acceleration.add(this.cohesion(boids));
_acceleration.add(this.separation(boids));
};
this.move = function () {
this.velocity.add(_acceleration);
var l = this.velocity.length();
if (l > _maxSpeed) {
this.velocity.divideScalar(l / _maxSpeed);
}
this.position.add(this.velocity);
_acceleration.set(0, 0, 0);
};
//检测边框
this.checkBounds = function () {
if (this.position.x > _width)
this.position.x = -_width;
if (this.position.x < -_width)
this.position.x = _width;
if (this.position.y > _height)
this.position.y = -_height;
if (this.position.y < -_height)
this.position.y = _height;
if (this.position.z > _depth)
this.position.z = -_depth;
if (this.position.z < -_depth)
this.position.z = _depth;
};
this.avoid = function (target) {
var steer = new THREE.Vector3();
//拷贝xyz矩阵
steer.copy(this.position);
//返回vector3() this.position.x - target.x this.position.y - target.y this.position.z - target.z
steer.sub(target);
//矩阵缩放 矩阵差的平方和 x^2 + y^2 + z^2
steer.multiplyScalar(1 / this.position.distanceToSquared(target));
return steer;
};
this.repulse = function (target) {
//矩阵差的平方和的平方根
var distance = this.position.distanceTo(target);
if (distance < 150) {
var steer = new THREE.Vector3();
//返回vector3() a.x - b.x a.y - b.y a.z - b.z 两个矩阵相减
steer.subVectors(this.position, target);
steer.multiplyScalar(0,5 / distance);
_acceleration.add(steer);
}
};
this.reach = function (target, amount) {
var steer = new THREE.Vector3();
steer.subVectors(target, this.position);
steer.multiplyScalar(amount);
return steer;
};
this.alignment = function (boids) {
var count = 0;
var velSum = new THREE.Vector3();
for (var i = 0, il = boids.length; i < il; i++) {
if (Math.random() > 0.6)
continue;
var boid = boids[i];
var distance = boid.position.distanceTo(this.position);
if (distance > 0 && distance <= _neighborhoodRedius) {
velSum.add(boid.velocity);
count++;
}
}
if (count > 0) {
//this.multiplyScalar(1 / count)
velSum.divideScalar(count);
var l = velSum.length();
if (l > _maxSteerForce) {
velSum.divideScalar(l / _maxSteerForce);
}
}
return velSum;
};
this.cohesion = function (boids) {
var count = 0;
var posSum = new THREE.Vector3();
var steer = new THREE.Vector3();
for (var i = 0, il = boids.length; i < il; i++) {
if (Math.random() > 0.6)
continue;
var boid = boids[i];
var distance = boid.position.distanceTo(this.position);
if (distance > 0 && distance <= _neighborhoodRedius) {
posSum.add(boid.position);
count++;
}
}
if (count > 0) {
posSum.divideScalar(count);
}
steer.subVectors(posSum, this.position);
var l = steer.length();
if (l > _maxSteerForce) {
steer.divideScalar(l / _maxSteerForce);
}
return steer;
};
this.separation = function (boids) {
var posSum = new THREE.Vector3();
var repulse = new THREE.Vector3();
for (var i = 0, il = boids.length; i < il; i++) {
if (Math.random() > 0.6)
continue;
var boid = boids[i];
var distance = boid.position.distanceTo(this.position);
if (distance > 0 && distance <= _neighborhoodRedius) {
repulse.subVectors(this.position, boid.position);
repulse.normalize();
repulse.divideScalar(distance);
posSum.add(repulse);
}
}
return posSum;
};
}
下面就是代码正文部分,涉及到初始化,动态效果,场景,渲染。
var stats;
var container;
var camera;
var scene;
var renderer;
var bird;
var birds;
var boid;
var boids;
init();
animate();
function init() {
var width = window.innerWidth || 0;
var height = window.innerHeight || 0;
container = document.createElement('div');
document.body.appendChild(container);
var info = document.createElement('div');
info.style.position = 'absolute';
info.style.top = '0px';
info.style.width = '100%';
info.style.padding = '5px';
container.appendChild(info);
//镜头设置
var aspect = width / height;
camera = new THREE.PerspectiveCamera(75, aspect, 1, 10000);
camera.position.z = 450;
//场景
scene = new THREE.Scene();
scene.background = ne
9979
w THREE.Color(0xffffff);
birds = [];
boids = [];
for (var i = 0; i < 100; i++) {
boid = boids[i] = new Boid();
boid.position.x = Math.random() * 400 - 200;
boid.position.y = Math.random() * 400 - 200;
boid.position.z = Math.random() * 400 - 200;
boid.velocity.x = Math.random() * 2 - 1;
boid.velocity.y = Math.random() * 2 - 1;
boid.velocity.z = Math.random() * 2 - 1;
boid.setAvoidWalls(true);
boid.setWorldSize(500, 500, 400);
bird = birds[i] = new THREE.Mesh(new Bird(), new THREE.MeshBasicMaterial({color : Math.random() * 0xffffff, side : THREE.DoubleSide}));
bird.phase = Math.floor(Math.random() * 62.83);
scene.add(bird);
}
renderer = new THREE.CanvasRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
document.addEventListener('mousemove', OnDocumentMouseMove, false);
document.body.appendChild(renderer.domElement);
//监控
stats = new Stats();
container.appendChild(stats.dom);
window.addEventListener('resize', onWindowResize, false);
}
//窗口缩放event
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//鼠标移动event
function OnDocumentMouseMove(event) {
var vector = new THREE.Vector3(event.clientX - window.innerWidth / 2, - event.clientY + window.innerHeight / 2, 0);
for (var i = 0, il = boids.length; i < il; i++) {
boid = boids[i];
vector.z = boid.position.z;
boid.repulse(vector);
}
}
function animate() {
//固定格式
requestAnimationFrame(animate);
//监控开始
stats.begin();
//渲染
render();
//监控结束
stats.end();
}
function render() {
for (var i = 0, il = birds.length; i < il; i++) {
boid = boids[i];
boid.run(boids);
bird = birds[i];
bird.position.copy(boids[i].position);
var color = bird.material.color;
color.r = color.g = color.b = (500 - bird.position.z) / 1000;
bird.rotation.y = Math.atan2(-boid.velocity.z, boid.velocity.x);
bird.rotation.z = Math.asin(boid.velocity.y / boid.velocity.length());
bird.phase = (bird.phase + (Math.max(0, bird.rotation.z) + 0.1)) % 62.83;
bird.geometry.vertices[5].y = bird.geometry.vertices[4].y = Math.sin(bird.phase) * 5;
}
renderer.render(scene, camera);
}
之后要涉及到airbus官网的效果。
var Bird = function () {
var scope = this;
THREE.Geometry.call(this);
v(5, 0, 0);
v(-5, -2, 1);
v(-5, 0, 0);
v(-5, -2, -1);
v(0, 2, -6);
v(0, 2, 6);
v(2, 0, 0);
v(-3, 0, 0);
f3(0, 2, 1);
f3(4, 7, 6);
f3(5, 6, 7);
this.computeFaceNormals();
function v(x, y, z) {
scope.vertices.push(new THREE.Vector3(x, y, z));
}
function f3(a, b, c) {
scope.faces.push(new THREE.Face3(a, b, c));
}
}
Bird.prototype = Object.create(THREE.Geometry.prototype);
Bird.prototype.constructor = Bird;
模拟出鸟类的样式。
同样需要模拟动态的鸟类飞行的状态,代码如下:
var Boid = function () {
var vector = new THREE.Vector3();
//加速
var _acceleration;
//宽度
var _width = 500;
//高度
var _height = 500;
//深度
var _depth = 200;
var _goal;
//相邻之间的距离
var _neighborhoodRedius = 100;
//最大速度
var _maxSpeed = 4;
var _maxSteerForce = 0.1;
//场景中是否有障碍
var _avoidWalls = false;
//位置
this.position = new THREE.Vector3();
//速率
this.velocity = new THREE.Vector3();
//加速
_acceleration = new THREE.Vector3();
//属性赋值
this.setGoal = function (target) {
_goal = target;
};
this.setAvoidWalls = function (value) {
_avoidWalls = value;
};
this.setWorldSize = function (width, height, depth) {
_width = width;
_height = height;
_depth = depth;
};
//运行
this.run = function (boids) {
if (_avoidWalls) {
vector.set(-_width, this.position.y, this.position.z);
vector = this.avoid(vector);
//vector中的xyz矩阵相乘倍数5 x=1 y=1 z=1 结果之后是 x=5 y=5 z=5
vector.multiplyScalar(5);
_acceleration.add(vector);
vector.set(_width, this.position.y, this.position.z);
vector = this.avoid(vector);
vector.multiplyScalar(5);
_acceleration.add(vector);
vector.set(this.position.x, -_height, this.position.z);
vector = this.avoid(vector);
vector.multiplyScalar(5);
_acceleration.add(vector);
vector.set(this.position.x, _height, this.position.z);
vector = this.avoid(vector);
vector.multiplyScalar(5);
_acceleration.add(vector);
vector.set(this.position.x, this.position.y, -_depth);
vector = this.avoid(vector);
vector.multiplyScalar(5);
_acceleration.add(vector);
vector.set(this.position.x, this.position.y, _depth);
vector = this.avoid(vector);
vector.multiplyScalar(5);
_acceleration.add(vector);
} else {
this.checkBounds();
}
if (Math.random() > 0.5) {
this.flock(boids);
}
this.move();
};
this.flock = function (boids) {
if (_goal) {
_acceleration.add(this.reach(_goal, 0.005));
}
_acceleration.add(this.alignment(boids));
_acceleration.add(this.cohesion(boids));
_acceleration.add(this.separation(boids));
};
this.move = function () {
this.velocity.add(_acceleration);
var l = this.velocity.length();
if (l > _maxSpeed) {
this.velocity.divideScalar(l / _maxSpeed);
}
this.position.add(this.velocity);
_acceleration.set(0, 0, 0);
};
//检测边框
this.checkBounds = function () {
if (this.position.x > _width)
this.position.x = -_width;
if (this.position.x < -_width)
this.position.x = _width;
if (this.position.y > _height)
this.position.y = -_height;
if (this.position.y < -_height)
this.position.y = _height;
if (this.position.z > _depth)
this.position.z = -_depth;
if (this.position.z < -_depth)
this.position.z = _depth;
};
this.avoid = function (target) {
var steer = new THREE.Vector3();
//拷贝xyz矩阵
steer.copy(this.position);
//返回vector3() this.position.x - target.x this.position.y - target.y this.position.z - target.z
steer.sub(target);
//矩阵缩放 矩阵差的平方和 x^2 + y^2 + z^2
steer.multiplyScalar(1 / this.position.distanceToSquared(target));
return steer;
};
this.repulse = function (target) {
//矩阵差的平方和的平方根
var distance = this.position.distanceTo(target);
if (distance < 150) {
var steer = new THREE.Vector3();
//返回vector3() a.x - b.x a.y - b.y a.z - b.z 两个矩阵相减
steer.subVectors(this.position, target);
steer.multiplyScalar(0,5 / distance);
_acceleration.add(steer);
}
};
this.reach = function (target, amount) {
var steer = new THREE.Vector3();
steer.subVectors(target, this.position);
steer.multiplyScalar(amount);
return steer;
};
this.alignment = function (boids) {
var count = 0;
var velSum = new THREE.Vector3();
for (var i = 0, il = boids.length; i < il; i++) {
if (Math.random() > 0.6)
continue;
var boid = boids[i];
var distance = boid.position.distanceTo(this.position);
if (distance > 0 && distance <= _neighborhoodRedius) {
velSum.add(boid.velocity);
count++;
}
}
if (count > 0) {
//this.multiplyScalar(1 / count)
velSum.divideScalar(count);
var l = velSum.length();
if (l > _maxSteerForce) {
velSum.divideScalar(l / _maxSteerForce);
}
}
return velSum;
};
this.cohesion = function (boids) {
var count = 0;
var posSum = new THREE.Vector3();
var steer = new THREE.Vector3();
for (var i = 0, il = boids.length; i < il; i++) {
if (Math.random() > 0.6)
continue;
var boid = boids[i];
var distance = boid.position.distanceTo(this.position);
if (distance > 0 && distance <= _neighborhoodRedius) {
posSum.add(boid.position);
count++;
}
}
if (count > 0) {
posSum.divideScalar(count);
}
steer.subVectors(posSum, this.position);
var l = steer.length();
if (l > _maxSteerForce) {
steer.divideScalar(l / _maxSteerForce);
}
return steer;
};
this.separation = function (boids) {
var posSum = new THREE.Vector3();
var repulse = new THREE.Vector3();
for (var i = 0, il = boids.length; i < il; i++) {
if (Math.random() > 0.6)
continue;
var boid = boids[i];
var distance = boid.position.distanceTo(this.position);
if (distance > 0 && distance <= _neighborhoodRedius) {
repulse.subVectors(this.position, boid.position);
repulse.normalize();
repulse.divideScalar(distance);
posSum.add(repulse);
}
}
return posSum;
};
}
下面就是代码正文部分,涉及到初始化,动态效果,场景,渲染。
var stats;
var container;
var camera;
var scene;
var renderer;
var bird;
var birds;
var boid;
var boids;
init();
animate();
function init() {
var width = window.innerWidth || 0;
var height = window.innerHeight || 0;
container = document.createElement('div');
document.body.appendChild(container);
var info = document.createElement('div');
info.style.position = 'absolute';
info.style.top = '0px';
info.style.width = '100%';
info.style.padding = '5px';
container.appendChild(info);
//镜头设置
var aspect = width / height;
camera = new THREE.PerspectiveCamera(75, aspect, 1, 10000);
camera.position.z = 450;
//场景
scene = new THREE.Scene();
scene.background = ne
9979
w THREE.Color(0xffffff);
birds = [];
boids = [];
for (var i = 0; i < 100; i++) {
boid = boids[i] = new Boid();
boid.position.x = Math.random() * 400 - 200;
boid.position.y = Math.random() * 400 - 200;
boid.position.z = Math.random() * 400 - 200;
boid.velocity.x = Math.random() * 2 - 1;
boid.velocity.y = Math.random() * 2 - 1;
boid.velocity.z = Math.random() * 2 - 1;
boid.setAvoidWalls(true);
boid.setWorldSize(500, 500, 400);
bird = birds[i] = new THREE.Mesh(new Bird(), new THREE.MeshBasicMaterial({color : Math.random() * 0xffffff, side : THREE.DoubleSide}));
bird.phase = Math.floor(Math.random() * 62.83);
scene.add(bird);
}
renderer = new THREE.CanvasRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
document.addEventListener('mousemove', OnDocumentMouseMove, false);
document.body.appendChild(renderer.domElement);
//监控
stats = new Stats();
container.appendChild(stats.dom);
window.addEventListener('resize', onWindowResize, false);
}
//窗口缩放event
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//鼠标移动event
function OnDocumentMouseMove(event) {
var vector = new THREE.Vector3(event.clientX - window.innerWidth / 2, - event.clientY + window.innerHeight / 2, 0);
for (var i = 0, il = boids.length; i < il; i++) {
boid = boids[i];
vector.z = boid.position.z;
boid.repulse(vector);
}
}
function animate() {
//固定格式
requestAnimationFrame(animate);
//监控开始
stats.begin();
//渲染
render();
//监控结束
stats.end();
}
function render() {
for (var i = 0, il = birds.length; i < il; i++) {
boid = boids[i];
boid.run(boids);
bird = birds[i];
bird.position.copy(boids[i].position);
var color = bird.material.color;
color.r = color.g = color.b = (500 - bird.position.z) / 1000;
bird.rotation.y = Math.atan2(-boid.velocity.z, boid.velocity.x);
bird.rotation.z = Math.asin(boid.velocity.y / boid.velocity.length());
bird.phase = (bird.phase + (Math.max(0, bird.rotation.z) + 0.1)) % 62.83;
bird.geometry.vertices[5].y = bird.geometry.vertices[4].y = Math.sin(bird.phase) * 5;
}
renderer.render(scene, camera);
}
之后要涉及到airbus官网的效果。
相关文章推荐
- THREE.js 第二部分 canvas_camera_effect.html 内容分析
- three.js旋转的方块canvas_geometry_cube
- three.js旋转的360全景canvas_geometry_panorama
- THREE.js案例源码学习-geometry_birds
- THREE.js 第一部分 canvas_ascii_effect.html 内容分析
- three.js旋转的3D文字canvas_geometry_text
- Three.js源码阅读笔记(光照部分)
- HTML canvas原生js实现鼠标画图
- three.js 源码注释(七十九)extras/geometries/TorusGeometry.js
- html2canvas js截图并下载
- JS实现部分HTML固定页面顶部随屏滚动效果
- HTML5+JS游戏开发模块----canvas图片拖放
- JS原生轮播-基础篇(HTML+CSS)部分
- three.js 源码注释(八十)extras/geometries/OctahedronGeometry.js
- JS 使用html2canvas实现截图功能的问题记录和解决方案
- Node.js和Geddy初学者指南 - 第三部分:使用Mongdb持久化你的数据
- js获取网页上选中的部分,包含html代码
- canvas实现多个弹跳小球 js部分
- Javascript将html转成pdf,下载(html2canvas 和 jsPDF)
- canvas延伸-WebGL(three.js)