#include "main.h" #include "3dutils.h" #include #include "utils.h" #include "mesh.h" #include "vector.h" #include "texture.h" #include "glapi.h" int SKYBOX = -1; /* * Luo pyörähdyskappaleen y-akselin ympäri annetuista pisteistä * Parametrina taulukollinen pisteitä, * pisteidein määrä, * jakojen määrä pyörähdyssuunnassa, * jakojen määrä "pysty"suunnassa * Jos viimeinen parametri on sama kuin pisteiden määrä, * niin pyörähdyskappale vastaa suoraan annettujen pisteiden * pyörähdyskappaletta. Muulloin pisteet lasketaan kuutiollisella * interpoloinnilla annettujen pisteiden välillä. */ void createLathedSurface(point2d *points, point2d *pointderivates, int count, int slices, int stacks){ int i, j; point2d *h1, *h2; point2d *derivates; if (pointderivates == NULL) derivates = new point2d[count]; else derivates = pointderivates; //Derivaatta pisteessä i on (points[i+1]-points[i-1])/2 alkua ja loppua lukuunottamatta for (i = 0; i < count; i++){ if (pointderivates == NULL || (derivates[i].x == 0 && derivates[i].y == 0)){ if (i == 0) h1 = &points[0]; else h1 = &points[i-1]; if (i == count-1) h2 = &points[count-1]; else h2 = &points[i+1]; float dx,dy; dx = (h2->x - h1->x); dy = (h2->y - h1->y); if (i > 0 && i < count){ dx /= 2; dy /= 2; } derivates[i].x = dx; derivates[i].y = dy; } } float sif; int si; point2d newpoint, oldpoint; point2d derivate; point2d newnormal, oldnormal; point2d A, B, C, D; oldpoint.x = points[0].x; oldpoint.y = points[0].y; oldnormal.x = derivates[0].y; oldnormal.y = -derivates[0].x; point2d *p1, *p2, *d1, *d2; int i1, i2; float t; float x1, y1, z1, x2, y2, z2, nx1, ny1, nz1, nx2, ny2, nz2; for (i = 1; i <= stacks-(stacks/count); i++){ sif = (float)i*count/stacks; si = (int)sif; t = sif-si; i1 = si; i2 = si+1; if (i2 >= count) i2 = count-1; p1 = &points[i1]; p2 = &points[i2]; d1 = &derivates[i1]; d2 = &derivates[i2]; //Hermite-käyrä A*t^3 + B*t^2 + C*t + D //Hermite-käyrän derivaatta 3*A*t^2 + 2*B*t + C //Vakiot A,B,C ja D ovat laskettu siten, että: //1. H(0)=p1; //2. H(1)=p2; //3. H'(0)=d1; //4. H'(1)=d2; // //A = d2 - 2*p2 + d1 + 2*p1 //B = -d2 + 3*p2 - 2*d1 - 3*p1 //C = d1 //D = p1 A.x = d2->x - 2*p2->x + d1->x + 2*p1->x; A.y = d2->y - 2*p2->y + d1->y + 2*p1->y; B.x = - d2->x + 3*p2->x - 2*d1->x - 3*p1->x; B.y = - d2->y + 3*p2->y - 2*d1->y - 3*p1->y; C.x = d1->x; C.y = d1->y; D.x = p1->x; D.y = p1->y; newpoint.x = A.x*t*t*t + B.x*t*t + C.x*t + D.x; newpoint.y = A.y*t*t*t + B.y*t*t + C.y*t + D.y; derivate.x = 3*A.x*t*t + 2*B.x*t + C.x; derivate.y = 3*A.y*t*t + 2*B.y*t + C.y; newnormal.x = derivate.y; newnormal.y = -derivate.x; glBegin(GL_QUAD_STRIP); for (j = 0; j <= slices; j++){ float angle = j*2*PI/slices; nx2 = sin(angle)*newnormal.x; ny2 = newnormal.y; nz2 = cos(angle)*newnormal.x; glNormal3f(nx2, ny2, nz2); x2 = sin(angle)*newpoint.x; y2 = newpoint.y; z2 = cos(angle)*newpoint.x; glTexCoord2f(j*1.0/slices,1.0-(i*1.0/(stacks-1))); glVertex3f(x2, y2, z2); nx1 = sin(angle)*oldnormal.x; ny1 = oldnormal.y; nz1 = cos(angle)*oldnormal.x; glNormal3f(nx1, ny1, nz1); x1 = sin(angle)*oldpoint.x; y1 = oldpoint.y; z1 = cos(angle)*oldpoint.x; glTexCoord2f(j*1.0/slices,1.0-((i-1)*1.0/(stacks-1))); glVertex3f(x1, y1, z1); } glEnd(); oldpoint.x = newpoint.x; oldpoint.y = newpoint.y; oldnormal.x = newnormal.x; oldnormal.y = newnormal.y; } } GLUquadricObj *spherequadric = gluNewQuadric(); void createSphere(float r, int slices, int stacks){ /*float phi, theta; int x, y; for (y = 0; y < stacks; y++){ for (x = 0; x < slices; x++){ } }*/ gluSphere(spherequadric, r, slices, stacks); } #define DEFAULTSLICES 20 #define DEFAULTSTACKS 10 void createSphere(float r){ createSphere(r, DEFAULTSLICES, DEFAULTSTACKS); } bool solvePointInTriangle(float *position, float *normal, Vertex *v1, Vertex *v2, Vertex *v3, float *t, float *u, float *v){ float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; float det,inv_det; // find vectors for two edges sharing vert0 vectorSub(edge1, v2->position, v1->position); vectorSub(edge2, v3->position, v1->position); // begin calculating determinant - also used to calculate U parameter vectorCross(pvec, normal, edge2); //if determinant is near zero, ray lies in plane of triangle det = vectorDot(edge1, pvec); if (det > -EPSILON && det < EPSILON) return false; inv_det = 1.0 / det; // calculate distance from vert0 to ray origin vectorSub(tvec, position, v1->position); // calculate U parameter and test bounds *u = vectorDot(tvec, pvec) * inv_det; if (*u < 0.0 || *u > 1.0) return false; // prepare to test V parameter vectorCross(qvec, tvec, edge1); // calculate V parameter and test bounds *v = vectorDot(normal, qvec) * inv_det; if (*v < 0.0 || *u + *v > 1.0) return false; // calculate t, ray intersects triangle *t = vectorDot(edge2, qvec) * inv_det; return true; } float distanceFromPlane(float point[3], float normal[3], float distance){ return vectorDot(point, normal) + distance; } void createSkyBox(float x, float y, float z, float w, float h, float l) { glEnable(GL_TEXTURE_2D); glClear(GL_DEPTH_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glDisable(GL_ALPHA_TEST); glDisable(GL_LIGHTING); glShadeModel(GL_FLAT); float modelview[16]; glGetFloatv(GL_MODELVIEW_MATRIX, modelview); modelview[12] = modelview[13] = modelview[14] = 0.0f; glPushMatrix(); glLoadMatrixf(modelview); if (SKYBOX > 0){ glCallList(SKYBOX); } else{ SKYBOX = glGenLists(1); float d = 1.0/512; //glPushAttrib(GL_COLOR); glNewList(SKYBOX, GL_COMPILE_AND_EXECUTE); //glBindTexture(GL_TEXTURE_2D, SKY_BACK_ID); skybacktexture->enable(); glBegin(GL_QUADS); glColor4f(1, 1, 1, 1.0); glTexCoord2f(1-d, 1-d); glVertex3f(x + w, y, z); glTexCoord2f(1-d, 0+d); glVertex3f(x + w, y + h, z); glTexCoord2f(0+d, 0+d); glVertex3f(x, y + h, z); glTexCoord2f(0+d, 1-d); glVertex3f(x, y, z); glEnd(); //glBindTexture(GL_TEXTURE_2D, SKY_FRONT_ID); skyfronttexture->enable(); glBegin(GL_QUADS); glColor4f(1, 1, 1, 1.0); glTexCoord2f(1-d, 1-d); glVertex3f(x, y, z + l); glTexCoord2f(1-d, 0+d); glVertex3f(x, y + h, z + l); glTexCoord2f(0+d, 0+d); glVertex3f(x + w, y + h, z + l); glTexCoord2f(0+d, 1-d); glVertex3f(x + w, y, z + l); glEnd(); //glBindTexture(GL_TEXTURE_2D, SKY_TOP_ID); skytoptexture->enable(); glBegin(GL_QUADS); glColor4f(1, 1, 1, 1.0); glTexCoord2f(0+d, 0+d); glVertex3f(x + w, y + h, z + l); glTexCoord2f(1-d, 0+d); glVertex3f(x + w, y + h, z); glTexCoord2f(1-d, 1-d); glVertex3f(x, y + h, z); glTexCoord2f(0+d, 1-d); glVertex3f(x, y + h, z + l); /*glTexCoord2f(1.0f, 0+d); glVertex3f(x + w, y + h, z); glTexCoord2f(1.0f, 1.0f); glVertex3f(x + w, y + h, z + l); glTexCoord2f(0+d, 1.0f); glVertex3f(x, y + h, z + l); glTexCoord2f(0+d, 0+d); glVertex3f(x, y + h, z);*/ glEnd(); //glBindTexture(GL_TEXTURE_2D, SKY_BOTTOM_ID); skybottomtexture->enable(); glBegin(GL_QUADS); glColor4f(1, 1, 1, 1.0); glTexCoord2f(1-d, 0+d); glVertex3f(x, y, z); glTexCoord2f(1-d, 1-d); glVertex3f(x + w, y, z); glTexCoord2f(0+d, 1-d); glVertex3f(x + w, y, z + l); glTexCoord2f(0+d, 0+d); glVertex3f(x, y, z + l); glEnd(); //glBindTexture(GL_TEXTURE_2D, SKY_LEFT_ID); skylefttexture->enable(); glBegin(GL_QUADS); glColor4f(1, 1, 1, 1.0); glTexCoord2f(1-d, 0+d); glVertex3f(x, y + h, z); glTexCoord2f(0+d, 0+d); glVertex3f(x, y + h, z + l); glTexCoord2f(0+d, 1-d); glVertex3f(x, y, z + l); glTexCoord2f(1-d, 1-d); glVertex3f(x, y, z); glEnd(); //glBindTexture(GL_TEXTURE_2D, SKY_RIGHT_ID); skyrighttexture->enable(); glBegin(GL_QUADS); glColor4f(1, 1, 1, 1.0); glTexCoord2f(0+d, 1-d); glVertex3f(x + w, y, z); glTexCoord2f(1-d, 1-d); glVertex3f(x + w, y, z + l); glTexCoord2f(1-d, 0+d); glVertex3f(x + w, y + h, z + l); glTexCoord2f(0+d, 0+d); glVertex3f(x + w, y + h, z); glEnd(); glEndList(); } glPopMatrix(); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glShadeModel(GL_SMOOTH); } void enable2D(void){ glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0, 1, 1, 0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); } void disable2D(void){ glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); }