根据上篇笔记,在对3D对象可进行普通的控制后,以及学习了http://hiwebgl.com的教程第10章内容:世界模型的载入以及控制镜头移动,经过多次调试矩阵代码,已经可以实现在世界中旋转镜头/控制移动,并添加3D对象在世界模型中进行相对移动
测试代码如下,拷贝到您的浏览器打开,方向键控制镜头旋转与移动
<!doctype html>
<html>
<head>
<style>
* {margin:0;padding:0;overflow:hidden;}
</style>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat4 uPMatrix;
uniform mat4 uTranslateMatrix;
uniform mat4 uScaleMatrix;
uniform mat4 uRotateYMatrix;
uniform mat4 uRotateXMatrix;
uniform mat4 uRotateZMatrix;
varying vec2 vTextureCoord;
void main(void){
gl_Position = uPMatrix * uRotateZMatrix * uRotateYMatrix * uRotateXMatrix *uTranslateMatrix * uScaleMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
void main(void) {
gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
}
</script>
<script>
var op = function op(){}
op.intCanvas = function(id) {
var canvas = document.getElementById(id)
if(!canvas) {
alert('Could not intialise Canvas, sorry :-(")')
}
op.canvas = canvas
}
op.intGL = function(canvas) {
if(!canvas){
canvas = op.canvas
}
try {
var gl = canvas.getContext("experimental-webgl")
gl.viewportWidth = canvas.width
gl.viewportHeight = canvas.height
op.gl = gl
} catch(e) {
}
if(!gl) {
alert('Could not intialise WebGL, sorry :-(")')
}
}
op.intShader = function(){
op.gl.vertexShader = op.getShader('vertex-shader')
op.gl.fragmentShader = op.getShader('fragment-shader')
}
op.getShader = function (scriptId) {
try {
if(!op.gl) {
throw new Error('找不到WebGL对象。');
}
var gl = op.gl
var shaderScript = document.getElementById(scriptId)
if( ! shaderScript) {
throw new Error('找不到着色器代码。');
}
var str = ''
const TEXT_NODE = 3
k = shaderScript.firstChild;
while(k) {
if(k.nodeType == TEXT_NODE) {
str += k.textContent
}
k = k.nextSibling;
}
var shader, shaderType;
if(shaderScript.type == "x-shader/x-fragment") {
shaderType = gl.FRAGMENT_SHADER
} else if( shaderScript.type == "x-shader/x-vertex") {
shaderType = gl.VERTEX_SHADER
} else {
throw new Error('着色器类型有误。');
}
shader = gl.createShader(shaderType);
gl.shaderSource(shader, str)
gl.compileShader(shader);
if(! gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
throw new Error('着色器编译出现问题:' + gl.getShaderInfoLog(shader));
}
} catch(e) {
alert('[Error]' + e)
}
return shader;
}
op.intProgram = function(){
var gl = op.gl
var fragmentShader = gl.fragmentShader
var vertexShader = gl.vertexShader
var program = gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
gl.linkProgram(program)
if(! gl.getProgramParameter(program, gl.LINK_STATUS) ) {
alert("Could not initialise shaders");
}
gl.useProgram(program)
gl.program = program
program.vertexPositionAttribute = gl.getAttribLocation(program, 'aVertexPosition');
gl.enableVertexAttribArray(program.vertexPositionAttribute)
program.pMatrixUniform = gl.getUniformLocation(program, 'uPMatrix')
program.uRotateXMatrixUniform = gl.getUniformLocation(program, 'uRotateXMatrix');
program.uRotateYMatrixUniform = gl.getUniformLocation(program, 'uRotateYMatrix');
program.uRotateZMatrixUniform = gl.getUniformLocation(program, 'uRotateZMatrix');
program.uScaleMatrixUniform = gl.getUniformLocation(program, 'uScaleMatrix');
program.uTranslateMatrixUniform = gl.getUniformLocation(program, 'uTranslateMatrix');
program.textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord");
gl.enableVertexAttribArray(program.textureCoordAttribute);
program.samplerUniform = gl.getUniformLocation(program, 'uSampler')
}
op.setBuffer = function(bufferName, bufferData, isIndexBuffer, itemSize){
var gl = op.gl
var buffer = gl.createBuffer()
gl[bufferName] = buffer
if(isIndexBuffer) {
var BUFFER_TYPE = gl.ELEMENT_ARRAY_BUFFER
} else {
var BUFFER_TYPE = gl.ARRAY_BUFFER
}
gl.bindBuffer(BUFFER_TYPE, buffer)
gl.bufferData(BUFFER_TYPE, bufferData, gl.STATIC_DRAW)
gl.bindBuffer(BUFFER_TYPE, null)
buffer.itemSize = itemSize
buffer.numItem = bufferData.length/itemSize
buffer.bufferType = BUFFER_TYPE
return buffer
}
op.intBuffer = function(setCallback){
setCallback()
}
op.projection = function(angle, a, zMin, zMax) {
var ang = Math.tan((angle*.5)*Math.PI/180);
var matrix = new Float32Array([
0.5/ang, 0 , 0, 0,
0, 0.5*a/ang, 0, 0,
0, 0, -(zMax+zMin)/(zMax-zMin), -1,
0, 0, (-2*zMax*zMin)/(zMax-zMin), 0
]);
op.pMatrix = matrix
}
var matrixobj = function(){
this.translateMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
this.scaleMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
this.rotateYMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
this.rotateXMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
this.rotateZMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
}
matrixobj.prototype.translate = function(x,y,z){
this.translateMatrix[12]+=x
this.translateMatrix[13]+=y
this.translateMatrix[14]+=z
}
matrixobj.prototype.translateRelative = function(x,y,z){
glmatrix = new matrixobj
glmatrix.translate(x,y,z)
this.translateMatrix = multiply([], this.translateMatrix, glmatrix.translateMatrix)
}
matrixobj.prototype.scale = function(scale){
var matrix = new Float32Array([
scale, 0, 0, 0,
0, scale, 0,0,
0,0,scale,0,
0,0,0,1
])
this.scaleMatrix = matrix
}
matrixobj.prototype.rotateX = function(deg){
var rad, mcos, msin;
rad=deg*Math.PI/180
msin=Math.sin(rad)
mcos=Math.cos(rad)
var matrix = new Float32Array([
1, 0,0,0,
0, mcos,msin,0,
0, -msin, mcos, 0,
0,0,0,1
])
this.rotateXMatrix = matrix
}
matrixobj.prototype.rotateY = function(deg){
var rad, mcos, msin;
rad=deg*Math.PI/180
mcos=Math.cos(rad)
msin=Math.sin(rad)
var matrix = new Float32Array([
mcos, 0, -msin, 0,
0, 1, 0, 0,
msin, 0 , mcos, 0,
0, 0, 0, 1
])
this.rotateYMatrix = matrix
}
matrixobj.prototype.rotateZ = function(deg){
var rad, mcos, msin;
rad=deg*Math.PI/180
mcos=Math.cos(rad)
msin=Math.sin(rad)
var matrix = new Float32Array([
mcos, msin,0,0,
-msin, mcos,0,0,
0, 0 , 1, 0,
0,0,0,1
])
this.rotateZMatrix = matrix
}
function multiply(out, a, b) {
let a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
let a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
let a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
let a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
// Cache only the current line of the second matrix
let b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
return out;
}
op.setPMVMatrixUniformToProgram = function(mobj){
var gl = op.gl
var program = gl.program
if(!op.pMatrix) {
var angle = 45
op.projection(angle, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);
}
/*
if(!op.translateMatrix) {
op.translateMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
}
if(!op.scaleMatrix) {
op.scaleMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
}
if(!op.rotateYMatrix) {
op.rotateYMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
}
if(!op.rotateXMatrix) {
op.rotateXMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
}
if(!op.rotateZMatrix) {
op.rotateZMatrix = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
])
}
*/
gl.uniformMatrix4fv(program.pMatrixUniform, false, op.pMatrix)
gl.uniformMatrix4fv(program.uRotateZMatrixUniform, false, mobj.rotateZMatrix)
gl.uniformMatrix4fv(program.uRotateXMatrixUniform, false, mobj.rotateXMatrix)
gl.uniformMatrix4fv(program.uRotateYMatrixUniform, false, mobj.rotateYMatrix)
gl.uniformMatrix4fv(program.uScaleMatrixUniform, false, mobj.scaleMatrix)
gl.uniformMatrix4fv(program.uTranslateMatrixUniform, false, mobj.translateMatrix)
}
op.setBufferAttribToProgram = function(buffer, attribute, isTexture = false, texture){
var gl = op.gl
var program = gl.program
gl.bindBuffer(buffer.bufferType, buffer)
gl.vertexAttribPointer(attribute, buffer.itemSize, gl.FLOAT, false, 0, 0)
if(isTexture) {
gl.activeTexture(gl.TEXTURE0)
gl.bindTexture(gl.TEXTURE_2D, texture)
gl.uniform1i(program.samplerUniform, 0)
}
}
op.handleLoadedTexture = function(texture){
var gl = op.gl
gl.bindTexture(gl.TEXTURE_2D, texture)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
gl.bindTexture(gl.TEXTURE_2D, null)
}
op.createTexture = function(src){
var gl = op.gl
var texture = gl.createTexture()
texture.image = new Image()
texture.image.onload = function(){
op.handleLoadedTexture(texture)
}
texture.image.src = src
return texture
}
var trans_x=0
var trans_y=0
var trans_z=0
var lastTime = 0;
mobj = new matrixobj
console.log(mobj)
var objx = 0
var objxt = false;
var objz = 0
var objzt = false;
op.drawScene = function(){
var gl = op.gl
var program = gl.program
if(gl.worldVertexTextureCoordBuffer == null || ! gl.worldVertexPositionBuffer == null) {
return
}
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
var angle = 90
op.projection(angle, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);
mobj = new matrixobj
mobj.translate(-xPos, -0.4, -zPos);
mobj.rotateY(-yaw)
op.setBufferAttribToProgram(gl.worldVertexTextureCoordBuffer, program.textureCoordAttribute, true,op.mtexture)
op.setBufferAttribToProgram(gl.worldVertexPositionBuffer, program.vertexPositionAttribute)
op.setPMVMatrixUniformToProgram(mobj)
gl.drawArrays(gl.TRIANGLES, 0, gl.worldVertexPositionBuffer.numItems);
mobj2 = new matrixobj
mobj2.translate(-xPos, -0.1, -zPos);
mobj2.rotateY(-yaw)
mobj2.scale(0.1)
if(objx>2) {
objxt = true
}
if(objx<0) {
objxt = false
}
if(!objxt) {
objx+=0.01;
} else {
objx-=0.01;
}
mobj2.translateRelative(objx,0,0)
op.setPMVMatrixUniformToProgram(mobj2)
op.setBufferAttribToProgram(gl.squareVertexTextureCoordBuffer, program.textureCoordAttribute, true,op.nehetexture)
op.setBufferAttribToProgram(gl.squareVertexPositionBuffer, program.vertexPositionAttribute)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.squareVertexIndexBuffer)
gl.drawElements(gl.TRIANGLES, gl.squareVertexIndexBuffer.numItem, gl.UNSIGNED_SHORT, 0)
mobj3 = new matrixobj
mobj3.translate(-xPos, -0.1, -zPos);
mobj3.rotateY(-yaw)
mobj3.scale(0.1)
if(objz>2) {
objzt = true
}
if(objz<0) {
objzt = false
}
if(!objxt) {
objz+=0.01;
} else {
objz-=0.01;
}
mobj3.translateRelative(0,0,objz)
op.setPMVMatrixUniformToProgram(mobj3)
op.setBufferAttribToProgram(gl.squareVertexTextureCoordBuffer, program.textureCoordAttribute, true,op.nehetexture)
op.setBufferAttribToProgram(gl.squareVertexPositionBuffer, program.vertexPositionAttribute)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.squareVertexIndexBuffer)
gl.drawElements(gl.TRIANGLES, gl.squareVertexIndexBuffer.numItem, gl.UNSIGNED_SHORT, 0)
mobj_self = new matrixobj
mobj_self.translate(0, -0.2, -0.2);
//mobj_self.rotateZ(10)
mobj_self.rotateX(10)
mobj_self.scale(0.1)
//mobj_self.translateRelative(0,0,objz)
op.setPMVMatrixUniformToProgram(mobj_self)
op.setBufferAttribToProgram(gl.squareVertexTextureCoordBuffer, program.textureCoordAttribute, true,op.nehetexture)
op.setBufferAttribToProgram(gl.squareVertexPositionBuffer, program.vertexPositionAttribute)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.squareVertexIndexBuffer)
gl.drawElements(gl.TRIANGLES, gl.squareVertexIndexBuffer.numItem, gl.UNSIGNED_SHORT, 0)
}
</script>
</head>
<body>
<canvas id="my_Canvas" width="500" height="500" ></canvas>
<script>
var clearColor = [1.0, 1.0, 1.0, 1.0];
var setBuffers = function(){
op.setBuffer('squareVertexPositionBuffer', new Float32Array([
-1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1,
-1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1,
-1,-1,-1, -1, 1,-1, -1, 1, 1, -1,-1, 1,
1,-1,-1, 1, 1,-1, 1, 1, 1, 1,-1, 1,
-1,-1,-1, -1,-1, 1, 1,-1, 1, 1,-1,-1,
-1, 1,-1, -1, 1, 1, 1, 1, 1, 1, 1,-1,
]), false, 3)
op.setBuffer('squareVertexIndexBuffer', new Uint16Array([
0,1,2, 0,2,3, 4,5,6, 4,6,7,
8,9,10, 8,10,11, 12,13,14, 12,14,15,
16,17,18, 16,18,19, 20,21,22, 20,22,23
]), true, 1)
op.setBuffer('squareVertexTextureCoordBuffer', new Float32Array([
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
0.0, 0.0,
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
]), false, 2)
}
op.loadWorld = function(){
//引用自hiwebgl.com的world.txt文件
op.handleLoadedWorld(`
NUMPOLLIES 36
// Floor 1
-3.0 0.0 -3.0 0.0 6.0
-3.0 0.0 3.0 0.0 0.0
3.0 0.0 3.0 6.0 0.0
-3.0 0.0 -3.0 0.0 6.0
3.0 0.0 -3.0 6.0 6.0
3.0 0.0 3.0 6.0 0.0
// Ceiling 1
-3.0 1.0 -3.0 0.0 6.0
-3.0 1.0 3.0 0.0 0.0
3.0 1.0 3.0 6.0 0.0
-3.0 1.0 -3.0 0.0 6.0
3.0 1.0 -3.0 6.0 6.0
3.0 1.0 3.0 6.0 0.0
// A1
-2.0 1.0 -2.0 0.0 1.0
-2.0 0.0 -2.0 0.0 0.0
-0.5 0.0 -2.0 1.5 0.0
-2.0 1.0 -2.0 0.0 1.0
-0.5 1.0 -2.0 1.5 1.0
-0.5 0.0 -2.0 1.5 0.0
// A2
2.0 1.0 -2.0 2.0 1.0
2.0 0.0 -2.0 2.0 0.0
0.5 0.0 -2.0 0.5 0.0
2.0 1.0 -2.0 2.0 1.0
0.5 1.0 -2.0 0.5 1.0
0.5 0.0 -2.0 0.5 0.0
// B1
-2.0 1.0 2.0 2.0 1.0
-2.0 0.0 2.0 2.0 0.0
-0.5 0.0 2.0 0.5 0.0
-2.0 1.0 2.0 2.0 1.0
-0.5 1.0 2.0 0.5 1.0
-0.5 0.0 2.0 0.5 0.0
// B2
2.0 1.0 2.0 2.0 1.0
2.0 0.0 2.0 2.0 0.0
0.5 0.0 2.0 0.5 0.0
2.0 1.0 2.0 2.0 1.0
0.5 1.0 2.0 0.5 1.0
0.5 0.0 2.0 0.5 0.0
// C1
-2.0 1.0 -2.0 0.0 1.0
-2.0 0.0 -2.0 0.0 0.0
-2.0 0.0 -0.5 1.5 0.0
-2.0 1.0 -2.0 0.0 1.0
-2.0 1.0 -0.5 1.5 1.0
-2.0 0.0 -0.5 1.5 0.0
// C2
-2.0 1.0 2.0 2.0 1.0
-2.0 0.0 2.0 2.0 0.0
-2.0 0.0 0.5 0.5 0.0
-2.0 1.0 2.0 2.0 1.0
-2.0 1.0 0.5 0.5 1.0
-2.0 0.0 0.5 0.5 0.0
// D1
2.0 1.0 -2.0 0.0 1.0
2.0 0.0 -2.0 0.0 0.0
2.0 0.0 -0.5 1.5 0.0
2.0 1.0 -2.0 0.0 1.0
2.0 1.0 -0.5 1.5 1.0
2.0 0.0 -0.5 1.5 0.0
// D2
2.0 1.0 2.0 2.0 1.0
2.0 0.0 2.0 2.0 0.0
2.0 0.0 0.5 0.5 0.0
2.0 1.0 2.0 2.0 1.0
2.0 1.0 0.5 0.5 1.0
2.0 0.0 0.5 0.5 0.0
// Upper hallway - L
-0.5 1.0 -3.0 0.0 1.0
-0.5 0.0 -3.0 0.0 0.0
-0.5 0.0 -2.0 1.0 0.0
-0.5 1.0 -3.0 0.0 1.0
-0.5 1.0 -2.0 1.0 1.0
-0.5 0.0 -2.0 1.0 0.0
// Upper hallway - R
0.5 1.0 -3.0 0.0 1.0
0.5 0.0 -3.0 0.0 0.0
0.5 0.0 -2.0 1.0 0.0
0.5 1.0 -3.0 0.0 1.0
0.5 1.0 -2.0 1.0 1.0
0.5 0.0 -2.0 1.0 0.0
// Lower hallway - L
-0.5 1.0 3.0 0.0 1.0
-0.5 0.0 3.0 0.0 0.0
-0.5 0.0 2.0 1.0 0.0
-0.5 1.0 3.0 0.0 1.0
-0.5 1.0 2.0 1.0 1.0
-0.5 0.0 2.0 1.0 0.0
// Lower hallway - R
0.5 1.0 3.0 0.0 1.0
0.5 0.0 3.0 0.0 0.0
0.5 0.0 2.0 1.0 0.0
0.5 1.0 3.0 0.0 1.0
0.5 1.0 2.0 1.0 1.0
0.5 0.0 2.0 1.0 0.0
// Left hallway - Lw
-3.0 1.0 0.5 1.0 1.0
-3.0 0.0 0.5 1.0 0.0
-2.0 0.0 0.5 0.0 0.0
-3.0 1.0 0.5 1.0 1.0
-2.0 1.0 0.5 0.0 1.0
-2.0 0.0 0.5 0.0 0.0
// Left hallway - Hi
-3.0 1.0 -0.5 1.0 1.0
-3.0 0.0 -0.5 1.0 0.0
-2.0 0.0 -0.5 0.0 0.0
-3.0 1.0 -0.5 1.0 1.0
-2.0 1.0 -0.5 0.0 1.0
-2.0 0.0 -0.5 0.0 0.0
// Right hallway - Lw
3.0 1.0 0.5 1.0 1.0
3.0 0.0 0.5 1.0 0.0
2.0 0.0 0.5 0.0 0.0
3.0 1.0 0.5 1.0 1.0
2.0 1.0 0.5 0.0 1.0
2.0 0.0 0.5 0.0 0.0
// Right hallway - Hi
3.0 1.0 -0.5 1.0 1.0
3.0 0.0 -0.5 1.0 0.0
2.0 0.0 -0.5 0.0 0.0
3.0 1.0 -0.5 1.0 1.0
2.0 1.0 -0.5 0.0 1.0
2.0 0.0 -0.5 0.0 0.0
`)
/*
var request = new XMLHttpRequest();
request.open("GET", "world.txt");
request.onreadystatechange = function () {
if (request.readyState == 4) {
op.handleLoadedWorld(request.responseText);
}
}
request.send();*/
}
op.handleLoadedWorld = function (data) {
var worldVertexPositionBuffer = null;
var worldVertexTextureCoordBuffer = null;
var gl = op.gl
var lines = data.split("\n");
var vertexCount = 0;
var vertexPositions = [];
var vertexTextureCoords = [];
for (var i in lines) {
var vals = lines[i].replace(/^\s+/, "").split(/\s+/);
if (vals.length == 5 && vals[0] != "//") {
// It is a line describing a vertex; get X, Y and Z first
vertexPositions.push(parseFloat(vals[0]));
vertexPositions.push(parseFloat(vals[1]));
vertexPositions.push(parseFloat(vals[2]));
// And then the texture coords
vertexTextureCoords.push(parseFloat(vals[3]));
vertexTextureCoords.push(parseFloat(vals[4]));
vertexCount += 1;
}
}
worldVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositions), gl.STATIC_DRAW);
worldVertexPositionBuffer.itemSize = 3;
worldVertexPositionBuffer.numItems = vertexCount;
worldVertexPositionBuffer.bufferType = gl.ARRAY_BUFFER
worldVertexTextureCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, worldVertexTextureCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexTextureCoords), gl.STATIC_DRAW);
worldVertexTextureCoordBuffer.itemSize = 2;
worldVertexTextureCoordBuffer.numItems = vertexCount;
worldVertexTextureCoordBuffer.bufferType = gl.ARRAY_BUFFER
gl.worldVertexTextureCoordBuffer = worldVertexTextureCoordBuffer
gl.worldVertexPositionBuffer = worldVertexPositionBuffer
}
op.intCanvas('my_Canvas')
op.intGL()
op.intShader()
op.intProgram()
op.intBuffer(setBuffers)
//引用自hiwebgl.com的纹理
textimgdata = "data:image/gif;base64,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"
op.nehetexture = op.createTexture(textimgdata)
op.mtexture = op.createTexture(textimgdata)
op.loadWorld()
op.gl.clearColor(...clearColor)
op.gl.enable(op.gl.DEPTH_TEST)
var speed = 0
var yawRate = 0
var yaw = 0;
var xPos = 0;
var yPos = 0.4;
var zPos = 0;
op.handleUserOp = function(){
if(key_sw['ArrowUp']) {
speed= 0.1
}
else if(key_sw['ArrowDown']) {
speed= -0.1
} else {
speed = 0
}
if(key_sw['ArrowLeft']) {
yawRate = 0.1;
mov_x_length+=2;
}else if(key_sw['ArrowRight']) {
yawRate = -0.1;
mov_x_length-=2;
} else {
yawRate = 0
}
if(key_sw['PageUp']) {
trans_y+=0.05;
}
if(key_sw['PageDown']) {
trans_y-=0.05;
}
}
var xjd=0,yjd=0,zjd=0
var moving = false
var mov_x_length = 0
var mov_y_length = 0
var page_x=0;
var page_y=0;
document.onmousedown = function(e){
moving = true
page_x = e.x
page_y = e.y
}
document.onmouseup = function(e) {
moving = false
}
document.onmousemove = function(e) {
if(moving) {
mov_x_length+=page_x-e.x
mov_y_length+=page_y-e.y
page_x = e.x
page_y = e.y
}
}
var key_sw = []
var zoom=0;
document.onkeydown = function(e) {
key_sw[e.key] = true
}
document.onkeyup = function(e) {
key_sw[e.key] = false
}
var lastTime = 0;
animate = function(){
canvas = op.canvas
gl = op.gl
gl.viewportWidth = canvas.width = innerWidth
gl.viewportHeight = canvas.height = innerHeight
op.handleUserOp()
op.drawScene()
var timeNow = new Date().getTime();
if (lastTime != 0) {
var elapsed = timeNow - lastTime;
if (speed != 0) { //是否前进/后退(平移z,需要重新计算model x,y ,用当前x减去 移动过的比值)
xPos-= Math.sin(yaw * Math.PI/180) * speed * 1;
zPos-= Math.cos(yaw * Math.PI/180) * speed * 1;
//joggingAngle += elapsed * 0.6; // 0.6 "fiddle factor" - makes it feel more realistic :-)
//yPos = Math.sin(degToRad(joggingAngle)) / 20 + 0.4
}
yaw += yawRate * 5;
//console.log('yaw',yaw)
}
lastTime = timeNow;
window.requestAnimationFrame(animate)
}
animate()
</script>
</body>
</html>