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;
}
objects/Store3D.js的主要作用
是初始化场景、初始化相机、初始化渲染器、初始化建筑物创建建筑物、初始化灯光定时刷新等
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);
}