/*
Benötigt matrix.h erhältlich hier http://matrix.drque.net/
Tastenbelegung:
W,S,A,D,Q,E - Steuerung der Kugel/Ziel-punkt
X,Y,Z - Kameraausrichtung auf XY,YZ und ZX Ebenen(Front-, Seiten- und Draufsicht)
O,P - Punkte menge durchlaufen
1,2,3,4 Armlänge ändern
i - start/stop animate
u - richtung der animation
*/
#define GLFW_DLL
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
using namespace std;
#include "vec3.hpp"
#include "matrix.h"
static double alpha_ = 0;
static double beta_ = 0;
static double gamma_= 0;
static double delta_ = 0;
static double epsilon_ = 0;
static double zetta_ = 0;
static double bla_ = 0;
static double dt_ = 1;
static double angleXAxis_=0;
static double angleYAxis_=-90;
static double angleZAxis_=0;
static double a[2] = {15,15};
Vec3 p( 5, 0, 5);
Vec3 q(0,0,0);
Vec3 theta(M_PI/2, M_PI/2, M_PI/2);
//static double q[3] = {0, 0, 0};
int counter=0;
bool animate;
bool richtung;
double J[3][3];
static Vec3 mouseSpeed(0,0,0);
static double window_width_ = 1000;
static double window_height_ =1000;
static double zoomIn = 1;
vector<Vec3> getTorus(double radius1,double radius2,int resolution1,int resolution2){
vector<Vec3>punkte;
for (int i=0;i<=resolution1;i++){
double alpha=i*2*M_PI/resolution1;
for (int j=0;j<=resolution2;j++){
double beta=j*2*M_PI/resolution2;
punkte.push_back(Vec3((radius1+radius2*cos(beta))*cos(alpha),(radius1+radius2*cos(beta))*sin(alpha),radius2*sin(beta)));
}
}
return punkte;
}
vector<Vec3> getBall(double size,int slices,double resolution){
vector<Vec3>punkte;
for (int i=-slices;i<=slices;i++){
double aktslice=i*size/slices;
double R=sqrt(pow(size,2)-pow(aktslice,2));
for (int j=0;j<=resolution;j++){
double aktPunkt=j*2*M_PI/resolution;
punkte.push_back(Vec3(R*cos(aktPunkt),R*sin(aktPunkt),aktslice));
}
}
return punkte;
}
void SetMaterialColor(int side, double r, double g, double b) {
float amb[4], dif[4], spe[4];
int mat;
dif[0] = r;
dif[1] = g;
dif[2] = b;
for(int i = 0; i < 3; i++) {
amb[i] = .1 * dif[i];
spe[i] = .5;
}
amb[3] = dif[3] = spe[3] = 1.0;
switch(side){
case 1: mat = GL_FRONT;
break;
case 2: mat = GL_BACK;
break;
default: mat = GL_FRONT_AND_BACK;
}
glMaterialfv(mat, GL_AMBIENT, amb);
glMaterialfv(mat, GL_DIFFUSE, dif);
glMaterialfv(mat, GL_SPECULAR, spe);
glMaterialf( mat, GL_SHININESS, 20);
}
void DrawQuad(Vec3 a,Vec3 b,Vec3 c,Vec3 d){
Vec3 norm((a-b)%(a-c));
norm=norm/norm.Length();
glBegin(GL_QUADS);
glNormal3dv(norm.p);
glVertex3dv(a.p);
glVertex3dv(b.p);
glVertex3dv(c.p);
glVertex3dv(d.p);
glEnd();
}
void DrawTriangle(Vec3 a,Vec3 b,Vec3 c){
Vec3 norm((a-b)%(a-c));
norm=norm/norm.Length();
glBegin(GL_TRIANGLES);
glNormal3dv(norm.p);
glVertex3dv(a.p);
glVertex3dv(b.p);
glVertex3dv(c.p);
glEnd();
}
void DrawZylinder(double radius,double hoehe,double res){
int i;
double a1=2* M_PI /res;
Vec3 M1(0,0,0);
Vec3 M2(0,0,hoehe);
for(i=0; i<=res; i++){
Vec3 P0(radius*sin(a1*(i+0)),radius*cos(a1*(i+0)),hoehe);
Vec3 P1(radius*sin(a1*(i+0.5)),radius*cos(a1*(i+0.5)),0);
Vec3 P2(radius*sin(a1*(i+1)),radius*cos(a1*(i+1)),hoehe);
Vec3 P3(radius*sin(a1*(i+1.5)),radius*cos(a1*(i+1.5)),0);
DrawTriangle(P0,P1,P2);
DrawTriangle(P1,P2,P3);
DrawTriangle(P0,M2,P2);
DrawTriangle(P3,P1,M1);
}
}
// draw a sphere composed of triangles
void DrawSphere(const Vec3& ctr, double r){
int i, j,
n1 = 20, n2 = 60;
Vec3 normal, v1;
double a1, a1d = M_PI / n1,
a2, a2d = M_PI / n2,
s1, s2,
c1, c2;
glShadeModel(GL_SMOOTH);
for(i = 0; i < n1; i++){
a1 = i * a1d;
// if(i<=n1*0.5)SetMaterialColor(3,0,0,0);
// if(i>n1*0.5)SetMaterialColor(3,1,1,1);
glBegin(GL_TRIANGLE_STRIP);
for(j = 0; j <= n2; j++){
a2 = (j + .5 * (i % 2)) * 2 * a2d;
s1 = sin(a1);
c1 = cos(a1);
s2 = sin(a2);
c2 = cos(a2);
normal = c1 * XVec3 + s1 * (c2 * YVec3 + s2 * ZVec3);
v1 = ctr + r * normal;
glNormal3dv(normal.p);
glVertex3dv(v1.p);
s1 = sin(a1 + a1d);
c1 = cos(a1 + a1d);
s2 = sin(a2 + a2d);
c2 = cos(a2 + a2d);
normal = c1 * XVec3 + s1 * (c2 * YVec3 + s2 * ZVec3);
v1 = ctr + r * normal;
glNormal3dv(normal.p);
glVertex3dv(v1.p);
}
glEnd();
}
}
void DrawCube(double seitenlaenge){
//Eckpunkte
Vec3 P1(-seitenlaenge/2,seitenlaenge/2,-seitenlaenge/2);
Vec3 P2(seitenlaenge/2,seitenlaenge/2,-seitenlaenge/2);
Vec3 P3(seitenlaenge/2,seitenlaenge/2,seitenlaenge/2);
Vec3 P4(-seitenlaenge/2,seitenlaenge/2,seitenlaenge/2);
Vec3 P5(-seitenlaenge/2,-seitenlaenge/2,-seitenlaenge/2);
Vec3 P6(seitenlaenge/2,-seitenlaenge/2,-seitenlaenge/2);
Vec3 P7(seitenlaenge/2,-seitenlaenge/2,seitenlaenge/2);
Vec3 P8(-seitenlaenge/2,-seitenlaenge/2,seitenlaenge/2);
//Seiten
DrawQuad(P1,P2,P3,P4);
DrawQuad(P3,P2,P6,P7);
DrawQuad(P4,P3,P7,P8);
DrawQuad(P1,P4,P8,P5);
DrawQuad(P2,P1,P5,P6);
DrawQuad(P5,P6,P7,P8);
}
// set viewport transformations and draw objects
void InitLighting() {
GLfloat lp1[4] = { 10, 20, 10, 0};
GLfloat lp2[4] = { -50, 50, -10, 0};
GLfloat lp3[4] = { -5, -50, -10, 0};
GLfloat red[49] = {1.0, .8, .8, 1};
GLfloat blue[4] = { .8, .8, 1.0, 1};
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glShadeModel(GL_SMOOTH);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT1, GL_POSITION, lp1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, red);
glLightfv(GL_LIGHT1, GL_SPECULAR, red);
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT2, GL_POSITION, lp2);
glLightfv(GL_LIGHT2, GL_DIFFUSE, blue);
glLightfv(GL_LIGHT2, GL_SPECULAR, blue);
glEnable(GL_LIGHT2);
glLightfv(GL_LIGHT2, GL_POSITION, lp3);
glLightfv(GL_LIGHT2, GL_DIFFUSE, blue);
glLightfv(GL_LIGHT2, GL_SPECULAR, blue);
glEnable(GL_LIGHT3);
glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// init viewport to canvassize
glViewport(0, 0, window_width_, window_height_);
// init coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-30*zoomIn, 30*zoomIn, -30*zoomIn, 30*zoomIn, -50*zoomIn, 50*zoomIn);
// double n=10;
// double f=40;
// double a=0.5;
// double fov=90;
// double l=-1*n*tan((a*fov)/2);
// double r=f*tan((a*fov)/2);
// double b=-1*n*tan(fov/2);
// double t=f*tan(fov/2);
//
// glFrustum(l, r, b, t, n, f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void DrawKrane(){
double radius=1;
glPushMatrix();
glRotated(180+(180/M_PI) * theta.p[2],0,0,1);
glRotated(-90+(180/M_PI) * theta.p[0],0,1,0);
DrawSphere(Vec3(0,0,0),radius);
DrawZylinder(radius,a[0],50);
glTranslated(0,0,a[0]);
glRotated((180/M_PI) * theta.p[1],0,1,0);
DrawSphere(Vec3(0,0,0),radius);
DrawSphere(Vec3(0,0,a[1]),radius);
DrawZylinder(radius,a[1],50);
glPopMatrix();
}
vector<Vec3>Punkte=getTorus(10,5,100,100);
void IK(){
for(int i = 0; i <= 5; i++){
Vec3 r=a[0]*Vec3(cos(theta.p[0]) * cos(theta.p[2]),
cos(theta.p[0]) * sin(theta.p[2]),
sin(theta.p[0]));
Vec3 s=a[1]*Vec3(cos(theta.p[0] + theta.p[1]) * cos(theta.p[2]),
cos(theta.p[0] + theta.p[1]) * sin(theta.p[2]),
sin(theta.p[0] + theta.p[1]));
Vec3 f = q + r + s;
Vec3 F_theta1(-a[0] * sin(theta.p[0]) * cos(theta.p[2]) - a[1] * sin(theta.p[0] + theta.p[1]) * cos(theta.p[2]),
-a[0] * sin(theta.p[0]) * sin(theta.p[2]) - a[1] * sin(theta.p[0] + theta.p[1]) * sin(theta.p[2]),
a[0] * cos(theta.p[0]) + a[1] * cos(theta.p[0] + theta.p[1]));
Vec3 F_theta2(-a[1] * sin(theta.p[0] + theta.p[1]) * cos(theta.p[2]),
-a[1] * sin(theta.p[0] + theta.p[1]) * sin(theta.p[2]),
a[1] * cos(theta.p[0] + theta.p[1]));
Vec3 F_theta3(-a[0]*cos(theta.p[0]) *sin(theta.p[2]) - a[1]*cos(theta.p[0] + theta.p[1] ) * sin(theta.p[2]),
a[0]*cos(theta.p[0]) *cos(theta.p[2]) + a[1]*cos(theta.p[0] + theta.p[1] ) * cos(theta.p[2]),
0);
for(int i=0;i<=2;i++){
J[i][0] = F_theta1.p[i];
J[i][1] = F_theta2.p[i];
J[i][2] = F_theta3.p[i];
}
Matrix<double> Jacobi(3,3);
for(int k=0;k<=2;k++){
for(int l=0;l<=2;l++){
Jacobi.put(k,l,J[k][l]);
}
}
Matrix<double> JacobiRes(3,3);
JacobiRes = (Jacobi.getTranspose() * Jacobi).getInverse() * Jacobi.getTranspose();
Vec3 dtheta(0,0,0);
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
dtheta.p[i]+=JacobiRes.get(i,j)*(p-f).p[j];
}
}
theta = theta + dtheta;
}
}
// draw the entire scene
void Preview() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslated(0, 0, -30.0); // Move 10 units backwards in z,
// since camera is at origin
//glPushMatrix();
glRotated(angleXAxis_,0,1,0);
glRotated(angleYAxis_,1,0,0);
glRotated(angleZAxis_,0,0,1);
SetMaterialColor(3, 1, 0.5, 0);
for(int g=0;g<counter;g++){
//for(int g=0;g<(int)Punkte.size();g++){
Vec3 p1=Punkte.at(g);
glPushMatrix();
glTranslated(p1.p[0],p1.p[1],p1.p[2]);
DrawCube(0.2);
glPopMatrix();
}
if(animate){
if (counter<Punkte.size()-1 && !richtung){
p=Punkte.at(counter);
counter++;}
if(counter>0 && richtung){
p=Punkte.at(counter);
counter--;
}
}
IK();
DrawKrane();
SetMaterialColor(3, 1, 0, 0);
DrawSphere(p, 1.1);
glPopMatrix();
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS){
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
mouseSpeed.p[0] = xpos;
mouseSpeed.p[2] = ypos;
}
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE){
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
mouseSpeed.p[0] = xpos - mouseSpeed.p[0];
mouseSpeed.p[2] = ypos - mouseSpeed.p[2];
}
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods){
if (key == GLFW_KEY_N)dt_+=0.1;
if (key == GLFW_KEY_M)dt_-=0.1;
if (key == GLFW_KEY_UP)angleYAxis_+=dt_;
if (key == GLFW_KEY_DOWN)angleYAxis_-=dt_;
if (key == GLFW_KEY_LEFT)angleXAxis_+=dt_;
if (key == GLFW_KEY_RIGHT)angleXAxis_-=dt_;
if (key == GLFW_KEY_J){
zoomIn += 0.01;
}
if (key == GLFW_KEY_K){
zoomIn -= 0.01;
}
if (key == GLFW_KEY_O){
if(counter<Punkte.size()-1){
p=Punkte.at(counter);
counter++;
}
}
if (key == GLFW_KEY_P){
if(counter>0){
p=Punkte.at(counter);
counter--;
}
}
if (key == GLFW_KEY_I && action == GLFW_PRESS){
animate = !animate;
}
if (key == GLFW_KEY_U && action == GLFW_PRESS){
richtung = !richtung;
}
if (key == GLFW_KEY_Y){
angleXAxis_=0;
angleYAxis_=-90;
angleZAxis_=0;
}
if (key == GLFW_KEY_Z){
angleXAxis_=0;
angleYAxis_=0;
angleZAxis_=0;
}
if (key == GLFW_KEY_X){
angleXAxis_=0;
angleYAxis_=-90;
angleZAxis_=-90;
}
if (key == GLFW_KEY_W)p.p[2] +=dt_;
if (key == GLFW_KEY_S)p.p[2] -=dt_;
if (key == GLFW_KEY_A)p.p[0] -=dt_;
if (key == GLFW_KEY_D)p.p[0] +=dt_;
if (key == GLFW_KEY_Q)p.p[1] +=dt_;
if (key == GLFW_KEY_E)p.p[1] -=dt_;
if (key == GLFW_KEY_1)a[0]+=dt_;
if (key == GLFW_KEY_2)a[0]-=dt_;
if (key == GLFW_KEY_3)a[1]+=dt_;
if (key == GLFW_KEY_4)a[1]-=dt_;
// if (key == GLFW_KEY_1)alpha_+=dt_;
// if (key == GLFW_KEY_2)alpha_-=dt_;
// if (key == GLFW_KEY_3)beta_+=dt_;
// if (key == GLFW_KEY_4)beta_-=dt_;
if (key == GLFW_KEY_5)gamma_+=dt_;
if (key == GLFW_KEY_6)gamma_-=dt_;
if (key == GLFW_KEY_7)delta_+=dt_;
if (key == GLFW_KEY_8)delta_-=dt_;
if (key == GLFW_KEY_9)epsilon_+=dt_;
if (key == GLFW_KEY_0)epsilon_-=dt_;
if (key == GLFW_KEY_B)zetta_+=0.10;
if (key == GLFW_KEY_V)zetta_-=0.10;
if (key == GLFW_KEY_F)bla_+=0.1;
if (key == GLFW_KEY_G)bla_-=0.1;
if (key == GLFW_KEY_R){
alpha_=0;
beta_ =0;
gamma_=0;
delta_=0;
epsilon_=0;
zetta_=0;
angleXAxis_=0;
angleYAxis_=-90;
angleZAxis_=0;
dt_=1;
alpha_=0;
a[0]=15;
a[1]=15;
}
if(key == GLFW_KEY_ESCAPE)exit(0);
}
int main() {
GLFWwindow* window = NULL;
printf("Here we go!\n");
if(!glfwInit()){
return -1;
}
window = glfwCreateWindow(window_width_, window_height_,
"Simple 3D Animation", NULL, NULL);
if(!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
while(!glfwWindowShouldClose(window)) {
// switch on lighting (or you don't see anything)
InitLighting();
// set background color
glClearColor(0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//KeyFunctions
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetKeyCallback(window, key_callback);
// draw the scene
Preview();
// make it appear (before this, it's hidden in the rear buffer)
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
printf("Goodbye!\n");
return 0;
}
Comments