diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..6f1987fbf03d4fc1b6e2aada03bcd18c3bf7b2c9 --- /dev/null +++ b/README.md @@ -0,0 +1,193 @@ +# WebGL Transform Tutorial + +WebGL에서 transform을 이용할 때 좌표계가 어떻게 변화하는지 확인할 수 있는 예제입니다. + + + +(CC-NC-BY) Haeram Kim 2019 + + + +### Features + +- Three transform functions: translate, rotate, scale +- View matrix setting +- Logging transforms and model matrix +- Reset cube position and logs +- Some animation for fun + + + +### APIs + +- WebGL: version 1.0 +- [gl-matrix: version 3.0.0](<https://github.com/toji/gl-matrix/tree/master/dist>) + + + + + +## Structure Details + +### Vertexes + +- Vertex Attribute: 3 attributes(총 9차원): + XYZ coordinates(3), RGBA(4), Texture XY coordinates(2) +- 총 72개 vertex 사용: + XYZ plane(3 planes * 4 vertexes), arrows(6 arrows * 6 vertexes), cube(6 planes * 4 vertexes) +- array structure [here](./vertex.js) + + + +### Texture + + + +- 64px * 64px png file, 좌/하단 1px굵기의 검은 직선 외에 투명 +- XYZ plane에만 사용되어, 32번 반복해 격자 무늬를 만듬 +- [Base64 Image Encoder](<https://www.base64-image.de/>)로 png파일을 base64로 encode해 html파일 내에 hard coding + +``` +const GRID = "data:image/png;base64,/*...*/" +``` + +- 기타 image loading, mipmapping 처리 과정 등은 4차 과제 제출물 [facecube/WebGLHelloAPI.js](<http://git.ajou.ac.kr/ajouramram/facecube>)와 같습니다. + + + +### View matrix + +- gl-matrix.mat4.lookAt() function 사용 + +```js +var view_eye = [5,5,5]; + +// ...in function renderScene() +mat4.lookAt(view_matrix,view_eye,[0,0,0],[0,0,-1]); +``` + +- WebGL의 view matrix 기본값은 `view_eye=[0,0,0]`이고 `up=[0,1,0]`이지만, + view_eye는 HTML input element를 이용해 조정하도록 하였고 +익숙한 xyz좌표계와 비슷한 시점을 구현하기 위해 `up=[0,0,-1]`으로 설정 + + +```HTML +<--- HTML ---> +eye_matrix of View matrix: +<input id="viewX" type="range" min="3" max="7" step="1" value="5"> +<input id="viewY" type="range" min="3" max="7" step="1" value="5"> +<input id="viewZ" type="range" min="3" max="7" step="1" value="5"> +[x,y,z]=[<span id="viewtext">5,5,5</span>] +``` + +```js +// javascript +var viewX = document.getElementById("viewX"); +var viewY = document.getElementById("viewY"); +var viewZ = document.getElementById("viewZ"); +var viewtext = document.getElementById("viewtext"); + +viewX.oninput = () => { view_eye[0] = viewX.value; viewtext.innerHTML = view_eye; }; +viewY.oninput = () => { view_eye[1] = viewY.value; viewtext.innerHTML = view_eye; }; +viewZ.oninput = () => { view_eye[2] = viewZ.value; viewtext.innerHTML = view_eye; }; +``` + + + +### Model Matrix + +- XYZ planes model matrix: 4*4 identity matrix 사용 +- Arrows: HTML button element를 이용해 조작된 transform이 적용(상단 snapshot 참고) + transform은 gl-matrix.mat4 library 내의 function을 사용 + +```HTML +<-- HTML --> +<button onclick="scale(true)">Scale *1.50</button> +<button onclick="scale(false)">Scale *0.67</button><br> +<button class="x" onclick="translateX(0.5)">TranslateX +0.5</button> +<button class="x" onclick="translateX(1.0)">TranslateX +1.0</button> +<button class="y" onclick="translateY(0.5)">TranslateY +0.5</button> +<button class="y" onclick="translateY(1.0)">TranslateY +1.0</button> +<button class="z" onclick="translateZ(0.5)">TranslateZ +0.5</button> +<button class="z" onclick="translateZ(1.0)">TranslateZ +1.0</button><br> +<button class="x" onclick="translateX(-0.5)">TranslateX -0.5</button> +<button class="x" onclick="translateX(-1.0)">TranslateX -1.0</button> +<button class="y" onclick="translateY(-0.5)">TranslateY -0.5</button> +<button class="y" onclick="translateY(-1.0)">TranslateY -1.0</button> +<button class="z" onclick="translateZ(-0.5)">TranslateZ -0.5</button> +<button class="z" onclick="translateZ(-1.0)">TranslateZ -1.0</button><br><button class="x" onclick="rotateX(true)">RotateX +30deg</button> +<button class="y" onclick="rotateY(true)">RotateY +30deg</button> +<button class="z" onclick="rotateZ(true)">RotateZ +30deg</button><br> +<button class="x" onclick="rotateX(false)">RotateX -30deg</button> +<button class="y" onclick="rotateY(false)">RotateY -30deg</button> +<button class="z" onclick="rotateZ(false)">RotateZ -30deg</button><br> +``` + +```js +// js +var mov_matrix = mat4.create(); +const DEG30 = 30*Math.PI/180; +mat4.fromTranslation(mov_matrix,[1,1,1]); + +function translateX(d){ mat4.translate(mov_matrix,mov_matrix,[d,0,0]); } +function translateY(d){ mat4.translate(mov_matrix,mov_matrix,[0,d,0]); } +function translateZ(d){ mat4.translate(mov_matrix,mov_matrix,[0,0,d]); } +function rotateX(p){ mat4.rotateX(mov_matrix,mov_matrix,(p? DEG30:-DEG30)); } +function rotateY(p){ mat4.rotateY(mov_matrix,mov_matrix,(p? DEG30:-DEG30)); } +function rotateZ(p){ mat4.rotateZ(mov_matrix,mov_matrix,(p? DEG30:-DEG30)); } +function scale(p){ mat4.scale(mov_matrix,mov_matrix,(p? [1.5,1.5,1.5]:[0.67,0.67,0.67])); } +``` + +- Cube: arrow와 같은 model matrix에, 박동하는 듯한 animation 효과를 덧씌워 적용 + +```js +var animstatus = true; +var animvalue = 0; + +// ...in function renderScene() +if(animstatus){ + var t = 1 + ((Math.cos(animvalue)+1)/2)*0.05; + gl.uniformMatrix4fv(LocMmatrix, gl.FALSE, mat4.scale(mat4.create(),mov_matrix,[t,t,t])); + if (!testGLError("gl.vertexAttribPointer")) { return false; } + animvalue += 0.1; +} +``` + + + +### Logging + +- Arrow의 model matrix의 특정 값들을 이용해 cube의 center position과 delta를 표시해 + transform에 따라 model matrix가 어떻게 계산되는지 확인 +- center position: + +```js +var pos = [mov_matrix[12],mov_matrix[13],mov_matrix[14]].map(i => i.toFixed(2)); +``` + +- delta: + +```js +var dx = [mov_matrix[0],mov_matrix[1],mov_matrix[2]].map(i => i.toFixed(2)); +var dy = [mov_matrix[4],mov_matrix[5],mov_matrix[6]].map(i => i.toFixed(2)); +var dz = [mov_matrix[8],mov_matrix[9],mov_matrix[10]].map(i => i.toFixed(2)); +``` + +- css를 적용해 transform에 따라 어떤 값이 바뀌었는지 시각적으로 확인시켜줌 + + + +### Others + +- Fragment/vertex shader codes: [here](./shader.js) +- Depth test: Less than or equal to(LEQUAL) 적용 + Stencil, Blending 미적용 +- Projection matrix: gl-matrix.mat4.perspective() function 사용 + +```js +// POV: 180 degree, aspect ratio: 1.0, z-near: 1, z-far: 15 +mat4.perspective(proj_matrix,180,1,1,15); +``` + +- 설명을 위해 첨부한 [vertex.js](./vertex.js)와 [shader.js](./shader.js)는 [index.html](./index.html)과 연결되어 있지 않으므로 유의 +- 기타 상세 내역은 실제 code([index.html](./index.html)) 참조 \ No newline at end of file diff --git a/blob/ss.png b/blob/ss.png index 7ebe7c31de8fb946c5dcf9e67e5dd35a33b4b566..d348847b3ff8087b859c601e98b85440a03dd692 100644 Binary files a/blob/ss.png and b/blob/ss.png differ diff --git a/index.html b/index.html index 7fce10393a00ef162bd7b704e985cebbd8c35123..b5c45bfedb14253d6d62570631b39a3e744078a1 100644 --- a/index.html +++ b/index.html @@ -4,14 +4,18 @@ <meta charset="UTF-8"> <title>WebGL Transform Tutorial</title> <style> + div{ + position: relative; + } div.log{ - position: absolute; top: 0; right: 0; width: 512px; height:100%; background-color: rgba(127,127,127,0.1); + position: fixed; + top: 0; + right: 0; + height: 100%; + overflow: scroll; } - div.control{ - position: fixed; top: 0; width: 100%; background-color: white; - } - div{ - float: left; + button, table{ + font-family: "consolas"; } button.x{ background-color: rgba(255, 128, 128, 1.0); @@ -30,6 +34,9 @@ table, tr, td{ border: 1px solid black; } + td.changed{ + background-color: rgba(255, 255, 128, 0.5); + } </style> <script src="./gl-matrix-min.js"></script> <script> @@ -85,99 +92,97 @@ function initialiseBuffer() { gl.generateMipmap(gl.TEXTURE_2D); }); - /* vertex attribute: coord XYZ, color RGBA, texcoord XY - x/y/z plane coordinate: - 1+---+3 - | \ | - 0+---+2 - using TRIANGLES_STRIP method */ + // vertex attribute: coord XYZ, color RGBA, texcoord XY var vertexData = [ - 0.0, 0.0, 0.0, 1.0, 0.66, 0.66, 0.33, 0, 0, // x-plane vertex 0 - 0.0, 0.0, 10.0, 1.0, 0.66, 0.66, 0.33, 0, 32, // x-plane vertex 1 - 0.0, 10.0, 0.0, 1.0, 0.66, 0.66, 0.33, 32, 0, // x-plane vertex 2 - 0.0, 10.0, 10.0, 1.0, 0.66, 0.66, 0.33, 32, 32, // x-plane vertex 3 - - 0.0, 0.0, 0.0, 0.66, 1.0, 0.66, 0.33, 0, 0, // y-plane vertex 0 - 0.0, 0.0, 10.0, 0.66, 1.0, 0.66, 0.33, 0, 32, // y-plane vertex 1 - 10.0, 0.0, 0.0, 0.66, 1.0, 0.66, 0.33, 32, 0, // y-plane vertex 2 - 10.0, 0.0, 10.0, 0.66, 1.0, 0.66, 0.33, 32, 32, // y-plane vertex 3 - - 0.0, 0.0, 0.0, 0.66, 0.66, 1.0, 0.33, 0, 0, // z-plane vertex 0 - 0.0, 10.0, 0.0, 0.66, 0.66, 1.0, 0.33, 0, 32, // z-plane vertex 1 - 10.0, 0.0, 0.0, 0.66, 0.66, 1.0, 0.33, 32, 0, // z-plane vertex 2 - 10.0, 10.0, 0.0, 0.66, 0.66, 1.0, 0.33, 32, 32, // z-plane vertex 3 - - // box vertex - -0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0,//3 - 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0,//1 - 0.5, 0.5, -0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0,//2 - - -0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0,//3 - 0.5, 0.5, -0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0,//2 - -0.5, 0.5, -0.5, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0,//4 - - 0.5, 0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,//2 - 0.5, -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,//6 - -0.5,-0.5,-0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,//8 - - -0.5, 0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,//4 - 0.5, 0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,//2 - -0.5,-0.5,-0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,//8 - - 0.5, -0.5, 0.5, 1.0, 0.5, 0.0, 1.0, 0.0, 0.0,//5 - 0.5, -0.5, -0.5, 1.0, 0.5, 0.0, 1.0, 0.0, 0.0,//6 - 0.5, 0.5, -0.5, 1.0, 0.5, 0.0, 1.0, 0.0, 0.0,//2 - - 0.5, -0.5, 0.5, 1.0, 0.5, 0.0, 1.0, 0.0, 0.0,//5 - 0.5, 0.5, -0.5, 1.0, 0.5, 0.0, 1.0, 0.0, 0.0,//2 - 0.5, 0.5, 0.5, 1.0, 0.5, 0.0, 1.0, 0.0, 0.0,//1 - - -0.5, 0.5, -0.5, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,//4 - -0.5,-0.5, -0.5, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,//8 - -0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,//7 - - -0.5, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,//3 - -0.5, 0.5, -0.5, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,//4 - -0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0,//7 - - -0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0,//7 - 0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0,//5 - 0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0,//1 - - -0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0,//7 - 0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0,//1 - -0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0,//3 - - 0.5, -0.5, -0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,//6 - 0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,//5 - -0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,//7 - - -0.5,-0.5, -0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,//8 - 0.5, -0.5, -0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,//6 - -0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,//7 - - // box axis vertex - -2.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // x-line 0 - 2.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // x-line 1 + // XYZ plane coordinate: using TRIANGLES_STRIP method + 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.5, 0, 0, // x-plane vertex 0 + 0.0, 0.0, 10.0, 0.5, 0.0, 0.0, 0.5, 0, 32, // x-plane vertex 1 + 0.0, 10.0, 0.0, 0.5, 0.0, 0.0, 0.5, 32, 0, // x-plane vertex 2 + 0.0, 10.0, 10.0, 0.5, 0.0, 0.0, 0.5, 32, 32, // x-plane vertex 3 + + 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0, 0, // y-plane vertex 0 + 0.0, 0.0, 10.0, 0.0, 0.5, 0.0, 0.5, 0, 32, // y-plane vertex 1 + 10.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 32, 0, // y-plane vertex 2 + 10.0, 0.0, 10.0, 0.0, 0.5, 0.0, 0.5, 32, 32, // y-plane vertex 3 + + 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0, 0, // z-plane vertex 0 + 0.0, 10.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0, 32, // z-plane vertex 1 + 10.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 32, 0, // z-plane vertex 2 + 10.0, 10.0, 0.0, 0.0, 0.0, 0.5, 0.5, 32, 32, // z-plane vertex 3 + + // arrows: using TRIANGLES method + 2.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 1.5, 0.33, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 1.5, -0.33, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 2.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 1.66, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 1.66, -0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, // +x - 0.0, -2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, // y-line 0 - 0.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, // y-line 1 + 0.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, 1.5, 0.33, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, 1.5, -0.33, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, 1.66, 0.5, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, 1.66, -0.5, 0.0, 1.0, 0.0, 1.0, 0, 0, // +y - 0.0, 0.0, -2.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, // z-line 0 - 0.0, 0.0, 2.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, // z-line 1 + 0.0, 0.0, 2.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.33, 0.0, 1.5, 0.0, 0.0, 1.0, 1.0, 0, 0, + -0.33, 0.0, 1.5, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, 0.0, 2.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.5, 0.0, 1.66, 0.0, 0.0, 1.0, 1.0, 0, 0, + -0.5, 0.0, 1.66, 0.0, 0.0, 1.0, 1.0, 0, 0, // +z + + -1.5, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + -2.0, 0.0, 0.33, 1.0, 0.0, 0.0, 1.0, 0, 0, + -2.0, 0.0, -0.33, 1.0, 0.0, 0.0, 1.0, 0, 0, + -1.5, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + -1.88, 0.0, 0.5, 1.0, 0.0, 0.0, 1.0, 0, 0, + -1.88, 0.0, -0.5, 1.0, 0.0, 0.0, 1.0, 0, 0, // -x - // arrow head triangle - 2.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // x-head 0 - 1.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // x-head 1 - 1.5, -0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // x-head 2 + 0.0, -1.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.33, -2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + -0.33, -2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, -1.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.5, -1.88, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + -0.5, -1.88, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, // -y - 0.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, // y-head 0 - 0.0, 1.5, 0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, // y-head 1 - 0.0, 1.5, -0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, // y-head 2 - - 0.0, 0.0, 2.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, // z-head 0 - 0.5, 0.0, 1.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, // z-head 1 - -0.5, 0.0, 1.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, // z-head 2 + 0.0, 0.0, -1.5, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, 0.33, -2.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, -0.33, -2.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, 0.0, -1.5, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, 0.5, -1.88, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, -0.5, -1.88, 0.0, 0.0, 1.0, 1.0, 0, 0, // -z + + // cube: using TRIANGLE_STRIP method + 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0, 0, // +x + + -1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0, 0, // +y + + -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0, 0, // +z + + -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, + -1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + -1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + -1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, // -x + + -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, + 1.0, -1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + -1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, // -y + + -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, + 1.0, -1.0, -1.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + -1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, // -z ]; // Generate a buffer object @@ -202,21 +207,21 @@ function initialiseShaders() { gl.fragShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(gl.fragShader, fragmentShaderSource); gl.compileShader(gl.fragShader); - var vertexShaderSource = '\ - attribute highp vec3 myVertex; \ - attribute highp vec4 myColor; \ - attribute highp vec2 myUV; \ - uniform mediump mat4 Pmatrix; \ - uniform mediump mat4 Vmatrix; \ - uniform mediump mat4 Mmatrix; \ - varying mediump vec4 color; \ - varying mediump vec2 texCoord;\ - void main(void) \ - { \ - gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(myVertex, 1.0);\ - color = myColor; \ - texCoord = myUV; \ - }'; + var vertexShaderSource = '\ + attribute highp vec3 myVertex; \ + attribute highp vec4 myColor; \ + attribute highp vec2 myUV; \ + uniform mediump mat4 Pmatrix; \ + uniform mediump mat4 Vmatrix; \ + uniform mediump mat4 Mmatrix; \ + varying mediump vec4 color; \ + varying mediump vec2 texCoord;\ + void main(void) \ + { \ + gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(myVertex, 1.0);\ + color = myColor; \ + texCoord = myUV; \ + }'; // Create the vertex shader object gl.vertexShader = gl.createShader(gl.VERTEX_SHADER); @@ -263,54 +268,63 @@ function initialiseShaders() { var proj_matrix = mat4.create(); var mov_matrix = mat4.create(); var view_matrix = mat4.create(); -var view_eye = [4,4,4]; +var view_eye = [5,5,5]; var animvalue = 0; var animstatus = true; -var seqtext, seqpos; +var logtable; var viewX, viewY, viewZ, viewtext; const DEG30 = 30*Math.PI/180; -mat4.perspective(proj_matrix,180,1,0,10); +mat4.perspective(proj_matrix,180,1,1,15); +mat4.fromTranslation(mov_matrix,[1,1,1]); function reset(){ - mov_matrix = mat4.create(); - view_eye = [4,4,4]; - viewX.value = 4; viewY.value = 4; viewZ.value = 4; + mat4.fromTranslation(mov_matrix,[1,1,1]); + view_eye = [5,5,5]; + viewX.value = 5; viewY.value = 5; viewZ.value = 5; - seqtext.innerHTML="/* initial state */"; - seqpos.innerHTML="0.00,0.00,0.00"; - viewtext.innerHTML = "4,4,4"; + logtable.innerHTML = TABLE; + viewtext.innerHTML = "5,5,5"; } -function boxRotation(){ animvalue = 0; animstatus = !animstatus; } -function translateX(){ mat4.translate(mov_matrix,mov_matrix,[1,0,0]); updateLog("translate([1,0,0]);"); } -function translateY(){ mat4.translate(mov_matrix,mov_matrix,[0,1,0]); updateLog("translate([0,1,0]);"); } -function translateZ(){ mat4.translate(mov_matrix,mov_matrix,[0,0,1]); updateLog("translate([0,0,1]);"); } -function translateMinusX(){ mat4.translate(mov_matrix,mov_matrix,[-1,0,0]); updateLog("translate([-1,0,0]);"); } -function translateMinusY(){ mat4.translate(mov_matrix,mov_matrix,[0,-1,0]); updateLog("translate([0,-1,0]);"); } -function translateMinusZ(){ mat4.translate(mov_matrix,mov_matrix,[0,0,-1]); updateLog("translate([0,0,-1]);"); } -function rotateX(){ mat4.rotateX(mov_matrix,mov_matrix,DEG30); updateLog("rotateX(30deg);"); } -function rotateY(){ mat4.rotateY(mov_matrix,mov_matrix,DEG30); updateLog("rotateY(30deg);"); } -function rotateZ(){ mat4.rotateZ(mov_matrix,mov_matrix,DEG30); updateLog("rotateZ(30deg);"); } -function rotateMinusX(){ mat4.rotateX(mov_matrix,mov_matrix,-DEG30); updateLog("rotateX(-30deg);"); } -function rotateMinusY(){ mat4.rotateY(mov_matrix,mov_matrix,-DEG30); updateLog("rotateY(-30deg);"); } -function rotateMinusZ(){ mat4.rotateZ(mov_matrix,mov_matrix,-DEG30); updateLog("rotateY(-30deg);"); } -function scaleUp(){ mat4.scale(mov_matrix,mov_matrix,[1.33,1.33,1.33]); updateLog("scale(1.33);"); } -function scaleDown(){ mat4.scale(mov_matrix,mov_matrix,[0.75,0.75,0.75]); updateLog("scale(0.75);"); } -function updateLog(t){ +function boxAnimation(){ animvalue = 0; animstatus = !animstatus; } +function translateX(d){ mat4.translate(mov_matrix,mov_matrix,[d,0,0]); updateLog("translate(["+d+",0,0]);", 0); } +function translateY(d){ mat4.translate(mov_matrix,mov_matrix,[0,d,0]); updateLog("translate([0,"+d+",0]);", 0); } +function translateZ(d){ mat4.translate(mov_matrix,mov_matrix,[0,0,d]); updateLog("translate([0,0,"+d+"]);", 0); } +function rotateX(p){ mat4.rotateX(mov_matrix,mov_matrix,(p? DEG30:-DEG30)); updateLog("rotateX("+(p?"30deg);":"-30deg);"), 1); } +function rotateY(p){ mat4.rotateY(mov_matrix,mov_matrix,(p? DEG30:-DEG30)); updateLog("rotateY("+(p?"30deg);":"-30deg);"), 2); } +function rotateZ(p){ mat4.rotateZ(mov_matrix,mov_matrix,(p? DEG30:-DEG30)); updateLog("rotateZ("+(p?"30deg);":"-30deg);"), 3); } +function scale(p){ mat4.scale(mov_matrix,mov_matrix,(p? [1.5,1.5,1.5]:[0.67,0.67,0.67])); updateLog("scale("+(p?"1.5);":"0.67);"), 4); } +function updateLog(seq, type){ var pos = [mov_matrix[12],mov_matrix[13],mov_matrix[14]].map(i => i.toFixed(2)); - seqtext.innerHTML += "<br>"+t; - seqpos.innerHTML += "<br>"+pos; + var dx = [mov_matrix[0],mov_matrix[1],mov_matrix[2]].map(i => i.toFixed(2)); + var dy = [mov_matrix[4],mov_matrix[5],mov_matrix[6]].map(i => i.toFixed(2)); + var dz = [mov_matrix[8],mov_matrix[9],mov_matrix[10]].map(i => i.toFixed(2)); + + // type 0: translate, 123: XYZ rotate, 4: scale + switch(type){ + case 0: + logtable.innerHTML += "<tr><td rowspan=\"3\">"+seq+"</td><td rowspan=\"3\" class=\"changed\">"+pos+"</td><td>dx="+dx+"</td></tr><tr><td>dy="+dy+"</td></tr><tr><td>dz="+dz+"</td></tr>"; + break; + case 1: + logtable.innerHTML += "<tr><td rowspan=\"3\">"+seq+"</td><td rowspan=\"3\">"+pos+"</td><td>dx="+dx+"</td></tr><tr><td class=\"changed\">dy="+dy+"</td></tr><tr><td class=\"changed\">dz="+dz+"</td></tr>"; + break; + case 2: + logtable.innerHTML += "<tr><td rowspan=\"3\">"+seq+"</td><td rowspan=\"3\">"+pos+"</td><td class=\"changed\">dx="+dx+"</td></tr><tr><td>dy="+dy+"</td></tr><tr><td class=\"changed\">dz="+dz+"</td></tr>"; + break; + case 3: + logtable.innerHTML += "<tr><td rowspan=\"3\">"+seq+"</td><td rowspan=\"3\">"+pos+"</td><td class=\"changed\">dx="+dx+"</td></tr><tr><td class=\"changed\">dy="+dy+"</td></tr><tr><td>dz="+dz+"</td></tr>"; + break; + case 4: + logtable.innerHTML += "<tr><td rowspan=\"3\">"+seq+"</td><td rowspan=\"3\">"+pos+"</td><td class=\"changed\">dx="+dx+"</td></tr><tr><td class=\"changed\">dy="+dy+"</td></tr><tr><td class=\"changed\">dz="+dz+"</td></tr>"; + break; + default: + logtable.innerHTML += "<tr><td rowspan=\"3\">"+seq+"</td><td rowspan=\"3\">"+pos+"</td><td>dx="+dx+"</td></tr><tr><td>dy="+dy+"</td></tr><tr><td>dz="+dz+"</td></tr>"; + } } function renderScene() { gl.enable(gl.DEPTH_TEST); gl.depthFunc(gl.LEQUAL); - gl.enable(gl.BLEND); - gl.blendFunc(gl.SRC_ALPHA, gl.DST_ALPHA); - gl.blendEquation(gl.FUNC_ADD); - - gl.clearColor(0,0,0,1); - gl.clear(gl.COLOR_BUFFER_BIT); mat4.lookAt(view_matrix,view_eye,[0,0,0],[0,0,-1]); var LocPmatrix = gl.getUniformLocation(gl.programObject, "Pmatrix"); @@ -334,34 +348,43 @@ function renderScene() { return false; } - gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); // x-plane - gl.drawArrays(gl.TRIANGLE_STRIP, 4, 4); // y-plane - gl.drawArrays(gl.TRIANGLE_STRIP, 8, 4); // z-plane + var vertexnum = 0; + var vertexcount; + + // draw XYZ planes + vertexcount = 4; + for(var i=0; i<3; i++){gl.drawArrays(gl.TRIANGLE_STRIP, vertexnum, vertexcount); vertexnum += vertexcount;} gl.uniformMatrix4fv(LocMmatrix, gl.FALSE, mov_matrix); if (!testGLError("gl.vertexAttribPointer")) { return false; } - gl.drawArrays(gl.LINES, 48, 6); // box lines - gl.drawArrays(gl.TRIANGLES, 54, 9); // line arrow heads + // draw arrows + vertexcount = 36; + gl.drawArrays(gl.TRIANGLES, vertexnum, vertexcount); // arrows + vertexnum += vertexcount; + + // animation if(animstatus){ - var t = 1 + ((Math.cos(animvalue)+1)/2)*0.1; + var t = 1 + ((Math.cos(animvalue)+1)/2)*0.05; gl.uniformMatrix4fv(LocMmatrix, gl.FALSE, mat4.scale(mat4.create(),mov_matrix,[t,t,t])); if (!testGLError("gl.vertexAttribPointer")) { return false; } animvalue += 0.1; } - gl.drawArrays(gl.TRIANGLES, 12, 36); // box + + // draw cube + vertexcount = 4; + for(var i=0; i<6; i++){gl.drawArrays(gl.TRIANGLE_STRIP, vertexnum, vertexcount); vertexnum += vertexcount;} return true; } function main() { var canvas = document.getElementById("helloapicanvas"); - seqtext = document.getElementById("seqtext"); - seqpos = document.getElementById("seqpos"); + logtable = document.getElementById("logtable"); viewX = document.getElementById("viewX"); viewY = document.getElementById("viewY"); viewZ = document.getElementById("viewZ"); @@ -402,54 +425,54 @@ function main() { } const GRID = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AYht+m1YpUHSwo4pChOlkQFXGUKhbBQmkrtOpgcumP0KQhSXFxFFwLDv4sVh1cnHV1cBUEwR8QF1cnRRcp8buk0CLGO457eO97X+6+A4R6malmYBxQNctIxWNiNrciBl/RiV6aAQxIzNQT6YUMPMfXPXx8v4vyLO+6P0ePkjcZ4BOJZ5luWMTrxNObls55nzjMSpJCfE48ZtAFiR+5Lrv8xrnosMAzw0YmNUccJhaLbSy3MSsZKvEUcURRNcoXsi4rnLc4q+Uqa96TvzCU15bTXKc1jDgWkUASImRUsYEyLERp10gxkaLzmId/yPEnySWTawOMHPOoQIXk+MH/4HdvzcLkhJsUigEdL7b9MQIEd4FGzba/j227cQL4n4ErreWv1IGZT9JrLS1yBPRtAxfXLU3eAy53gMEnXTIkR/LTEgoF4P2MvikH9N8C3atu35rnOH0AMtSrpRvg4BAYLVL2mse7u9r79m9Ns38/IDZyhkj0bq0AAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfjBg4OCxdZIjAZAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAGdJREFUeNrt2zEBACAMwLCCf8/DB0sl5G/VtLjb8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgi07L9/kHC4UCfLVgYpkAAAAASUVORK5CYII="; +const TABLE = "<tr><td>Sequence</td><td>Position</td><td>Delta</td></tr><tr><td rowspan=\"3\">/* initial state */</td><td rowspan=\"3\">1.00,1.00,1.00</td><td>dx=1.00,0.00,0.00</td></tr><tr><td>dy=0.00,1.00,0.00</td></tr><tr><td>dz=0.00,0.00,1.00</td></tr>"; </script> </head> <body onload="main()"> - <div class="control"> + <div> + <div> <h2>WebGL Transform Tutorial</h2> + <p><canvas id="helloapicanvas" style="border: none;" width="500" height="500"></canvas></p> <p> <button onclick="reset()">Reset</button> - <button onclick="boxRotation()">Animation</button><br> - <button class="x" onclick="translateX()">TranslateX +1.0</button> - <button class="y" onclick="translateY()">TranslateY +1.0</button> - <button class="z" onclick="translateZ()">TranslateZ +1.0</button> - <button class="x" onclick="rotateX()">RotateX +30deg</button> - <button class="y" onclick="rotateY()">RotateY +30deg</button> - <button class="z" onclick="rotateZ()">RotateZ +30deg</button> - <button onclick="scaleUp()">Scale *1.33</button><br> - <button class="x" onclick="translateMinusX()">TranslateX -1.0</button> - <button class="y" onclick="translateMinusY()">TranslateY -1.0</button> - <button class="z" onclick="translateMinusZ()">TranslateZ -1.0</button> - <button class="x" onclick="rotateMinusX()">RotateX -30deg</button> - <button class="y" onclick="rotateMinusY()">RotateY -30deg</button> - <button class="z" onclick="rotateMinusZ()">RotateZ -30deg</button> - <button onclick="scaleDown()">Scale *0.75</button><br> - eye_matrix of View matrix: - <input id="viewX" type="range" min="1" max="6" step="0.1" value="4"> - <input id="viewY" type="range" min="1" max="6" step="0.1" value="4"> - <input id="viewZ" type="range" min="1" max="6" step="0.1" value="4">[x,y,z]=[<span id="viewtext">4,4,4</span>] - </p> - <p> (CC-NC-BY) 2019 Haeram Kim </p> - <div> - <canvas id="helloapicanvas" style="border: none;" width="500" height="500"></canvas> - </div> - <div><p>Red plane: x-plane, Red arrow: x-axis - <br>Green plane: y-plane, Green arrow: y-axis - <br>Blue plnae: z-plane, Blue arrow: z-axis</p> - <p>TranslateX: cube move with <b>red</b> arrow direction - <br>TranslateY: cube move with <b>green</b> arrow direction - <br>TranslateZ: cube move with <b>blue</b> arrow direction - <br>RotateX: cube rotate with <b>red</b> arrow axis anti-clockwise - <br>RotateY: cube rotate with <b>green</b> arrow axis anti-clockwise - <br>RotateZ: cube rotate with <b>blue</b> arrow axis anti-clockwise - <br>Scale: scale up/down cube size - <br>(will also scaling arrow size, which means will also scaling translate power)</p> + <button onclick="boxAnimation()">Animation</button> + <button onclick="scale(true)">Scale *1.50</button> + <button onclick="scale(false)">Scale *0.67</button><br> + <button class="x" onclick="translateX(0.5)">TranslateX +0.5</button><button class="x" onclick="translateX(1.0)">TranslateX +1.0</button> + <button class="y" onclick="translateY(0.5)">TranslateY +0.5</button><button class="y" onclick="translateY(1.0)">TranslateY +1.0</button> + <button class="z" onclick="translateZ(0.5)">TranslateZ +0.5</button><button class="z" onclick="translateZ(1.0)">TranslateZ +1.0</button><br> + <button class="x" onclick="translateX(-0.5)">TranslateX -0.5</button><button class="x" onclick="translateX(-1.0)">TranslateX -1.0</button> + <button class="y" onclick="translateY(-0.5)">TranslateY -0.5</button><button class="y" onclick="translateY(-1.0)">TranslateY -1.0</button> + <button class="z" onclick="translateZ(-0.5)">TranslateZ -0.5</button><button class="z" onclick="translateZ(-1.0)">TranslateZ -1.0</button><br> + <button class="x" onclick="rotateX(true)">RotateX +30deg</button> + <button class="y" onclick="rotateY(true)">RotateY +30deg</button> + <button class="z" onclick="rotateZ(true)">RotateZ +30deg</button><br> + <button class="x" onclick="rotateX(false)">RotateX -30deg</button> + <button class="y" onclick="rotateY(false)">RotateY -30deg</button> + <button class="z" onclick="rotateZ(false)">RotateZ -30deg</button><br> + eye_matrix: + <input id="viewX" type="range" min="3" max="7" step="1" value="5"> + <input id="viewY" type="range" min="3" max="7" step="1" value="5"> + <input id="viewZ" type="range" min="3" max="7" step="1" value="5">[x,y,z]=[<span id="viewtext">5,5,5</span>] + </p> + <p>Red plane: x-plane, Red arrow: dx + <br>Green plane: y-plane, Green arrow: dy + <br>Blue plnae: z-plane, Blue arrow: dz</p> + <p>TranslateX: cube move with <b>red</b> arrow direction(with dx) + <br>TranslateY: cube move with <b>green</b> arrow direction(with dy) + <br>TranslateZ: cube move with <b>blue</b> arrow direction(with dz) + <br>RotateX: cube rotate with <b>red</b> arrow axis anti-clockwise(changing dy,dz) + <br>RotateY: cube rotate with <b>green</b> arrow axis anti-clockwise(changing dz,dx) + <br>RotateZ: cube rotate with <b>blue</b> arrow axis anti-clockwise(changing dx,dy) + <br>Scale: scale up/down cube size(changing dx,dy,dz)</p> <p>Notice that position will be change whether do the same transforms but in difference sequences.</p> + <p>(CC-NC-BY) 2019 Haeram Kim</p> </div> <div class="log"> Log: - <table> - <tr><td>Sequence<td>Position</tr> - <tr><td id="seqtext">/* initial state */<td id="seqpos">0.00,0.00,0.00</tr> + <table id="logtable"> + <tr><td>Sequence</td><td>Position</td><td>Delta</td></tr> + <tr><td rowspan="3">/* initial state */</td><td rowspan="3">1.00,1.00,1.00</td> + <td>dx=1.00,0.00,0.00</td></tr><tr><td>dy=0.00,1.00,0.00</td></tr><tr><td>dz=0.00,0.00,1.00</td></tr> </table> </div> </div> diff --git a/shader.js b/shader.js new file mode 100644 index 0000000000000000000000000000000000000000..4888d00787e7f204b3385b7a9011afa1311b78a3 --- /dev/null +++ b/shader.js @@ -0,0 +1,23 @@ +var fragmentShaderSource = '\ + varying mediump vec4 color; \ + varying mediump vec2 texCoord;\ + uniform sampler2D sampler2d; \ + void main(void) \ + { \ + gl_FragColor = color + texture2D(sampler2d, texCoord); \ + }'; +var vertexShaderSource = '\ + attribute highp vec3 myVertex; \ + attribute highp vec4 myColor; \ + attribute highp vec2 myUV; \ + uniform mediump mat4 Pmatrix; \ + uniform mediump mat4 Vmatrix; \ + uniform mediump mat4 Mmatrix; \ + varying mediump vec4 color; \ + varying mediump vec2 texCoord;\ + void main(void) \ + { \ + gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(myVertex, 1.0);\ + color = myColor; \ + texCoord = myUV; \ + }'; \ No newline at end of file diff --git a/vertex.js b/vertex.js new file mode 100644 index 0000000000000000000000000000000000000000..194ffa59a906ea5ef25b2910ab6083659027acf1 --- /dev/null +++ b/vertex.js @@ -0,0 +1,91 @@ +var vertexData = [ + // XYZ plane coordinate: using TRIANGLES_STRIP method + 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.5, 0, 0, // x-plane vertex 0 + 0.0, 0.0, 10.0, 0.5, 0.0, 0.0, 0.5, 0, 32, // x-plane vertex 1 + 0.0, 10.0, 0.0, 0.5, 0.0, 0.0, 0.5, 32, 0, // x-plane vertex 2 + 0.0, 10.0, 10.0, 0.5, 0.0, 0.0, 0.5, 32, 32, // x-plane vertex 3 + + 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0, 0, // y-plane vertex 0 + 0.0, 0.0, 10.0, 0.0, 0.5, 0.0, 0.5, 0, 32, // y-plane vertex 1 + 10.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 32, 0, // y-plane vertex 2 + 10.0, 0.0, 10.0, 0.0, 0.5, 0.0, 0.5, 32, 32, // y-plane vertex 3 + + 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0, 0, // z-plane vertex 0 + 0.0, 10.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0, 32, // z-plane vertex 1 + 10.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 32, 0, // z-plane vertex 2 + 10.0, 10.0, 0.0, 0.0, 0.0, 0.5, 0.5, 32, 32, // z-plane vertex 3 + + // arrows: using TRIANGLES method + 2.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 1.5, 0.33, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 1.5, -0.33, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 2.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 1.66, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 1.66, -0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, // +x + + 0.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, 1.5, 0.33, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, 1.5, -0.33, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, 1.66, 0.5, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, 1.66, -0.5, 0.0, 1.0, 0.0, 1.0, 0, 0, // +y + + 0.0, 0.0, 2.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.33, 0.0, 1.5, 0.0, 0.0, 1.0, 1.0, 0, 0, + -0.33, 0.0, 1.5, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, 0.0, 2.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.5, 0.0, 1.66, 0.0, 0.0, 1.0, 1.0, 0, 0, + -0.5, 0.0, 1.66, 0.0, 0.0, 1.0, 1.0, 0, 0, // +z + + -1.5, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + -2.0, 0.0, 0.33, 1.0, 0.0, 0.0, 1.0, 0, 0, + -2.0, 0.0, -0.33, 1.0, 0.0, 0.0, 1.0, 0, 0, + -1.5, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + -1.88, 0.0, 0.5, 1.0, 0.0, 0.0, 1.0, 0, 0, + -1.88, 0.0, -0.5, 1.0, 0.0, 0.0, 1.0, 0, 0, // -x + + 0.0, -1.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.33, -2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + -0.33, -2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.0, -1.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 0.5, -1.88, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + -0.5, -1.88, 0.0, 0.0, 1.0, 0.0, 1.0, 0, 0, // -y + + 0.0, 0.0, -1.5, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, 0.33, -2.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, -0.33, -2.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, 0.0, -1.5, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, 0.5, -1.88, 0.0, 0.0, 1.0, 1.0, 0, 0, + 0.0, -0.5, -1.88, 0.0, 0.0, 1.0, 1.0, 0, 0, // -z + + // cube: using TRIANGLE_STRIP method + 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0, 0, // +x + + -1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0, 0, // +y + + -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, + 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0, 0, // +z + + -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, + -1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + -1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0, 0, + -1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, // -x + + -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, + 1.0, -1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + -1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0, 0, + 1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, // -y + + -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, + 1.0, -1.0, -1.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + -1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 1.0, 0, 0, + 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0, 0, // -z +]; \ No newline at end of file