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