"use strict"; // 參考 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode //////////////////////////////////////////////////////////////////////////////// // 貼圖動畫 //////////////////////////////////////////////////////////////////////////////// var camera, scene, renderer; var cameraControls, effectController; var clock = new THREE.Clock(); var uX = 1; var uY = 1; var uU = 1; var uV = 1; var texture = []; var material = []; var mtlName = 'grid'; var wireMaterial; var wrapName = 'repeat'; var wrapVal = THREE.RepeatWrapping; var gui; var showPoly = false; function fillScene() { scene = new THREE.Scene(); // 背景格線與軸,格線單位 1,軸交叉在 (0, 0) Coordinates.drawGrid({size:100,scale:1,orientation:"z",offset:-0.01}); Coordinates.drawAxes({axisLength:2.1,axisOrientation:"x",axisRadius:0.004,offset:-0.01}); Coordinates.drawAxes({axisLength:2.1,axisOrientation:"y",axisRadius:0.004,offset:-0.01}); var myPolygon = new SquareGeometry(); var polygonObject = new THREE.Mesh( myPolygon, material[mtlName] ); scene.add(polygonObject); if ( effectController.showPoly ) { polygonObject = new THREE.Mesh( myPolygon, wireMaterial ); scene.add(polygonObject); } } function setWrap() { for (var name in texture) { if (texture.hasOwnProperty(name)) { texture[name].wrapS = wrapVal; texture[name].wrapT = wrapVal; // 如果你改變了 Wrap Mode,你要知會貼圖發生改變 texture[name].needsUpdate = true; } } } function SquareGeometry() { var geo = new THREE.Geometry(); // 產生頂點 geo.vertices.push( new THREE.Vector3( 0.0, 0.0, 0.0 ) ); geo.vertices.push( new THREE.Vector3( uX, 0.0, 0.0 ) ); geo.vertices.push( new THREE.Vector3( uX, uY, 0.0 ) ); geo.vertices.push( new THREE.Vector3( 0.0, uY, 0.0 ) ); var uvs = []; uvs.push( new THREE.Vector2( 0.0, 0.0 ) ); uvs.push( new THREE.Vector2( uU, 0.0 ) ); uvs.push( new THREE.Vector2( uU, uV ) ); uvs.push( new THREE.Vector2( 0.0, uV ) ); // 產生面 geo.faces.push( new THREE.Face3( 0, 1, 2 ) ); geo.faceVertexUvs[ 0 ].push( [ uvs[0], uvs[1], uvs[2] ] ); geo.faces.push( new THREE.Face3( 0, 2, 3 ) ); geo.faceVertexUvs[ 0 ].push( [ uvs[0], uvs[2], uvs[3] ] ); // 完成:回傳 return geo; } function init() { canvasWidth = window.innerWidth; canvasHeight = window.innerHeight; var canvasRatio = canvasWidth/canvasHeight; // RENDERER renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.gammaInput = true; renderer.gammaOutput = true; renderer.setSize(canvasWidth, canvasHeight); renderer.setClearColorHex( 0xFFFFFF, 1.0 ); // 攝影機:Y 上、X 右、Z 上 camera = new THREE.PerspectiveCamera( 1, canvasRatio, 10, 200 ); camera.position.set( 0.75, 0.5, 100 ); // 控制 cameraControls = new THREE.OrbitAndPanControls(camera, renderer.domElement); cameraControls.target.set(0.75,0.5,0); wireMaterial = new THREE.MeshBasicMaterial( { wireframe: true, color: 0x00FF00 } ); // 貼圖 texture.crate = THREE.ImageUtils.loadTexture( '/cs291/texture/crate.gif' ); texture.grid = THREE.ImageUtils.loadTexture( '/cs291/texture/ash_uvgrid01.jpg'); //texture['maple'] = THREE.ImageUtils.loadTexture( '/cs291/texture/maple.png' ); //texture['feather'] = THREE.ImageUtils.loadTexture( '/cs291/texture/feather.png' ); texture.water = THREE.ImageUtils.loadTexture( '/cs291/texture/water.jpg' ); texture.concrete = THREE.ImageUtils.loadTexture( '/cs291/texture/concrete.jpg' ); texture.letterR = THREE.ImageUtils.loadTexture( '/cs291/texture/r_border.png' ); // 材質 for (var name in texture) { if (texture.hasOwnProperty(name)) { material[name] = new THREE.MeshBasicMaterial( { map: texture[name], side:THREE.DoubleSide } ); } } setWrap(); fillScene(); } function animate() { window.requestAnimationFrame(animate); render(); } function render() { var delta = clock.getDelta(); cameraControls.update(delta); if ( effectController.reset ) { resetGui(); // 遍歷所有控制 for (var i in gui.__controllers) { if (gui.__controllers.hasOwnProperty(i)) { gui.__controllers[i].updateDisplay(); } } } var refill = false; if ( wrapName !== effectController.wrap ) { wrapName = effectController.wrap; refill = true; if ( effectController.wrap === 'repeat' ) { wrapVal = THREE.RepeatWrapping; } else if ( effectController.wrap === 'mirrored repeat' ) { wrapVal = THREE.MirroredRepeatWrapping; } else { wrapVal = THREE.ClampToEdgeWrapping; } setWrap(); } if ( refill || showPoly !== effectController.showPoly || mtlName !== effectController.mtlName ) { showPoly = effectController.showPoly; mtlName = effectController.mtlName; fillScene(); } texture[effectController.mtlName].repeat.set( effectController.repeat, effectController.repeat ); // 學生作業: // 變換貼圖座標使貼圖以每秒幾張圖往下流動 renderer.render(scene, camera); } function resetGui() { effectController = { wrap: 'repeat', repeat: 3, showPoly: false, mtlName: 'water', reset: false }; } function addToDOM() { var container = document.getElementById('container'); var canvas = container.getElementsByTagName('canvas'); if (canvas.length>0) { container.removeChild(canvas[0]); } container.appendChild( renderer.domElement ); } function setupGui() { resetGui(); gui = new dat.GUI(); gui.add( effectController, "wrap", ['repeat', 'mirrored repeat', 'clamp to edge'] ).name("Wrap Mode"); gui.add( effectController, "repeat", 0.0, 10.0 ).name("貼圖重複"); gui.add( effectController, "showPoly" ).name("顯示多面體"); gui.add( effectController, "mtlName", ['crate','grid','water','concrete','letterR'] ).name("貼圖影像"); gui.add( effectController, "reset" ).name("重置"); } document.addEventListener("DOMContentLoaded", function () { try { setupGui(); init(); fillScene(); addToDOM(); animate(); } catch(e) { var errorReport = "你的程式遇到不可復原的錯誤,無法繪製 Canvas。錯誤是:<br/><br/>"; $('#container').append(errorReport+e); } })