--- /dev/null
+#include "animator.h"
+#include "eye.h"
+
+#include <random>
+
+struct {
+ double blink;
+} animation;
+
+std::random_device rd;
+
+const double blinkDuration = 0.2;
+
+void blink(double dt) {
+ if (animation.blink < -1) {
+ animation.blink = blinkDuration;
+ } else if (animation.blink <= 0.0) {
+ auto roll = rd();
+ if (roll > rd.max() * 0.8)
+ animation.blink -= dt;
+ } else {
+ animation.blink -= dt;
+ }
+
+ if (animation.blink <= 0.0) {
+ eyes[0].blinkFrame = open;
+ eyes[1].blinkFrame = open;
+ } else {
+ const double frameTimings[BLINKFRAME_MAX] {blinkDuration, blinkDuration*0.6, blinkDuration*0.3, 0};
+ for (int i = open; i < BLINKFRAME_MAX; i++) {
+ auto frame = blinkDuration - animation.blink;
+ if (frameTimings[i+1] <= frame && frame <= frameTimings[i]) {
+ eyes[0].blinkFrame = (blinkFrame_t)(i+1);
+ eyes[1].blinkFrame = (blinkFrame_t)(i+1);
+ }
+ }
+ }
+}
+
+void updateAnimations(double dt) {
+ blink(dt);
+}
+
+void initAnimator() {
+ animation.blink = 0.0;
+}
#include "eye.h"
+#include "eye_frames.h"
#include <cstdio>
#include <cstddef>
const char* eye_vertex_shader =
"#version 120\n"
-"attribute vec3 aPos;\n"
-"uniform int eyeflipped;\n"
-"void main() {\n"
+"attribute vec3 aPos;"
+"uniform int eyeflipped;"
+"void main() {"
" // scale pixel position to +-1;\n"
-" gl_Position = vec4(eyeflipped * (aPos.x/400 -1), aPos.y/240 -1, aPos.z, 1.0);\n"
+" gl_Position = vec4(eyeflipped * (aPos.x/400 -1), aPos.y/240 -1, aPos.z, 1.0);"
"};";
const char* eye_fragment_shader =
const char* eye_pupil_fragment_shader =
"#version 120\n"
+"uniform ivec2 position;"
"void main() {"
-" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);"
+" float radius = 10.0;"
+" vec2 pos = gl_FragCoord.xy - position;"
+" float yUp = pos.y + 0;"
+" float yDown = pos.y - 0;"
+" float topTerm = sqrt( yUp * yUp/5 + pos.x * pos.x) - 8;"
+" float equation = topTerm;"
+" float width = 0.5;"
+" if (equation - width < 0 && equation + width > 0) {"
+" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);"
+" } else {"
+" discard;"
+" }"
"};";
-float eyeline[] {
- 150, 130, 0,
- 150, 190, 0,
-
- 150, 220, 0,
- 150, 280, 0,
-
- 150, 310, 0,
- 150, 370, 0,
-
- 160, 380, 0,
- 240, 380, 0,
-
- 260, 370, 0,
- 310, 310, 0,
-
- 320, 280, 0,
- 320, 220, 0,
-
- 320, 190, 0,
- 320, 130, 0,
-
- 330, 110, 0,
- 250, 110, 0,
-
- 230, 110, 0,
- 140, 110, 0,
-};
-
-float eyePos[] {
- 270, 280, 0,
-};
-
GLuint eyeShaderProgram;
GLuint eyeFlipLocation;
+GLuint eyePupilLocation;
GLuint pupilShaderProgram;
eye_t eyes[2];
}
auto pupilFragShader = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(pupilFragShader, 1, &eye_fragment_shader, NULL);
+ glShaderSource(pupilFragShader, 1, &eye_pupil_fragment_shader, NULL);
glCompileShader(pupilFragShader);
glGetShaderiv(pupilFragShader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
if (err) {
printf("uhoh uniform location error: %d\n", err);
}
+
+ eyePupilLocation = glGetUniformLocation(pupilShaderProgram, "position");
+ err = glGetError();
+ if (err) {
+ printf("uhoh uniform location error: %d\n", err);
+ }
}
void initEye(eye_t *eye) {
void initEyes() {
auto eye = &eyes[0];
eye->left = 1;
+ eye->blinkFrame = open;
+ eye->pupilLoc[0] = 250;
+ eye->pupilLoc[1] = 250;
initEye(eye);
eye = &eyes[1];
eye->left = -1;
+ eye->blinkFrame = open;
+ eye->pupilLoc[0] = 550;
+ eye->pupilLoc[1] = 250;
initEye(eye);
setEyeShaderProgram();
glUniform1i(eyeFlipLocation, eye->left);
glBindBuffer(GL_ARRAY_BUFFER, eye->eyeVBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
- glDrawArrays(GL_LINES, 0, 18);
+ int nPoints = eyeLineCount[eye->blinkFrame]*2;
+ int startIndex = eye->blinkFrame * eyeMaxPoints;
+ glDrawArrays(GL_LINES, startIndex, nPoints);
}
void drawPupil(eye_t *eye) {
+ if (eye->blinkFrame >= blink_30) {
+ return;
+ }
+ // Eyes are not symmetric, don't flip
glUniform1i(eyeFlipLocation, eye->left);
+ glUniform2i(eyePupilLocation, eye->pupilLoc[0], eye->pupilLoc[1]);
glBindBuffer(GL_ARRAY_BUFFER, eye->pupilVBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
- glDrawArrays(GL_POINTS, 0, 1);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
void drawEyes() {
#include "log.h"
#include "eye.h"
#include "mouth.h"
+#include "animator.h"
float triangles[] = {
-0.5,0.5,0,
initEyes();
initMouth();
+ initAnimator();
GLuint VBOS[2];
glGenBuffers(2, (GLuint*) &VBOS);
glEnableVertexAttribArray(0);
+ double targetFps = 24.0;
+ double targetRate = 1 / targetFps;
+ double currentTime, lastUpdateTime =0.0, lastRenderTime = 0.0;
+
while(!glfwWindowShouldClose(window)) {
- glClearColor(.0f, .0f, .0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
+ currentTime = glfwGetTime();
+ glfwPollEvents();
- drawEyes();
- drawMouth();
+ // update
+ updateAnimations(currentTime - lastUpdateTime);
+ lastUpdateTime = currentTime;
+
+ if (currentTime - lastRenderTime > targetRate) {
+ lastRenderTime = currentTime;
+
+ // render
+ glfwSwapBuffers(window);
+ glClearColor(.0f, .0f, .0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ drawEyes();
+ drawMouth();
+ }
- glfwSwapBuffers(window);
- glfwPollEvents();
}
glfwTerminate();
}