WebGL/ThreeJS項目結構介紹
最重要的一個js就是這個Store3D.js, 絕大多數代碼都放在這裡,也是整個程式的起點,
common/CommonFunction.js的主要作用
common/CommonFunction.js裡面有個函數CommonFunction.createMaterial用來建立材質,
function CommonFunction() {
}
/**
* 判斷目前對象是否為空對象
*/
CommonFunction.hasObj = function (obj) {
if (obj != null && typeof (obj) != "undefined") {
return true;
} else {
return false;
}
},
/**
* 建立材質
* length:材質的長
* width:材質寬度
* style:材質特性
*/
CommonFunction.createMaterial = function (length, width, style) {
var color = 0xFF0000;//材質的顔色
var image = null;//才是是否有貼圖
var texture = null;
var ifRepeat = 0;//貼圖是否設定重複顯示
var transparent = 0;//材質是否透明
var opacity = 0;//材質透明度
var depthTest = 1;//材質深度測試
if (CommonFunction.hasObj(style)) {
color = style.color || 0xFF0000;
image = style.image || null;
ifRepeat = style.ifRepeat || 0;
transparent = style.transparent || 0;
opacity = style.opacity || 0;
depthTest = style.depthTest;
}
let material = new THREE.MeshPhongMaterial({map: texture, color: color});
if (image != null) {
texture = new THREE.TextureLoader().load(image);
if (ifRepeat == 1) {
texture.repeat.x = length / 128;
texture.repeat.y = width / 128;
texture.repeat.y = 5;
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
}
material = new THREE.MeshBasicMaterial({map: texture});
}
if (transparent == 1) {
material.transparent = true;
}
if (depthTest == 0) {
material.depthTest = false;
}
material.opacity = opacity;
return material;
}
Data/BuildingData.js的主要作用
Data/BuildingData.js裡面聲明了一個buildingObjects對象表示所有建築物的類,
我們的資料分為兩部分,一部分是和建築相關的,比如牆和地闆,這些基本上是不會變化的,我們統一把它放到一個對象類裡面,
let buildingObjects = { // 所有建築物的類
objects: [ // 我們可以把地闆看作是一個非常薄的立方體
{
objectName: 'floor', // 地闆
objectType: 'cube',
length: 3400, // 長
width: 1200, // 寬
height: 1, // 高
position: { // 設定地闆位置在螢幕的正中央
x: 0,
y: 0,
z: 0
},
style:{
color: 0x5F7480,
opacity: 1
}
}
]
}
objects/Cube.js的主要作用
剛剛我們看了Data/BuildingData.js裡面的物體資料,那麼就要用一個Cube類來繪制這個立方體,就是objects/Cube.js
/**
* 立方體類
* 我們生活中很多的物體都可以歸結為立方體類,比如牆體,地闆,窗戶等都可看成是立方體類
* @param option
* @constructor
*/
function Cube(option){
this.length = option.length || 1;
this.width = option.width || 1;
this.height = option.height || 1;
this.Name = option.objName;
this.positionX = option.position.x || 0;
this.positionY = option.position.y || 0;
this.positionZ = option.position.z || 0;
// 設定立方體的顔色
this.style=option.style||{color:0xFF0000};
// 設定立方體的材質
let curmaterial=CommonFunction.createMaterial(this.width,this.height,this.style);
// 建立一個立方體
let cubeGeometry = new THREE.BoxGeometry(this.length, this.height, this.width);
let cube = new THREE.Mesh( cubeGeometry, curmaterial );
cube.name=this.Name;
cube.position.x=this.positionX;
cube.position.y=this.positionY;
cube.position.z=this.positionZ;
return cube;
}
function Store3D() {
this.scene = null; //場景
this.camera = null; //相機
this.renderer = null; //渲染器
this.objects = []; //場景中所有對象的集合
}
/**
* 初始化倉庫所有插件
*/
Store3D.prototype.initMain = function () {
this.initScene(); /** 初始化場景 */
this.initCamera(); /** 初始化相機 */
this.initRenderer(); /** 初始化渲染器 */
this.initBuilding(); /** 初始化建築物 */
this.initLight(); /** 初始化燈光 */
},
/**
* 倉庫整體開始運作
*/
Store3D.prototype.start = function () {
this.initMain();
this.animate();
},
/**
初始化場景,僅僅需要有句話就可以生命一個場景,非常簡單
**/
Store3D.prototype.initScene = function () {
this.scene = new THREE.Scene();
},
/**
初始化場景,因為我們做的工廠模型,盡可能的接近于真實情景,采用透視相機
**/
Store3D.prototype.initCamera = function () {
// 聲明一個相機, 這裡我們使用透視相機
// 視角:60,
// 縱橫比aspect:全屏,使用的是浏覽器的寬度/高度
//近平面near:0.1
//遠平面視角far:10000
this.camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 10000);
/*
設定相機位置,注意threejs中的坐标系采用的是右手坐标系
*/
this.camera.position.x = 0;
this.camera.position.y = 1600;
this.camera.position.z = 1000;
//相機的朝向
this.camera.lookAt(0, 0, 0);
//将相機放到場景中
this.scene.add(this.camera);
},
/**
聲名渲染器
**/
Store3D.prototype.initRenderer = function () {
this.renderer = new THREE.WebGLRenderer(
{
antialias: true, //是否開啟反鋸齒,設定為true開啟反鋸齒。
alpha: true, //是否可以設定背景色透明。
logarithmicDepthBuffer: true //模型的重疊部位便不停的閃爍起來。這便是Z-Fighting問題,為解決這個問題,我們可以采用該種方法
}
);
this.renderer.setSize(window.innerWidth, window.innerHeight);//渲染器的尺寸與windows的尺寸相同
this.renderer.setClearColor(0x39609B);//設定渲染的背景顔色
this.renderer.setPixelRatio(window.devicePixelRatio);//設定渲染器的分辨率與浏覽器電腦本身的分辨率相同
//将渲染器添加到我們的網頁中,可以将渲染的内容在網頁中顯示出來
let container = document.getElementById("container");
container.appendChild(this.renderer.domElement);
},
/**
* 初始化燈光
*/
Store3D.prototype.initLight=function(){
//首先添加個環境光
let ambient = new THREE.AmbientLight(0xffffff, 1); //AmbientLight,影響整個場景的光源
ambient.position.set(0, 0, 0);
this.addObject(ambient);
//添加平行光,平行光類似于太陽光
let directionalLight = new THREE.DirectionalLight(0xffffff, 0.3);//模拟遠處類似太陽的光源
directionalLight.position.set(0, 200, 0);
this.addObject(directionalLight);
//設定點光源
let pointLight1=new THREE.PointLight(0xffffff, 0.3);
pointLight1.position.set(-500,200,0);
this.addObject(pointLight1);
let pointLight2=new THREE.PointLight(0xffffff, 0.3);
pointLight2.position.set(500,200,0);
this.addObject(pointLight2);
},
/**
* 向場景中添加物體,并記錄到
*/
Store3D.prototype.addObject = function (object) {
this.scene.add(object);
this.objects.push(object);
},
/**
建立建築物
*/
Store3D.prototype.initBuilding = function () {
let buildingData = buildingObjects.objects;
// buildingObjects.objects 下的所有對象進行周遊
for (let i = 0; i < buildingData.length; i++) {
let object = buildingData[i];
switch (object.objectType) { // 取object.objectType,
case "cube": // 當類型為cube的時候
let cube = new Cube(object); // 建立一個立方體
this.addObject(cube); // 将這個立方體放入場景中
}
}
},
/**
* 定時重複重新整理
*/
Store3D.prototype.animate = function () {
requestAnimationFrame(this.animate.bind(this));
this.renderer.render(this.scene, this.camera);
}