<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js fire</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="three.js"></script>
<script src="OrbitControls.js"></script>
<script>
var container, controls;
var camera, scene, renderer, light,groundMesh;
var clock = new THREE.Clock();
var fireArray = []; //保存所有的火焰
var activeFire; //跟随鼠标移动的火焰
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set( 50, 50, 50 );
controls = new THREE.OrbitControls( camera );
controls.target.set( 0, 0, 0 );
controls.update();
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xa0a0a0 );
//scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
light.position.set( 0, 200, 0 );
scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 200, 100 );
light.castShadow = true;
light.shadow.camera.top = 180;
light.shadow.camera.bottom = -100;
light.shadow.camera.left = -120;
light.shadow.camera.right = 120;
scene.add( light );
// scene.add( new THREE.CameraHelper( light.shadow.camera ) );
// ground
groundMesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 1000, 1000 ), new THREE.MeshPhongMaterial( { color: 0x222222, depthWrite: false } ) );
groundMesh.rotation.x = - Math.PI / 2;
groundMesh.receiveShadow = true;
scene.add( groundMesh );
var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
container.appendChild( renderer.domElement );
container.addEventListener('mousemove', onDocumentMouseMove, false);
container.addEventListener("mousedown", onDocumentMouseClick)
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
updateActiveFire();
updateFires();
renderer.render( scene, camera );
}
/*
* 鼠标平移事件
* */
function onDocumentMouseMove(event) {
var mouse = getInterection(event.offsetX,event.offsetY);
if(!mouse || mouse == undefined) return;
if(!activeFire){ //没有跟随鼠标的火点 需要创建
activeFire = new FirePoints([mouse.x,mouse.y + 0.5,mouse.z]);
activeFire.init();
scene.add(activeFire.obj);
}else{ //已经存在,更新位置
activeFire.updatePosition([mouse.x,mouse.y + 0.5,mouse.z]);
}
}
/*
* 鼠标单击事件
* */
function onDocumentMouseClick( event ) {
//判断是否有拖拽动作
var mouse = getInterection(event.offsetX,event.offsetY);
if(!mouse || mouse == undefined) return;
addFire([mouse.x,mouse.y + 0.5,mouse.z]);
}
//添加模拟火点
function addFire(position){
var fire = new FirePoints(position);//使用{FirePoints}创建火情
fire.init();
scene.add(fire.obj);
fireArray.push(fire);
}
/**
* 获取相交
* */
function getInterection(screenX,screenY){
var mv = new THREE.Vector3(
(screenX / container.clientWidth) * 2 - 1,
-(screenY / container.clientHeight) * 2 + 1,
0.5 );
mv.unproject(this.camera);
var raycaster = new THREE.Raycaster(camera.position, mv.sub(camera.position).normalize());
var intersects = raycaster.intersectObjects([groundMesh]); //scene.children
if (intersects.length > 0) {
var selected = intersects[0];//取第一个物体
return selected.point; //相交点坐标
}
}
//更新跟随鼠标的火焰
function updateActiveFire(){
var now = Date.now();
if(activeFire){
activeFire.update();
if(!activeFire.last_time_activate) activeFire.last_time_activate = Date.now();
if (now - activeFire.last_time_activate > 20) {
activeFire.activateMover();
activeFire.last_time_activate = Date.now();
}
}
}
//更新火焰
function updateFires(){
var now = Date.now();
for(var i=0;i<fireArray.length;i++){
var fire = fireArray[i];
fire.update();
if(!fire.last_time_activate) fire.last_time_activate = Date.now();
if (now - fire.last_time_activate > 20) {
fire.activateMover();
fire.last_time_activate = Date.now();
}
}
}
//模拟火情的一些常量
var FireUtil = {
getRandomInt: function(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
},
getDegree: function(radian) {
return radian / Math.PI * 180;
},
getRadian: function(degrees) {
return degrees * Math.PI / 180;
},
getSpherical: function(rad1, rad2, r) {
var x = Math.cos(rad1) * Math.cos(rad2) * r;
var z = Math.cos(rad1) * Math.sin(rad2) * r;
var y = Math.sin(rad1) * r;
return new THREE.Vector3(x, y, z);
}
}
/*
* 创建模拟火情的精灵点
* @param {THREE.Material} material 材质
*/
var FireGrain = function(material) {
this.position = new THREE.Vector3();
this.velocity = new THREE.Vector3();
this.acceleration = new THREE.Vector3();
this.material = material;
this.sprite = new THREE.Sprite(this.material);
this.sprite.scale.set(5,5,1);
this.mass = 1;
this.is_active = false;
};
FireGrain.prototype = {
init: function(vector) {
this.position = vector.clone();
this.velocity = vector.clone();
this.acceleration.set(0, 0, 0);
this.sprite.position.copy(this.position);
},
updatePosition: function() {
this.position.copy(this.velocity);
this.sprite.position.copy(this.position);
},
updateVelocity: function() {
this.acceleration.divideScalar(this.mass);
this.velocity.add(this.acceleration);
},
applyForce: function(vector) {
this.acceleration.add(vector);
},
activate: function() {
this.is_active = true;
},
inactivate: function() {
this.is_active = false;
}
};
/*
* 根据三维坐标点创建模拟火情
* @param {Array} position
evomap
- 粉丝: 486
- 资源: 15
最新资源
- java-leetcode题解之Check If It Is a Good Array.java
- java-leetcode题解之Cheapest Flights Within K Stops.java
- java-leetcode题解之Champagne Tower.java
- java-leetcode题解之Cells with Odd Values in a Matrix.java
- java-leetcode题解之Card Flipping Game.java
- java-leetcode题解之Capacity To Ship Packages Within D Days.java
- java-leetcode题解之Can Place Flowers.java
- java-leetcode题解之Can Make Palindrome from Substring.java
- java-leetcode题解之Can I Win.java
- java-leetcode题解之Candy.java
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
- 1
- 2
- 3
前往页