From 5291b4e6c027a47513c3a549433dc11c4ee4903d Mon Sep 17 00:00:00 2001 From: pyjong1999 <pyjong1999@gmail.com> Date: Wed, 5 Jun 2024 14:16:43 +0900 Subject: [PATCH] save --- example/project.html | 49 +++++- example/project.js | 363 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 344 insertions(+), 68 deletions(-) diff --git a/example/project.html b/example/project.html index 7bebbb3..fe0da32 100644 --- a/example/project.html +++ b/example/project.html @@ -4,23 +4,50 @@ <script id="vertex-shader" type="x-shader/x-vertex"> attribute vec4 vPosition; +attribute vec4 vColor; uniform mat4 modelViewMatrix; uniform mat4 projectionMatrix; +varying vec4 fColor; + +attribute vec3 vNormal; +uniform vec4 ambientProduct, diffuseProduct, specularProduct; +uniform vec4 lightPosition; +uniform float shininess; void main() { + vec3 pos = -(modelViewMatrix * vPosition).xyz; + vec3 light = lightPosition.xyz; + + vec3 L = normalize(light - pos); + vec3 E = normalize(-pos); + vec3 H = normalize(L + E); + + vec4 NN = vec4(vNormal, 0); + + vec3 N = normalize((modelViewMatrix*NN).xyz); + vec4 ambient = ambientProduct; + + float d_val = max( dot(L, N), 0.0); + vec4 diffuse = d_val * diffuseProduct; + + float s_val = pow( max(dot(N, H), 0.0), shininess); + vec4 specular = s_val * specularProduct; + gl_Position = projectionMatrix * modelViewMatrix * vPosition; + fColor = (ambient + diffuse + specular)*vColor; } </script> <script id="fragment-shader" type="x-shader/x-fragment"> precision mediump float; +varying vec4 fColor; void main() { - gl_FragColor = vec4(0.3, 0.4, 0.5, 1.0); + gl_FragColor = fColor; } </script> @@ -32,13 +59,17 @@ void main() <script type="text/javascript" src="../Common/MV.js"></script> <script type="text/javascript" src="project.js"></script> +<button id="button1">greeting</button> + +<button id="button2">handshigh</button> + <div> torso angle -180 <input id="slider0" type="range" min="-180" max="180" step="10" value="0" /> 180 </div><br/> -<div> +<!-- <div> head2 angle -180 <input id="slider10" type="range" min="-180" max="180" step="10" value="0" /> @@ -100,6 +131,20 @@ right lower leg angle -180 <input id="slider9" type="range" min="-180" max="180" step="10" value="0" /> 180 +</div><br/> --> + +<div> +lightX -20 <input id="slider11" type="range" + min="-20" max="20" step="1" value="0" + /> + 20 +</div><br/> + +<div> +lightY -20 <input id="slider12" type="range" + min="-20" max="20" step="1" value="0" + /> + 20 </div><br/> diff --git a/example/project.js b/example/project.js index 78361d7..da8a8d9 100644 --- a/example/project.js +++ b/example/project.js @@ -22,6 +22,11 @@ var vertices = [ vec4( 0.5, -0.5, -0.5, 1.0 ) ]; +var lightposVector = [0.0, 50, 0.0]; +var xAxis = 0; +var yAxis = 1; +var zAxis = 2; + var torsoId = 0; var headId = 1; @@ -38,6 +43,7 @@ var rightLowerLegId = 9; var headUpperArmId = 10; var headLowerArmId = 11; var headArmHandId = 12; +var torsoBackLegId = 14; var torsoHeight = 8; @@ -55,15 +61,25 @@ var headWidth = 1.5; var headUpperArmHeight = 5.0; var headUpperArmWidth = 0.5; var headLowerArmHeight = 5.0; -var headLowerArmWidth = 0.5; +var headLowerArmWidth = 0.65; var headArmHandHeight = 1.0; -var headArmHandWidth = 0.5; +var headArmHandWidth = 0.8; var numNodes = 13; -var numAngles = 14; +var numAngles = 15; var angle = 0; -var theta = [0, 0, 210, -60, 210, -60, 210, -60, 210, -60, 30, 120, -60, 0]; +var posVec = [0, 0, 0]; +var theta = [0, 0, 210, -60, 210, -60, 210, -60, 210, -60, -60, 150, 0, 0, 0]; +var directionVec = [0, 0, 0]; + +function degreesToRadians(degrees) { + return degrees * (Math.PI / 180); +} + +function updatedirectionVec(){ + directionVec = [Math.sin(degreesToRadians(theta[torsoId])), 0, Math.cos(degreesToRadians(theta[torsoId]))] +} var numVertices = 24; @@ -77,6 +93,8 @@ var vBuffer; var modelViewLoc; var pointsArray = []; +var normalsArray = []; +var colorsArray = []; //------------------------------------------- @@ -109,8 +127,12 @@ function initNodes(Id) { switch(Id) { case torsoId: - - m = rotate(theta[torsoId], 0, 1, 0 ); + + m = translate(posVec[xAxis], posVec[yAxis], posVec[zAxis]); + m = mult(m, translate(0.0, 0, torsoHeight*0.4)); + m = mult(m, rotate(theta[torsoBackLegId], 1, 0, 0)); + m = mult(m, rotate(theta[torsoId], 0, 1, 0 )); + m = mult(m, translate(0.0, 0, -torsoHeight*0.4)); figure[torsoId] = createNode( m, torso, null, headId ); break; @@ -228,6 +250,7 @@ function torso() { instanceMatrix = mult(modelViewMatrix, translate(0.0, 0.5*torsoWidth, 0.0) ); instanceMatrix = mult(instanceMatrix, scale4( torsoWidth, torsoWidth, torsoHeight)); gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(instanceMatrix)); + cube(vec4(0.9, 0.9, 0.3, 1.0)); // 기존 색상 for(var i =0; i<6; i++) gl.drawArrays(gl.TRIANGLE_FAN, 4*i, 4); } @@ -236,6 +259,7 @@ function head() { instanceMatrix = mult(modelViewMatrix, translate(0.0, 0.5 * headHeight, 0.0 )); instanceMatrix = mult(instanceMatrix, scale4(headWidth, headHeight, headWidth) ); gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(instanceMatrix)); + cube(vec4(0.2, 0.2, 0.2, 1.0)); // 기존 색상 for(var i =0; i<6; i++) gl.drawArrays(gl.TRIANGLE_FAN, 4*i, 4); } @@ -268,6 +292,7 @@ function leftUpperArm() { instanceMatrix = mult(modelViewMatrix, translate(0.0, 0.5 * upperArmHeight, 0.0) ); instanceMatrix = mult(instanceMatrix, scale4(upperArmWidth, upperArmHeight, upperArmWidth) ); gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(instanceMatrix)); + cube(vec4(0.0, 1.0, 0.0, 1.0)); // 초록색 for(var i =0; i<6; i++) gl.drawArrays(gl.TRIANGLE_FAN, 4*i, 4); } @@ -276,6 +301,7 @@ function leftLowerArm() { instanceMatrix = mult(modelViewMatrix, translate(0.0, 0.5 * lowerArmHeight, 0.0) ); instanceMatrix = mult(instanceMatrix, scale4(lowerArmWidth, lowerArmHeight, lowerArmWidth) ); gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(instanceMatrix)); + cube(vec4(0.0, 1.0, 0.0, 1.0)); // 초록색 for(var i =0; i<6; i++) gl.drawArrays(gl.TRIANGLE_FAN, 4*i, 4); } @@ -327,22 +353,71 @@ function rightLowerLeg() { for(var i =0; i<6; i++) gl.drawArrays(gl.TRIANGLE_FAN, 4*i, 4); } -function quad(a, b, c, d) { +function quad(a, b, c, d, color) { + + var t1 = subtract(vertices[b], vertices[a]); + var t2 = subtract(vertices[c], vertices[b]); + var normal = cross(t1, t2); + var normal = vec3(normal); + pointsArray.push(vertices[a]); + colorsArray.push(color); + normalsArray.push(normal); pointsArray.push(vertices[b]); + colorsArray.push(color); + normalsArray.push(normal); pointsArray.push(vertices[c]); + colorsArray.push(color); + normalsArray.push(normal); pointsArray.push(vertices[d]); + colorsArray.push(color); + normalsArray.push(normal); + // pointsArray.push(vertices[a]); + // normalsArray.push(normal); + // pointsArray.push(vertices[c]); + // normalsArray.push(normal); + // pointsArray.push(vertices[d]); + // normalsArray.push(normal); } -function cube() +function cube(color) { - quad( 1, 0, 3, 2 ); - quad( 2, 3, 7, 6 ); - quad( 3, 0, 4, 7 ); - quad( 6, 5, 1, 2 ); - quad( 4, 5, 6, 7 ); - quad( 5, 4, 0, 1 ); + + pointsArray = []; + colorsArray = []; + normalsArray = []; + + quad( 1, 0, 3, 2, color); + quad( 2, 3, 7, 6, color); + quad( 3, 0, 4, 7, color); + quad( 6, 5, 1, 2, color); + quad( 4, 5, 6, 7, color); + quad( 5, 4, 0, 1, color); + + vBuffer = gl.createBuffer(); + gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer ); + gl.bufferData(gl.ARRAY_BUFFER, flatten(pointsArray), gl.STATIC_DRAW); + + var vPosition = gl.getAttribLocation( program, "vPosition" ); + gl.vertexAttribPointer( vPosition, 4, gl.FLOAT, false, 0, 0 ); + gl.enableVertexAttribArray( vPosition ); + + var cBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, cBuffer); + gl.bufferData(gl.ARRAY_BUFFER, flatten(colorsArray), gl.STATIC_DRAW); + + var vColor = gl.getAttribLocation(program, "vColor"); + gl.vertexAttribPointer(vColor, 4, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(vColor); + + var nBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, nBuffer); + gl.bufferData(gl.ARRAY_BUFFER, flatten(normalsArray), gl.STATIC_DRAW); + + var vNormal = gl.getAttribLocation(program, "vNormal"); + gl.vertexAttribPointer(vNormal, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(vNormal); } @@ -356,6 +431,10 @@ window.onload = function init() { gl.viewport( 0, 0, canvas.width, canvas.height ); gl.clearColor( 1.0, 1.0, 1.0, 1.0 ); + gl.enable(gl.CULL_FACE); + gl.cullFace(gl.BACK); + gl.enable(gl.DEPTH_TEST); + // // Load shaders and initialize attribute buffers // @@ -365,83 +444,235 @@ window.onload = function init() { instanceMatrix = mat4(); - projectionMatrix = ortho(-10.0,10.0,-10.0, 10.0,-10.0,10.0); - modelViewMatrix = mat4(); + // lightSource - gl.uniformMatrix4fv(gl.getUniformLocation( program, "modelViewMatrix"), false, flatten(modelViewMatrix) ); - gl.uniformMatrix4fv( gl.getUniformLocation( program, "projectionMatrix"), false, flatten(projectionMatrix) ); + var lightPosition = vec4(lightposVector[xAxis], lightposVector[yAxis], lightposVector[zAxis], 0.0); + var lightAmbient = vec4(0.2, 0.2, 0.2, 1.0); + var lightDiffuse = vec4(1.0, 1.0, 1.0, 1.0); + var lightSpecular = vec4(1.0, 1.0, 1.0, 1.0); - modelViewMatrixLoc = gl.getUniformLocation(program, "modelViewMatrix") + var materialAmbient = vec4(1.0, 0.0, 1.0, 1.0); + var materialDiffuse = vec4(1.0, 0.8, 0.0, 1.0); + var materialSpecular = vec4(1.0, 0.8, 0.0, 1.0); + var materialShininess = 100; - cube(); + var ambientProduct = mult(lightAmbient, materialAmbient); + var diffuseProduct = mult(lightDiffuse, materialDiffuse); + var specularProduct = mult(lightSpecular, materialSpecular); - vBuffer = gl.createBuffer(); + gl.uniform4fv(gl.getUniformLocation(program, "ambientProduct"), flatten(ambientProduct)); + gl.uniform4fv(gl.getUniformLocation(program, "diffuseProduct"), flatten(diffuseProduct)); + gl.uniform4fv(gl.getUniformLocation(program, "specularProduct"), flatten(specularProduct)); + gl.uniform4fv(gl.getUniformLocation(program, "lightPosition"), flatten(lightPosition)); - gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer ); - gl.bufferData(gl.ARRAY_BUFFER, flatten(pointsArray), gl.STATIC_DRAW); + gl.uniform1f(gl.getUniformLocation(program, "shininess"),materialShininess); - var vPosition = gl.getAttribLocation( program, "vPosition" ); - gl.vertexAttribPointer( vPosition, 4, gl.FLOAT, false, 0, 0 ); - gl.enableVertexAttribArray( vPosition ); + // ProjectionMatrix + var fovy = 60.0; + var aspect = canvas.width / canvas.height; + var near = 0.1; + var far = 100.0; + projectionMatrix = perspective(fovy, aspect, near, far); + // projectionMatrix = ortho(-10.0,10.0,-10.0, 10.0,-10.0,10.0); + + var eye = vec3(0, 10, 20); + var at = vec3(0, 0, 0); + var up = vec3(0, 1, 0); + modelViewMatrix = lookAt(eye, at, up); + //modelViewMatrix = mat4(); - document.getElementById("slider0").onchange = function(event) { - theta[torsoId ] = event.target.value; + + gl.uniformMatrix4fv(gl.getUniformLocation( program, "modelViewMatrix"), false, flatten(modelViewMatrix) ); + gl.uniformMatrix4fv( gl.getUniformLocation( program, "projectionMatrix"), false, flatten(projectionMatrix) ); + + modelViewMatrixLoc = gl.getUniformLocation(program, "modelViewMatrix") + + //cube(vec4(0.9, 0.3, 0.3, 1.0)); + + document.getElementById("slider0").onchange = function(event) { + theta[torsoId] = parseFloat(event.target.value); + console.log(event.target.value); + //theta[torsoId] = 50; initNodes(torsoId); + return; }; - document.getElementById("slider1").onchange = function(event) { - theta[head1Id] = event.target.value; - initNodes(head1Id); + // document.getElementById("slider1").onchange = function(event) { + // theta[head1Id] = event.target.value; + // initNodes(head1Id); + // }; + + // document.getElementById("slider2").onchange = function(event) { + // theta[leftUpperArmId] = event.target.value; + // initNodes(leftUpperArmId); + // }; + // document.getElementById("slider3").onchange = function(event) { + // theta[leftLowerArmId] = event.target.value; + // initNodes(leftLowerArmId); + // }; + + // document.getElementById("slider4").onchange = function(event) { + // theta[rightUpperArmId] = event.target.value; + // initNodes(rightUpperArmId); + // }; + // document.getElementById("slider5").onchange = function(event) { + // theta[rightLowerArmId] = event.target.value; + // initNodes(rightLowerArmId); + // }; + // document.getElementById("slider6").onchange = function(event) { + // theta[leftUpperLegId] = event.target.value; + // initNodes(leftUpperLegId); + // }; + // document.getElementById("slider7").onchange = function(event) { + // theta[leftLowerLegId] = event.target.value; + // initNodes(leftLowerLegId); + // }; + // document.getElementById("slider8").onchange = function(event) { + // theta[rightUpperLegId] = event.target.value; + // initNodes(rightUpperLegId); + // }; + // document.getElementById("slider9").onchange = function(event) { + // theta[rightLowerLegId] = event.target.value; + // initNodes(rightLowerLegId); + // }; + // document.getElementById("slider10").onchange = function(event) { + // theta[head2Id] = event.target.value; + // initNodes(head2Id); + // }; + + document.getElementById("slider11").onchange = function(event) { + lightposVector[xAxis] = event.target.value; + lightPosition = vec4(lightposVector[xAxis], lightposVector[yAxis], lightposVector[zAxis], 0.0); + gl.uniform4fv(gl.getUniformLocation(program, "lightPosition"), flatten(lightPosition)); }; - document.getElementById("slider2").onchange = function(event) { - theta[leftUpperArmId] = event.target.value; - initNodes(leftUpperArmId); - }; - document.getElementById("slider3").onchange = function(event) { - theta[leftLowerArmId] = event.target.value; - initNodes(leftLowerArmId); + document.getElementById("slider12").onchange = function(event) { + lightposVector[yAxis] = event.target.value; + lightPosition = vec4(lightposVector[xAxis], lightposVector[yAxis], lightposVector[zAxis], 0.0); + gl.uniform4fv(gl.getUniformLocation(program, "lightPosition"), flatten(lightPosition)); }; - document.getElementById("slider4").onchange = function(event) { - theta[rightUpperArmId] = event.target.value; - initNodes(rightUpperArmId); - }; - document.getElementById("slider5").onchange = function(event) { - theta[rightLowerArmId] = event.target.value; - initNodes(rightLowerArmId); - }; - document.getElementById("slider6").onchange = function(event) { - theta[leftUpperLegId] = event.target.value; - initNodes(leftUpperLegId); - }; - document.getElementById("slider7").onchange = function(event) { - theta[leftLowerLegId] = event.target.value; - initNodes(leftLowerLegId); + document.getElementById("button1").onclick = function() { + if (animationState === 0) { + animationState = 1; // Start animation + } }; - document.getElementById("slider8").onchange = function(event) { - theta[rightUpperLegId] = event.target.value; - initNodes(rightUpperLegId); - }; - document.getElementById("slider9").onchange = function(event) { - theta[rightLowerLegId] = event.target.value; - initNodes(rightLowerLegId); - }; - document.getElementById("slider10").onchange = function(event) { - theta[head2Id] = event.target.value; - initNodes(head2Id); + + document.getElementById("button2").onclick = function() { + if (animationState === 0) { + animationState = 5; // Start animation + } }; + + for(i=0; i<numNodes; i++) initNodes(i); render(); } +// Animation Part + +var animationState = 0; // 0: idle, 1: increasing, 2: decreasing +var frameCount = 0; + +function divideArrays(arr1, arr2, frame) { + return arr1.map((value, index) => (value - arr2[index]) / frame); +} +function updateTheta(theta, array, frameCount, frame, nextState) { + theta = theta.map((value, index) => value + array[index]); + frameCount++; + if (frameCount >= frame) { + animationState = nextState; + frameCount = 0; + } + return { theta, frameCount }; +} + +function updatepos(pos, array) { + return pos.map((value, index) => value + array[index]); +} + +function greeting(){ + // 1 ~ 4 + if(animationState < 1 || animationState > 4) + return; + + const tstate1 = [70, 0, 210, -60, 210, -60, 210, -60, 210, -60, -60, 150, 0, 0, 0]; + const pstate1 = [0, 0, 0]; + const tstate2 = [70, 0, 235, -80, 190, -75, 210, -60, 210, -60, 10, 130, 30, 0, 6]; + const pstate2 = pstate1.map((value, index) => value + directionVec[index] * 3); + const tstate3 = [70, 0, 245, -90, 180, -80, 210, -60, 210, -60, 30, 120, 40, 0, 8]; + const tstate4 = tstate3; + const tstate5 = tstate1; + + const frame1 = 60; + const frame2 = 30; + const frame3 = 100; + const frame4 = 45; + + const tarray1 = divideArrays(tstate2, tstate1, frame1); + const parray1 = divideArrays(pstate2, pstate1, frame1); + const tarray2 = divideArrays(tstate3, tstate2, frame2); + const tarray3 = divideArrays(tstate4, tstate3, frame3); + const tarray4 = divideArrays(tstate5, tstate4, frame4); + + if (animationState === 1) { + posVec = updatepos(posVec, parray1); + ({ theta, frameCount } = updateTheta(theta, tarray1, frameCount, frame1, 2)); + } else if (animationState === 2) { + ({ theta, frameCount } = updateTheta(theta, tarray2, frameCount, frame2, 3)); + } else if (animationState === 3) { + ({ theta, frameCount } = updateTheta(theta, tarray3, frameCount, frame3, 4)); + } else if (animationState === 4) { + ({ theta, frameCount } = updateTheta(theta, tarray4, frameCount, frame4, 0)); + } + + for (let i = 0; i < numNodes; i++) { + initNodes(i); + } +} + +function handshigh(){ + // 5 ~ 7 + if(animationState < 5 || animationState > 7) + return; + + const tstate1 = [70, 0, 210, -60, 210, -60, 210, -60, 210, -60, -60, 150, 0, 0, 0]; + const tstate2 = [70, 0, 180, -90, 180, -90, 220, -60, 220, -60, -50, 130, 0, 0, -10]; + const tstate3 = tstate2; + const tstate4 = tstate1; + + + const frame1 = 20; + const frame2 = 60; + const frame3 = 20; + + const tarray1 = divideArrays(tstate2, tstate1, frame1); + const tarray2 = divideArrays(tstate3, tstate2, frame2); + const tarray3 = divideArrays(tstate4, tstate3, frame3); + + if (animationState === 5) { + ({ theta, frameCount } = updateTheta(theta, tarray1, frameCount, frame1, 6)); + } else if (animationState === 6) { + ({ theta, frameCount } = updateTheta(theta, tarray2, frameCount, frame2, 7)); + } else if (animationState === 7) { + ({ theta, frameCount } = updateTheta(theta, tarray3, frameCount, frame3, 0)); + } + + for (let i = 0; i < numNodes; i++) { + initNodes(i); + } +} var render = function() { gl.clear( gl.COLOR_BUFFER_BIT ); - theta[head2Id] += 1; - initNodes(head2Id); + updatedirectionVec(); + if (animationState !== 0) { + greeting(); + handshigh(); + //headmove(); + } traverse(torsoId); requestAnimFrame(render); -- GitLab