You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
899 lines
28 KiB
899 lines
28 KiB
2 years ago
|
<!DOCTYPE html>
|
||
|
<!-- saved from url=(0037)http://three.zuoben.top/case-031.html -->
|
||
|
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
|
<title>Threejs实现数字化工厂安全生产监控</title>
|
||
|
|
||
|
<script src="./hm.js"></script><script type="text/javascript" src="./statistics(1).js"></script>
|
||
|
<!-- <script type="text/javascript" src="./steak(1).js"></script> -->
|
||
|
<script type="text/javascript" src="./three.js"></script>
|
||
|
<script type="text/javascript" src="./OrbitControls.js"></script>
|
||
|
<script type="text/javascript" src="./GLTFLoader.js"></script>
|
||
|
<script type="text/javascript" src="./ThreeBSP.js"></script>
|
||
|
<script type="text/javascript" src="./dat.gui.js"></script><style type="text/css">.dg {
|
||
|
/** Clear list styles */
|
||
|
/* Auto-place container */
|
||
|
/* Auto-placed GUI's */
|
||
|
/* Line items that don't contain folders. */
|
||
|
/** Folder names */
|
||
|
/** Hides closed items */
|
||
|
/** Controller row */
|
||
|
/** Name-half (left) */
|
||
|
/** Controller-half (right) */
|
||
|
/** Controller placement */
|
||
|
/** Shorter number boxes when slider is present. */
|
||
|
/** Ensure the entire boolean and function row shows a hand */ }
|
||
|
.dg ul {
|
||
|
list-style: none;
|
||
|
margin: 0;
|
||
|
padding: 0;
|
||
|
width: 100%;
|
||
|
clear: both; }
|
||
|
.dg.ac {
|
||
|
position: fixed;
|
||
|
top: 0;
|
||
|
left: 0;
|
||
|
right: 0;
|
||
|
height: 0;
|
||
|
z-index: 0; }
|
||
|
.dg:not(.ac) .main {
|
||
|
/** Exclude mains in ac so that we don't hide close button */
|
||
|
overflow: hidden; }
|
||
|
.dg.main {
|
||
|
-webkit-transition: opacity 0.1s linear;
|
||
|
-o-transition: opacity 0.1s linear;
|
||
|
-moz-transition: opacity 0.1s linear;
|
||
|
transition: opacity 0.1s linear; }
|
||
|
.dg.main.taller-than-window {
|
||
|
overflow-y: auto; }
|
||
|
.dg.main.taller-than-window .close-button {
|
||
|
opacity: 1;
|
||
|
/* TODO, these are style notes */
|
||
|
margin-top: -1px;
|
||
|
border-top: 1px solid #2c2c2c; }
|
||
|
.dg.main ul.closed .close-button {
|
||
|
opacity: 1 !important; }
|
||
|
.dg.main:hover .close-button,
|
||
|
.dg.main .close-button.drag {
|
||
|
opacity: 1; }
|
||
|
.dg.main .close-button {
|
||
|
/*opacity: 0;*/
|
||
|
-webkit-transition: opacity 0.1s linear;
|
||
|
-o-transition: opacity 0.1s linear;
|
||
|
-moz-transition: opacity 0.1s linear;
|
||
|
transition: opacity 0.1s linear;
|
||
|
border: 0;
|
||
|
position: absolute;
|
||
|
line-height: 19px;
|
||
|
height: 20px;
|
||
|
/* TODO, these are style notes */
|
||
|
cursor: pointer;
|
||
|
text-align: center;
|
||
|
background-color: #000; }
|
||
|
.dg.main .close-button:hover {
|
||
|
background-color: #111; }
|
||
|
.dg.a {
|
||
|
float: right;
|
||
|
margin-right: 15px;
|
||
|
overflow-x: hidden; }
|
||
|
.dg.a.has-save > ul {
|
||
|
margin-top: 27px; }
|
||
|
.dg.a.has-save > ul.closed {
|
||
|
margin-top: 0; }
|
||
|
.dg.a .save-row {
|
||
|
position: fixed;
|
||
|
top: 0;
|
||
|
z-index: 1002; }
|
||
|
.dg li {
|
||
|
-webkit-transition: height 0.1s ease-out;
|
||
|
-o-transition: height 0.1s ease-out;
|
||
|
-moz-transition: height 0.1s ease-out;
|
||
|
transition: height 0.1s ease-out; }
|
||
|
.dg li:not(.folder) {
|
||
|
cursor: auto;
|
||
|
height: 27px;
|
||
|
line-height: 27px;
|
||
|
overflow: hidden;
|
||
|
padding: 0 4px 0 5px; }
|
||
|
.dg li.folder {
|
||
|
padding: 0;
|
||
|
border-left: 4px solid rgba(0, 0, 0, 0); }
|
||
|
.dg li.title {
|
||
|
cursor: pointer;
|
||
|
margin-left: -4px; }
|
||
|
.dg .closed li:not(.title),
|
||
|
.dg .closed ul li,
|
||
|
.dg .closed ul li > * {
|
||
|
height: 0;
|
||
|
overflow: hidden;
|
||
|
border: 0; }
|
||
|
.dg .cr {
|
||
|
clear: both;
|
||
|
padding-left: 3px;
|
||
|
height: 27px; }
|
||
|
.dg .property-name {
|
||
|
cursor: default;
|
||
|
float: left;
|
||
|
clear: left;
|
||
|
width: 40%;
|
||
|
overflow: hidden;
|
||
|
text-overflow: ellipsis; }
|
||
|
.dg .c {
|
||
|
float: left;
|
||
|
width: 60%; }
|
||
|
.dg .c input[type=text] {
|
||
|
border: 0;
|
||
|
margin-top: 4px;
|
||
|
padding: 3px;
|
||
|
width: 100%;
|
||
|
float: right; }
|
||
|
.dg .has-slider input[type=text] {
|
||
|
width: 30%;
|
||
|
/*display: none;*/
|
||
|
margin-left: 0; }
|
||
|
.dg .slider {
|
||
|
float: left;
|
||
|
width: 66%;
|
||
|
margin-left: -5px;
|
||
|
margin-right: 0;
|
||
|
height: 19px;
|
||
|
margin-top: 4px; }
|
||
|
.dg .slider-fg {
|
||
|
height: 100%; }
|
||
|
.dg .c input[type=checkbox] {
|
||
|
margin-top: 9px; }
|
||
|
.dg .c select {
|
||
|
margin-top: 5px; }
|
||
|
.dg .cr.function,
|
||
|
.dg .cr.function .property-name,
|
||
|
.dg .cr.function *,
|
||
|
.dg .cr.boolean,
|
||
|
.dg .cr.boolean * {
|
||
|
cursor: pointer; }
|
||
|
.dg .selector {
|
||
|
display: none;
|
||
|
position: absolute;
|
||
|
margin-left: -9px;
|
||
|
margin-top: 23px;
|
||
|
z-index: 10; }
|
||
|
.dg .c:hover .selector,
|
||
|
.dg .selector.drag {
|
||
|
display: block; }
|
||
|
.dg li.save-row {
|
||
|
padding: 0; }
|
||
|
.dg li.save-row .button {
|
||
|
display: inline-block;
|
||
|
padding: 0px 6px; }
|
||
|
.dg.dialogue {
|
||
|
background-color: #222;
|
||
|
width: 460px;
|
||
|
padding: 15px;
|
||
|
font-size: 13px;
|
||
|
line-height: 15px; }
|
||
|
|
||
|
/* TODO Separate style and structure */
|
||
|
#dg-new-constructor {
|
||
|
padding: 10px;
|
||
|
color: #222;
|
||
|
font-family: Monaco, monospace;
|
||
|
font-size: 10px;
|
||
|
border: 0;
|
||
|
resize: none;
|
||
|
box-shadow: inset 1px 1px 1px #888;
|
||
|
word-wrap: break-word;
|
||
|
margin: 12px 0;
|
||
|
display: block;
|
||
|
width: 440px;
|
||
|
overflow-y: scroll;
|
||
|
height: 100px;
|
||
|
position: relative; }
|
||
|
|
||
|
#dg-local-explain {
|
||
|
display: none;
|
||
|
font-size: 11px;
|
||
|
line-height: 17px;
|
||
|
border-radius: 3px;
|
||
|
background-color: #333;
|
||
|
padding: 8px;
|
||
|
margin-top: 10px; }
|
||
|
#dg-local-explain code {
|
||
|
font-size: 10px; }
|
||
|
|
||
|
#dat-gui-save-locally {
|
||
|
display: none; }
|
||
|
|
||
|
/** Main type */
|
||
|
.dg {
|
||
|
color: #eee;
|
||
|
font: 11px 'Lucida Grande', sans-serif;
|
||
|
text-shadow: 0 -1px 0 #111;
|
||
|
/** Auto place */
|
||
|
/* Controller row, <li> */
|
||
|
/** Controllers */ }
|
||
|
.dg.main {
|
||
|
/** Scrollbar */ }
|
||
|
.dg.main::-webkit-scrollbar {
|
||
|
width: 5px;
|
||
|
background: #1a1a1a; }
|
||
|
.dg.main::-webkit-scrollbar-corner {
|
||
|
height: 0;
|
||
|
display: none; }
|
||
|
.dg.main::-webkit-scrollbar-thumb {
|
||
|
border-radius: 5px;
|
||
|
background: #676767; }
|
||
|
.dg li:not(.folder) {
|
||
|
background: #1a1a1a;
|
||
|
border-bottom: 1px solid #2c2c2c; }
|
||
|
.dg li.save-row {
|
||
|
line-height: 25px;
|
||
|
background: #dad5cb;
|
||
|
border: 0; }
|
||
|
.dg li.save-row select {
|
||
|
margin-left: 5px;
|
||
|
width: 108px; }
|
||
|
.dg li.save-row .button {
|
||
|
margin-left: 5px;
|
||
|
margin-top: 1px;
|
||
|
border-radius: 2px;
|
||
|
font-size: 9px;
|
||
|
line-height: 7px;
|
||
|
padding: 4px 4px 5px 4px;
|
||
|
background: #c5bdad;
|
||
|
color: #fff;
|
||
|
text-shadow: 0 1px 0 #b0a58f;
|
||
|
box-shadow: 0 -1px 0 #b0a58f;
|
||
|
cursor: pointer; }
|
||
|
.dg li.save-row .button.gears {
|
||
|
background: #c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;
|
||
|
height: 7px;
|
||
|
width: 8px; }
|
||
|
.dg li.save-row .button:hover {
|
||
|
background-color: #bab19e;
|
||
|
box-shadow: 0 -1px 0 #b0a58f; }
|
||
|
.dg li.folder {
|
||
|
border-bottom: 0; }
|
||
|
.dg li.title {
|
||
|
padding-left: 16px;
|
||
|
background: black url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;
|
||
|
cursor: pointer;
|
||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.2); }
|
||
|
.dg .closed li.title {
|
||
|
background-image: url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==); }
|
||
|
.dg .cr.boolean {
|
||
|
border-left: 3px solid #806787; }
|
||
|
.dg .cr.function {
|
||
|
border-left: 3px solid #e61d5f; }
|
||
|
.dg .cr.number {
|
||
|
border-left: 3px solid #2fa1d6; }
|
||
|
.dg .cr.number input[type=text] {
|
||
|
color: #2fa1d6; }
|
||
|
.dg .cr.string {
|
||
|
border-left: 3px solid #1ed36f; }
|
||
|
.dg .cr.string input[type=text] {
|
||
|
color: #1ed36f; }
|
||
|
.dg .cr.function:hover, .dg .cr.boolean:hover {
|
||
|
background: #111; }
|
||
|
.dg .c input[type=text] {
|
||
|
background: #303030;
|
||
|
outline: none; }
|
||
|
.dg .c input[type=text]:hover {
|
||
|
background: #3c3c3c; }
|
||
|
.dg .c input[type=text]:focus {
|
||
|
background: #494949;
|
||
|
color: #fff; }
|
||
|
.dg .c .slider {
|
||
|
background: #303030;
|
||
|
cursor: ew-resize; }
|
||
|
.dg .c .slider-fg {
|
||
|
background: #2fa1d6; }
|
||
|
.dg .c .slider:hover {
|
||
|
background: #3c3c3c; }
|
||
|
.dg .c .slider:hover .slider-fg {
|
||
|
background: #44abda; }
|
||
|
</style>
|
||
|
<script type="text/javascript" charset="UTF-8" src="./Tween.min.js"></script>
|
||
|
<style>
|
||
|
body {
|
||
|
margin: 0;
|
||
|
overflow: hidden;
|
||
|
}
|
||
|
</style>
|
||
|
</head>
|
||
|
<body>
|
||
|
<div id="dom"><canvas width="1427" height="794" style="width: 1427px; height: 794px;"></canvas></div>
|
||
|
<script type="text/javascript">
|
||
|
var camera;
|
||
|
var renderer;
|
||
|
var peopleMesh;
|
||
|
var peopleMixer;
|
||
|
var mixer;
|
||
|
var matArrayA = []; //内墙
|
||
|
var matArr = []; //外墙
|
||
|
var texture;
|
||
|
var textureSecure;
|
||
|
var curve;
|
||
|
|
||
|
function init() {
|
||
|
var urls = [
|
||
|
'assets/bgImage/skyBox6/posx.jpg',
|
||
|
'assets/bgImage/skyBox6/negx.jpg',
|
||
|
'assets/bgImage/skyBox6/posy.jpg',
|
||
|
'assets/bgImage/skyBox6/negy.jpg',
|
||
|
'assets/bgImage/skyBox6/posz.jpg',
|
||
|
'assets/bgImage/skyBox6/negz.jpg'
|
||
|
];
|
||
|
// 创建一个场景,它将包含我们所有的元素,如物体,相机和灯光。
|
||
|
var scene = new THREE.Scene();
|
||
|
var cubeLoader = new THREE.CubeTextureLoader();
|
||
|
// scene.background = cubeLoader.load(urls);
|
||
|
scene.opacity = 0;
|
||
|
|
||
|
// 创建一个摄像机,它定义了我们正在看的地方
|
||
|
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100000);
|
||
|
// 将摄像机对准场景的中心
|
||
|
camera.position.z = 2000;
|
||
|
camera.position.y = 800;
|
||
|
camera.lookAt(scene.position);
|
||
|
var orbit = new THREE.OrbitControls(camera);
|
||
|
|
||
|
// 创建一个渲染器并设置大小,WebGLRenderer将会使用电脑显卡来渲染场景
|
||
|
renderer = new THREE.WebGLRenderer({
|
||
|
antialias: true,
|
||
|
logarithmicDepthBuffer: true,
|
||
|
});
|
||
|
renderer.setClearColor(new THREE.Color("#0e0934"));
|
||
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
||
|
|
||
|
var ambientLight = new THREE.AmbientLight("#ffffff", 1);
|
||
|
scene.add(ambientLight);
|
||
|
|
||
|
// 将呈现器的输出添加到HTML元素
|
||
|
document.getElementById("dom").appendChild(renderer.domElement);
|
||
|
|
||
|
// 启动动画
|
||
|
renderScene();
|
||
|
initContent();
|
||
|
initSloganModel();
|
||
|
|
||
|
for (var i = 0; i < 8; i++) {
|
||
|
let px = 1060 - i * 300;
|
||
|
addArea(px, -400, 200, 500, scene, "库区1-" + (i + 1) + "号", "FF0000", 20, "居中");
|
||
|
}
|
||
|
for (var i = 0; i < 8; i++) {
|
||
|
let px = 1060 - i * 300;
|
||
|
if (i != 1 && i != 2 && i != 5 && i != 6) {
|
||
|
addArea(px, 400, 200, 500, scene, "库区2-" + (i + 1) + "号", "FF0000", 20, "居中");
|
||
|
}
|
||
|
}
|
||
|
initSecureModel();
|
||
|
|
||
|
// 初始化模型
|
||
|
function initContent() {
|
||
|
createFloor();
|
||
|
createWallMaterail();
|
||
|
var mat = new THREE.MeshPhongMaterial({
|
||
|
color: 0xafc0ca
|
||
|
});
|
||
|
createCubeWall(10, 200, 1400, 0, matArr, -1295, 100, 0, "墙面");
|
||
|
createCubeWall(10, 200, 1400, 1, matArr, 1295, 100, 0, "墙面");
|
||
|
createCubeWall(10, 200, 2600, 1.5, matArr, 0, 100, -700, "墙面");
|
||
|
//创建挖了门的墙
|
||
|
var wall = returnWallObject(2600, 200, 10, 0, mat, 0, 100, 700, "墙面");
|
||
|
var door_cube1 = returnWallObject(200, 180, 10, 0, mat, -600, 90, 700, "前门1");
|
||
|
var door_cube2 = returnWallObject(200, 180, 10, 0, mat, 600, 90, 700, "前门2");
|
||
|
var window_cube1 = returnWallObject(100, 100, 10, 0, mat, -900, 90, 700, "窗户1");
|
||
|
var window_cube2 = returnWallObject(100, 100, 10, 0, mat, 900, 90, 700, "窗户2");
|
||
|
var window_cube3 = returnWallObject(100, 100, 10, 0, mat, -200, 90, 700, "窗户3");
|
||
|
var window_cube4 = returnWallObject(100, 100, 10, 0, mat, 200, 90, 700, "窗户4");
|
||
|
var objects_cube = [];
|
||
|
objects_cube.push(door_cube1);
|
||
|
objects_cube.push(door_cube2);
|
||
|
objects_cube.push(window_cube1);
|
||
|
objects_cube.push(window_cube2);
|
||
|
objects_cube.push(window_cube3);
|
||
|
objects_cube.push(window_cube4);
|
||
|
createResultBsp(wall, objects_cube);
|
||
|
// 为墙面安装门
|
||
|
createDoor(100, 180, 2, 0, -700, 90, 700, "左门1");
|
||
|
createDoor(100, 180, 2, 0, -500, 90, 700, "右门1");
|
||
|
createDoor(100, 180, 2, 0, 500, 90, 700, "左门2");
|
||
|
createDoor(100, 180, 2, 0, 700, 90, 700, "右门2");
|
||
|
// 为墙面安装窗户
|
||
|
createWindow(100, 100, 2, 0, -900, 90, 700, "窗户");
|
||
|
createWindow(100, 100, 2, 0, 900, 90, 700, "窗户");
|
||
|
createWindow(100, 100, 2, 0, -200, 90, 700, "窗户");
|
||
|
createWindow(100, 100, 2, 0, 200, 90, 700, "窗户");
|
||
|
}
|
||
|
|
||
|
setTimeout(function() {
|
||
|
doorOpenColse(true);
|
||
|
}, 2000);
|
||
|
setTimeout(function() {
|
||
|
initPeople();
|
||
|
}, 2500);
|
||
|
|
||
|
// 添加人物模型
|
||
|
function initPeople() {
|
||
|
var loader = new THREE.GLTFLoader();
|
||
|
loader.load('assets/models/man/man.gltf', function(result) {
|
||
|
console.log(result)
|
||
|
result.scene.scale.set(50, 50, 50);
|
||
|
// result.scene.rotation.y = Math.PI / 2;
|
||
|
peopleMesh = result.scene;
|
||
|
scene.add(peopleMesh);
|
||
|
|
||
|
peopleMixer = new THREE.AnimationMixer(peopleMesh);
|
||
|
let AnimationAction = peopleMixer.clipAction(result.animations[0]);
|
||
|
AnimationAction.play();
|
||
|
|
||
|
motion()
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function motion() {
|
||
|
// 通过类CatmullRomCurve3创建一个3D样条曲线
|
||
|
curve = new THREE.CatmullRomCurve3([
|
||
|
new THREE.Vector3(602, 3, 790),
|
||
|
new THREE.Vector3(597, 3, -3),
|
||
|
new THREE.Vector3(-605, 3, -3),
|
||
|
new THREE.Vector3(-602, 3, 790)
|
||
|
], false, "catmullrom", 0.01);
|
||
|
// 样条曲线均匀分割100分,返回51个顶点坐标
|
||
|
var points = curve.getPoints(100);
|
||
|
var geometry = new THREE.Geometry();
|
||
|
// 把从曲线轨迹上获得的顶点坐标赋值给几何体
|
||
|
geometry.vertices = points
|
||
|
var material = new THREE.LineBasicMaterial({
|
||
|
color: 0x4488ff
|
||
|
});
|
||
|
var line = new THREE.Line(geometry, material);
|
||
|
// scene.add(line)
|
||
|
|
||
|
// 通过Threejs的帧动画相关API播放网格模型沿着曲线做动画运动
|
||
|
// 声明一个数组用于存储时间序列
|
||
|
let arr = []
|
||
|
for (let i = 0; i < 101; i++) {
|
||
|
arr.push(i)
|
||
|
}
|
||
|
// 生成一个时间序列
|
||
|
var times = new Float32Array(arr);
|
||
|
|
||
|
var posArr = []
|
||
|
points.forEach(elem => {
|
||
|
posArr.push(elem.x, elem.y, elem.z)
|
||
|
});
|
||
|
// 创建一个和时间序列相对应的位置坐标系列
|
||
|
var values = new Float32Array(posArr);
|
||
|
// 创建一个帧动画的关键帧数据,曲线上的位置序列对应一个时间序列
|
||
|
var posTrack = new THREE.KeyframeTrack('.position', times, values);
|
||
|
let duration = 101;
|
||
|
let clip = new THREE.AnimationClip("default", duration, [posTrack]);
|
||
|
mixer = new THREE.AnimationMixer(peopleMesh);
|
||
|
let AnimationAction = mixer.clipAction(clip);
|
||
|
AnimationAction.play();
|
||
|
}
|
||
|
|
||
|
function changeLookAt(t) {
|
||
|
// 当前点在线条上的位置
|
||
|
var position = curve.getPointAt(t);
|
||
|
peopleMesh.position.copy(position);
|
||
|
if(position.z < 0) {
|
||
|
peopleMesh.rotation.y = Math.PI;
|
||
|
// camera.position.set(position.x + 200, 70, position.z);
|
||
|
}
|
||
|
if(position.z > 0 && position.x > 0) {
|
||
|
peopleMesh.rotation.y = Math.PI / 2;
|
||
|
// camera.position.set(position.x , 70, position.z+ 200);
|
||
|
}
|
||
|
if(position.z > 0 && position.x < 0) {
|
||
|
peopleMesh.rotation.y = -Math.PI / 2;
|
||
|
// camera.position.set(position.x , 70, position.z - 200);
|
||
|
}
|
||
|
// console.log(position)
|
||
|
// camera.position.set(position.x / 2, 69, position.z / 2);
|
||
|
camera.lookAt(position);
|
||
|
// camera.lookAt(position);659.0248303057256, y: 69.31162905236907, z: 921
|
||
|
|
||
|
|
||
|
// 返回一个点t在曲线上位置向量的法线向量
|
||
|
const tangent = curve.getTangentAt(t);
|
||
|
// 位置向量和切线向量相加即为所需朝向的点向量
|
||
|
const lookAtVec = tangent.add(position);
|
||
|
// peopleMesh.lookAt(lookAtVec);
|
||
|
}
|
||
|
|
||
|
//Secure 安全通道
|
||
|
function initSecureModel() {
|
||
|
var planGeometry = new THREE.PlaneGeometry(680, 40);
|
||
|
textureSecure = new THREE.TextureLoader().load('assets/textures/roll.png');
|
||
|
textureSecure.wrapS = THREE.RepeatWrapping
|
||
|
|
||
|
var tubeMaterial = new THREE.MeshBasicMaterial({
|
||
|
map: textureSecure,
|
||
|
transparent: true,
|
||
|
side: THREE.DoubleSide,
|
||
|
});
|
||
|
|
||
|
// 设置数组材质对象作为网格模型材质参数
|
||
|
var obj = new THREE.Mesh(planGeometry, tubeMaterial); //网格模型对象Mesh
|
||
|
obj.position.z = 350;
|
||
|
obj.position.y = 1.5;
|
||
|
obj.position.x = 599;
|
||
|
obj.rotateX(Math.PI / 2.0);
|
||
|
obj.rotateZ(Math.PI / 2.0);
|
||
|
var obj2 = obj.clone();
|
||
|
obj2.translateY(1200);
|
||
|
obj2.rotateZ(Math.PI);
|
||
|
|
||
|
var geometry2 = new THREE.PlaneGeometry(1230, 40);
|
||
|
var obj3 = new THREE.Mesh(geometry2, tubeMaterial);
|
||
|
obj3.position.set(0, 1.5, -10);
|
||
|
obj3.rotation.x = -Math.PI / 2.0;
|
||
|
|
||
|
var group = new THREE.Group();
|
||
|
group.add(obj);
|
||
|
group.add(obj2);
|
||
|
group.add(obj3);
|
||
|
scene.add(group);
|
||
|
}
|
||
|
|
||
|
//region 矩形区域
|
||
|
function addPlane(x, z, width, length, scene) {
|
||
|
var LineMat = new THREE.MeshLambertMaterial();
|
||
|
new THREE.TextureLoader().load("assets/textures/line.png", function(map) {
|
||
|
LineMat.map = map;
|
||
|
LineMat.needsUpdate = true;
|
||
|
});
|
||
|
var lineWidth = 8
|
||
|
var geometry = new THREE.PlaneGeometry(lineWidth, length);
|
||
|
var obj = new THREE.Mesh(geometry, LineMat);
|
||
|
obj.position.set(x, 1.5, z);
|
||
|
obj.rotation.x = -Math.PI / 2.0;
|
||
|
var obj2 = obj.clone();
|
||
|
obj2.translateX(width);
|
||
|
|
||
|
var geometry2 = new THREE.PlaneGeometry(lineWidth, width);
|
||
|
var obj3 = new THREE.Mesh(geometry2, LineMat);
|
||
|
obj3.position.set(x + width / 2, 1.5, z - length / 2 + lineWidth / 2);
|
||
|
obj3.rotation.x = -Math.PI / 2.0;
|
||
|
obj3.rotation.z = -Math.PI / 2.0;
|
||
|
var obj4 = obj3.clone();
|
||
|
obj4.translateX(length - lineWidth);
|
||
|
|
||
|
var group = new THREE.Group();
|
||
|
group.add(obj);
|
||
|
group.add(obj2);
|
||
|
group.add(obj3);
|
||
|
group.add(obj4);
|
||
|
group.translateX(-width / 2);
|
||
|
scene.add(group);
|
||
|
}
|
||
|
|
||
|
// 口号标语
|
||
|
function initSloganModel() {
|
||
|
var planGeometry = new THREE.PlaneGeometry(500, 35);
|
||
|
texture = new THREE.TextureLoader().load('assets/textures/biaoyu.png');
|
||
|
texture.wrapS = THREE.RepeatWrapping
|
||
|
|
||
|
var tubeMaterial = new THREE.MeshBasicMaterial({
|
||
|
map: texture,
|
||
|
transparent: true,
|
||
|
side: THREE.DoubleSide,
|
||
|
});
|
||
|
|
||
|
// 设置数组材质对象作为网格模型材质参数
|
||
|
var mesh = new THREE.Mesh(planGeometry, tubeMaterial); //网格模型对象Mesh
|
||
|
mesh.position.y = 175;
|
||
|
mesh.position.z = 710;
|
||
|
// mesh.rotateZ(3.14);
|
||
|
scene.add(mesh); //网格模型添加到场景中
|
||
|
}
|
||
|
|
||
|
//region 库区
|
||
|
/** 放置虚线框区域和库区名称 */
|
||
|
function addArea(x, z, width, length, scene, name, textColor, font_size, textposition) {
|
||
|
addPlane(x, z, width, length, scene);
|
||
|
|
||
|
new THREE.FontLoader().load('font/FZYaoTi_Regular.json', function(font) {
|
||
|
//加入立体文字
|
||
|
var text = new THREE.TextGeometry(name, {
|
||
|
// 设定文字字体
|
||
|
font: font,
|
||
|
//尺寸
|
||
|
size: font_size,
|
||
|
//厚度
|
||
|
height: 0.01
|
||
|
});
|
||
|
text.computeBoundingBox();
|
||
|
//3D文字材质
|
||
|
var m = new THREE.MeshStandardMaterial({
|
||
|
color: "#" + textColor
|
||
|
});
|
||
|
var mesh = new THREE.Mesh(text, m)
|
||
|
if (textposition == "左对齐") {
|
||
|
mesh.position.x = x - width / 2 + 10;
|
||
|
} else if (textposition == "居中") {
|
||
|
mesh.position.x = x - 65;
|
||
|
} else if (textposition == "右对齐") {
|
||
|
mesh.position.x = x + width / 2 - 60;
|
||
|
}
|
||
|
mesh.position.y = 1.3;
|
||
|
mesh.position.z = z + length / 2 - 20;
|
||
|
mesh.rotation.x = -Math.PI / 2.0;
|
||
|
scene.add(mesh);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
//创建墙纹理
|
||
|
function createWallMaterail() {
|
||
|
matArr.push(new THREE.MeshPhongMaterial({
|
||
|
color: 0xafc0ca
|
||
|
})); //前 0xafc0ca :灰色
|
||
|
matArr.push(new THREE.MeshPhongMaterial({
|
||
|
color: 0x9cb2d1
|
||
|
})); //后 0x9cb2d1:淡紫
|
||
|
matArr.push(new THREE.MeshPhongMaterial({
|
||
|
color: 0xd6e4ec
|
||
|
})); //上 0xd6e4ec: 偏白色
|
||
|
matArr.push(new THREE.MeshPhongMaterial({
|
||
|
color: 0xd6e4ec
|
||
|
})); //下
|
||
|
matArr.push(new THREE.MeshPhongMaterial({
|
||
|
color: 0xafc0ca
|
||
|
})); //左 0xafc0ca :灰色
|
||
|
matArr.push(new THREE.MeshPhongMaterial({
|
||
|
color: 0xafc0ca
|
||
|
})); //右
|
||
|
}
|
||
|
|
||
|
//返回墙对象
|
||
|
function returnWallObject(width, height, depth, angle, material, x, y, z, name) {
|
||
|
var cubeGeometry = new THREE.BoxGeometry(width, height, depth);
|
||
|
var cube = new THREE.Mesh(cubeGeometry, material);
|
||
|
cube.position.x = x;
|
||
|
cube.position.y = y;
|
||
|
cube.position.z = z;
|
||
|
cube.rotation.y += angle * Math.PI;
|
||
|
cube.name = name;
|
||
|
return cube;
|
||
|
}
|
||
|
|
||
|
//墙上挖门,通过两个几何体生成BSP对象
|
||
|
function createResultBsp(bsp, objects_cube) {
|
||
|
var material = new THREE.MeshPhongMaterial({
|
||
|
color: 0x9cb2d1,
|
||
|
specular: 0x9cb2d1,
|
||
|
shininess: 30,
|
||
|
transparent: true,
|
||
|
opacity: 1
|
||
|
});
|
||
|
var BSP = new ThreeBSP(bsp);
|
||
|
for (var i = 0; i < objects_cube.length; i++) {
|
||
|
var less_bsp = new ThreeBSP(objects_cube[i]);
|
||
|
BSP = BSP.subtract(less_bsp);
|
||
|
}
|
||
|
var result = BSP.toMesh(material);
|
||
|
result.material.flatshading = THREE.FlatShading;
|
||
|
result.geometry.computeFaceNormals(); //重新计算几何体侧面法向量
|
||
|
result.geometry.computeVertexNormals();
|
||
|
result.material.needsUpdate = true; //更新纹理
|
||
|
result.geometry.buffersNeedUpdate = true;
|
||
|
result.geometry.uvsNeedUpdate = true;
|
||
|
scene.add(result);
|
||
|
}
|
||
|
|
||
|
//创建地板
|
||
|
function createFloor() {
|
||
|
var loader = new THREE.TextureLoader();
|
||
|
loader.load("assets/textures/floor.jpg", function(texture) {
|
||
|
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
|
||
|
texture.repeat.set(10, 10);
|
||
|
var floorGeometry = new THREE.BoxGeometry(2600, 1400, 1);
|
||
|
var floorMaterial = new THREE.MeshBasicMaterial({
|
||
|
map: texture,
|
||
|
});
|
||
|
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
|
||
|
floor.rotation.x = -Math.PI / 2;
|
||
|
floor.name = "地面";
|
||
|
scene.add(floor);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
//创建墙
|
||
|
function createCubeWall(width, height, depth, angle, material, x, y, z, name) {
|
||
|
var cubeGeometry = new THREE.BoxGeometry(width, height, depth);
|
||
|
var cube = new THREE.Mesh(cubeGeometry, material);
|
||
|
cube.position.x = x;
|
||
|
cube.position.y = y;
|
||
|
cube.position.z = z;
|
||
|
cube.rotation.y += angle * Math.PI; //-逆时针旋转,+顺时针
|
||
|
cube.name = name;
|
||
|
scene.add(cube);
|
||
|
}
|
||
|
|
||
|
//创建门
|
||
|
function createDoor(width, height, depth, angle, x, y, z, name) {
|
||
|
var loader = new THREE.TextureLoader();
|
||
|
|
||
|
var doorgeometry = new THREE.BoxGeometry(width, height, depth);
|
||
|
var doormaterial_left = new THREE.MeshPhongMaterial({
|
||
|
map: loader.load("assets/textures/door_left.png")
|
||
|
});
|
||
|
doormaterial_left.opacity = 1.0;
|
||
|
doormaterial_left.transparent = true;
|
||
|
var doormaterial_right = new THREE.MeshPhongMaterial({
|
||
|
map: loader.load("assets/textures/door_right.png")
|
||
|
});
|
||
|
doormaterial_right.opacity = 1.0;
|
||
|
doormaterial_right.transparent = true;
|
||
|
|
||
|
var doormaterialArr = [];
|
||
|
if (name.indexOf("左门") > -1) {
|
||
|
doorgeometry.translate(50, 0, 0);
|
||
|
doormaterialArr = [doormaterial_left, doormaterial_left, doormaterial_left,
|
||
|
doormaterial_left, doormaterial_left, doormaterial_right
|
||
|
];
|
||
|
} else {
|
||
|
doorgeometry.translate(-50, 0, 0);
|
||
|
doormaterialArr = [doormaterial_right, doormaterial_right, doormaterial_right,
|
||
|
doormaterial_right, doormaterial_right, doormaterial_left
|
||
|
];
|
||
|
}
|
||
|
|
||
|
var door = new THREE.Mesh(doorgeometry, doormaterialArr);
|
||
|
door.position.set(x, y, z);
|
||
|
door.rotation.y += angle * Math.PI; //-逆时针旋转,+顺时针
|
||
|
door.name = name;
|
||
|
scene.add(door);
|
||
|
}
|
||
|
|
||
|
//创建窗户
|
||
|
function createWindow(width, height, depth, angle, x, y, z, name) {
|
||
|
var loader = new THREE.TextureLoader();
|
||
|
loader.load("assets/textures/window.png", function(texture) {
|
||
|
var windowgeometry = new THREE.BoxGeometry(width, height, depth);
|
||
|
var windowmaterial = new THREE.MeshBasicMaterial({
|
||
|
map: texture,
|
||
|
color: 0xffffff
|
||
|
});
|
||
|
windowmaterial.opacity = 1.0;
|
||
|
windowmaterial.transparent = true;
|
||
|
var window = new THREE.Mesh(windowgeometry, windowmaterial);
|
||
|
window.position.set(x, y, z);
|
||
|
window.rotation.y += angle * Math.PI; //-逆时针旋转,+顺时针
|
||
|
window.name = name;
|
||
|
scene.add(window);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// 键盘事件
|
||
|
document.onkeydown = function(event) {
|
||
|
// 打开
|
||
|
if (event.keyCode == 79) {
|
||
|
doorOpenColse(true);
|
||
|
}
|
||
|
// 关闭
|
||
|
if (event.keyCode == 67) {
|
||
|
doorOpenColse(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 门打开关闭
|
||
|
function doorOpenColse(bool) {
|
||
|
|
||
|
var l1 = scene.getObjectByName("左门1");
|
||
|
var l2 = scene.getObjectByName("左门2");
|
||
|
var r1 = scene.getObjectByName("右门1");
|
||
|
var r2 = scene.getObjectByName("右门2");
|
||
|
// 打开
|
||
|
if (bool) {
|
||
|
new TWEEN.Tween({
|
||
|
lv: 0,
|
||
|
rv: 0,
|
||
|
})
|
||
|
.to({
|
||
|
lv: -0.5 * Math.PI,
|
||
|
rv: 0.5 * Math.PI,
|
||
|
}, 1000)
|
||
|
.easing(TWEEN.Easing.Bounce.Out)
|
||
|
.onUpdate(function() {
|
||
|
l1.rotation.y = this.lv;
|
||
|
l2.rotation.y = this.lv;
|
||
|
r1.rotation.y = this.rv;
|
||
|
r2.rotation.y = this.rv;
|
||
|
})
|
||
|
.start();
|
||
|
}
|
||
|
// 关闭
|
||
|
if (!bool) {
|
||
|
new TWEEN.Tween({
|
||
|
lv: -0.5 * Math.PI,
|
||
|
rv: 0.5 * Math.PI,
|
||
|
})
|
||
|
.to({
|
||
|
lv: 0,
|
||
|
rv: 0,
|
||
|
}, 1000)
|
||
|
.easing(TWEEN.Easing.Bounce.Out)
|
||
|
.onUpdate(function() {
|
||
|
l1.rotation.y = this.lv;
|
||
|
l2.rotation.y = this.lv;
|
||
|
r1.rotation.y = this.rv;
|
||
|
r2.rotation.y = this.rv;
|
||
|
})
|
||
|
.start();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 拾取对象
|
||
|
function pickupObjects(event) {
|
||
|
// 点击屏幕创建一个向量
|
||
|
var raycaster = new THREE.Raycaster();
|
||
|
var vector = new THREE.Vector2((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window
|
||
|
.innerHeight) * 2 + 1);
|
||
|
var fxl = new THREE.Vector3(0, 1, 0);
|
||
|
var groundplane = new THREE.Plane(fxl, 0);
|
||
|
raycaster.setFromCamera(vector, camera);
|
||
|
var ray = raycaster.ray;
|
||
|
let intersects = ray.intersectPlane(groundplane);
|
||
|
console.log(intersects)
|
||
|
|
||
|
|
||
|
// 点击屏幕创建一个向量
|
||
|
var vector1 = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window
|
||
|
.innerHeight) * 2 + 1, 0.5);
|
||
|
vector1 = vector1.unproject(camera); // 将屏幕的坐标转换成三维场景中的坐标
|
||
|
var raycaster = new THREE.Raycaster(camera.position, vector1.sub(camera.position).normalize());
|
||
|
var intersects1 = raycaster.intersectObjects(scene.children, true);
|
||
|
if (intersects1.length > 0) {
|
||
|
console.log(intersects1)
|
||
|
// intersects1[0].object.material.color.set("#ff0000");
|
||
|
}
|
||
|
}
|
||
|
document.addEventListener('click', pickupObjects, false); //监听单击拾取对象初始化球体
|
||
|
|
||
|
var clock = new THREE.Clock(); //声明一个时钟对象
|
||
|
const loopTime = 50 * 1000; // loopTime: 循环一圈的时间
|
||
|
function renderScene() {
|
||
|
orbit.update();
|
||
|
TWEEN.update();
|
||
|
// 使用requestAnimationFrame函数进行渲染
|
||
|
requestAnimationFrame(renderScene);
|
||
|
renderer.render(scene, camera);
|
||
|
// 更新帧动画的时间
|
||
|
if (mixer) {
|
||
|
// mixer.update(clock.getDelta());
|
||
|
}
|
||
|
if (peopleMixer) {
|
||
|
peopleMixer.update(clock.getDelta());
|
||
|
}
|
||
|
|
||
|
if (curve) {
|
||
|
let time = Date.now();
|
||
|
let t = (time % loopTime) / loopTime; // 计算当前时间进度百分比
|
||
|
changeLookAt(t);
|
||
|
}
|
||
|
|
||
|
if (textureSecure) {
|
||
|
texture.offset.x += 0.004;
|
||
|
textureSecure.offset.x += 0.0005;
|
||
|
}
|
||
|
// console.log(camera.position)
|
||
|
}
|
||
|
|
||
|
// 渲染的场景
|
||
|
renderer.render(scene, camera);
|
||
|
}
|
||
|
window.onload = init;
|
||
|
|
||
|
// 随着窗体的变化修改场景
|
||
|
function onResize() {
|
||
|
camera.aspect = window.innerWidth / window.innerHeight;
|
||
|
camera.updateProjectionMatrix();
|
||
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
||
|
}
|
||
|
// 监听窗体调整大小事件
|
||
|
window.addEventListener('resize', onResize, false);
|
||
|
</script>
|
||
|
|
||
|
|
||
|
</body></html>
|