bool line_polyHit (const LINE3 * const line, int points, const VECTOR3 * const poly, float * tAtIntersection) { VECTOR3 u, v, plane, hit; LINE3 transLine; float t; u = vectorSubtract (&poly[1], &poly[0]); v = vectorSubtract (&poly[2], &poly[0]); plane = vectorCross (&u, &v); plane = vectorNormalize (&plane); // see note in the line_triHit function transLine.origin = vectorSubtract (&line->origin, &poly[0]); transLine.dir = line->dir; if (!line_planeHit (&transLine, &plane, &t)) return false; hit = vectorCreate ( line->origin.x + line->dir.x * t, line->origin.y + line->dir.y * t, line->origin.z + line->dir.z * t ); if (pointInPoly (&hit, points, poly)) { if (tAtIntersection) *tAtIntersection = t; return true; } return false; }
static REAL triangleArea2( const BVector *vertexA, const BVector *vertexB, const BVector *vertexC ) { BVector ab, ac; vectorSubtract( vertexB, vertexA, &ab ); vectorSubtract( vertexC, vertexA, &ac ); return vectorCrossProduct( &ac, &ab ); }
void OBJ_GenerateLightingInfo(obj_t* obj) { vec3_t v1,v2 ; int i; vec2_t st1,st2; float coef; vec3_t currentTangent; vec3_t currentNormal; vec3_t* tangents; vec3_t* normals; tangents = (vec3_t*)calloc(obj->num_vertices, sizeof(vec3_t)); normals = (vec3_t*)calloc(obj->num_vertices, sizeof(vec3_t)); //Accumulate tangents & normals for(i=0;i<obj->num_indices/3;i++) { vectorSubtract(obj->vertices[obj->indices[i*3+2]].position , obj->vertices[obj->indices[i*3]].position, v1); vectorSubtract(obj->vertices[obj->indices[i*3+1]].position , obj->vertices[obj->indices[i*3]].position, v2); vector2Subtract(obj->vertices[obj->indices[i*3+2]].textCoo,obj->vertices[obj->indices[i*3]].textCoo,st1); vector2Subtract(obj->vertices[obj->indices[i*3+1]].textCoo,obj->vertices[obj->indices[i*3]].textCoo,st2); //Normal part vectorCrossProduct(v2, v1, currentNormal); vectorAdd(normals[obj->indices[i*3+0]],currentNormal,normals[obj->indices[i*3+0]]); vectorAdd(normals[obj->indices[i*3+1]],currentNormal,normals[obj->indices[i*3+1]]); vectorAdd(normals[obj->indices[i*3+2]],currentNormal,normals[obj->indices[i*3+2]]); //Tangent part coef = 1/ (st1[0] * st2[1] - st2[0] * st1[1]); currentTangent[0] = coef * (v1[0] * st2[1] + v2[0] * -st1[1]); currentTangent[1] = coef * (v1[1] * st2[1] + v2[1] * -st1[1]); currentTangent[2] = coef * (v1[2] * st2[1] + v2[2] * -st1[1]); vectorAdd(tangents[obj->indices[i*3+0]],currentTangent,tangents[obj->indices[i*3+0]]); vectorAdd(tangents[obj->indices[i*3+1]],currentTangent,tangents[obj->indices[i*3+1]]); vectorAdd(tangents[obj->indices[i*3+2]],currentTangent,tangents[obj->indices[i*3+2]]); } //Vector Normalize + Normalize for(i=0;i<obj->num_vertices;i++) { normalize(tangents[i]); vectorScale(tangents[i],DE_SHRT_MAX,obj->vertices[i].tangent); normalize(normals[i]); vectorScale(normals[i],DE_SHRT_MAX,obj->vertices[i].normal); } free(tangents); free(normals); }
// init data bool Terrain::init (const char *filename) { // try to load map printf ("\nLOADING TERRAIN...\n", filename); printf ("\tMap file: %s\n", filename); if (!loadHeightMap (filename)) return false; int v_index = 0; // index for vertex array int n_index = 0; // index for normal array float x, z; // temp coord SDL_LockSurface(map_h); size = map_h -> w; num_vert = (long) (map_h -> w * map_h -> h * 4 / (res * res)); vertex = new Vector[num_vert]; // allocate vertex memory texcoord = new TexCoord[num_vert]; // allocate texture memory num_normal = (long) (map_h -> w * map_h -> h / (res * res)); normal = new Vector[num_normal]; // allocate normal memory printf ("\tVertex num: %d\n", num_vert); // loop for init vertex for (int i = 0; i < map_h -> w; i += (int) res) { // width for (int j = 0; j < map_h -> h; j += (int) res) { // height for (int n_tri = 0; n_tri < 4; n_tri++) { // polygon // x, y x = (float) i + ( ( n_tri == 1 || n_tri == 2) ? res : 0.0f ); z = (float) j + ( ( n_tri == 2 || n_tri == 3) ? res : 0.0f ); // set vertex vertex[v_index].x = (x - ( map_h -> w / 2 )); vertex[v_index].z = (z - ( map_h -> h / 2 )); vertex[v_index].y = getHeightFromMap (x, z); // set texture coord texcoord[v_index].u = x / map_h -> w; texcoord[v_index].v = z / map_h -> h; v_index++; // go to next vertex } // calculate normal coord Vector ab, bc; vectorSubtract (vertex[v_index-3], vertex[v_index-2], ab); vectorSubtract (vertex[v_index-2], vertex[v_index-1], bc); crossProduct (ab, bc, normal[n_index]); normalize (normal[n_index]); n_index++; } } SDL_UnlockSurface(map_h); return true; }
float *faceNormal(float *vectA, float *vectB, float *vectC) { float *result; float *vectD; float *vectE; vectD = vectorSubtract(vectB, vectA, 3); vectE = vectorSubtract(vectC, vectA, 3); result = vectorCrossProduct(vectD, vectE); delete []vectD; delete []vectE; return result; }
bool pointInPoly (const VECTOR3 * const point, int points, const VECTOR3 * const poly) { VECTOR3 u, v, plane; enum dim_drop drop; int i = 0, side, sideMatch = 10; float x, y, px[2], py[2]; if (points < 3) return false; u = vectorSubtract (&poly[1], &poly[0]); v = vectorSubtract (&poly[2], &poly[0]); plane = vectorCross (&u, &v); drop = (fabs(plane.x) > fabs(plane.y)) ? (fabs(plane.x) > fabs(plane.z)) ? DROP_X : DROP_Z : (fabs(plane.y) > fabs(plane.z)) ? DROP_Y : DROP_Z; //printf ("dropping %c\n", drop == DROP_X ? 'X' : drop == DROP_Y ? 'Y' : 'Z'); x = (drop == DROP_X) ? point->y : point->x; y = (drop == DROP_Z) ? point->y : point->z; px[1] = (drop == DROP_X) ? poly[points-1].y : poly[points-1].x; py[1] = (drop == DROP_Z) ? poly[points-1].y : poly[points-1].z; while (i < points) { px[0] = px[1]; py[0] = py[1]; px[1] = (drop == DROP_X) ? poly[i].y : poly[i].x; py[1] = (drop == DROP_Z) ? poly[i].y : poly[i].z; side = turns (x, y, px[0], py[0], px[1], py[1]); //printf ("%.2f, %.2f vs. %.2f, %.2f -> %.2f, %.2f: %c\n", x, y, px[0], py[0], px[1], py[1], d == RIGHT ? 'R' : d == LEFT ? 'L' : 'T'); if (sideMatch != 10 && side != sideMatch) return false; sideMatch = side; i++; } return true; }
// If the ray intersects the sphere, return nearest distance along ray at which // it happens. If it doesn't, return -1 int sphereIntersection(struct Sphere sphere, struct Ray ray) { // The intersection algorithm assumes that the ray starts at the origin, // so translate the sphere first. sphere.position = vectorSubtract(sphere.position, ray.origin); int directionDotPosition = \ vectorUnitDotProduct2(sphere.position, ray.direction); int sqrtTerm = fp_mult(directionDotPosition,directionDotPosition) \ - vectorDotProduct(sphere.position, sphere.position) \ + fp_mult(sphere.radius,sphere.radius); int result = -1; // Return value for no intersection if (sqrtTerm >= 0) // If there is an intersection (more likely 2) { sqrtTerm = fp_sqrt(sqrtTerm); // There are usually two solutions, for the two intersection points // between the ray and sphere. int solution1 = directionDotPosition + sqrtTerm; int solution2 = directionDotPosition - sqrtTerm; // We want the nearest non-negative (behind the ray origin) intersection if (solution1 >= 0) { result = solution1; if (solution2 >= 0 && solution2 < solution1) result = solution2; } else if (solution2 >= 0) result = solution2; } return result; }
void OWTriangle::defaulGeneralCalNorVec() { OWVector4* AB = vectorSubtract(&(myVector[1]),&(myVector[0])); OWVector4* AC = vectorSubtract(&(myVector[2]),&(myVector[0])); OWVector4* tempVec = crossProduct(AB,AC); float tempx, tempy, tempz; tempx = tempVec->getX(); tempy = tempVec->getY(); tempz = tempVec->getZ(); generalNorVec.setX(tempx); generalNorVec.setY(tempy); generalNorVec.setZ(tempz); for (int i=0; i<3; i++) { norVec[i].setX(tempx); norVec[i].setY(tempy); norVec[i].setZ(tempz); } delete tempVec; delete AB; delete AC; }
// check if one object has collided with another object // returns true if the two objects have collided bool checkCollision(movableObject& obj1, movableObject& obj2) { vector2 diff = vectorSubtract(obj1.position, obj2.position); float mag = getMagnitude(diff); if(mag > 0 && mag < obj1.height){ // collision obj1.speed = multiplyScalar( getNormal(diff), 5); obj2.speed = multiplyScalar( getNormal(diff), -5); return true; } return false; }
// Gets a sphere that completely surrounds a bounding box _C3DTSpheroid sphereFromBounds(_C3DTBounds b) { _C3DTSpheroid s; // Center is the middle point between the 2 bounds coordinate s.center.cartesian.x = (b.topRightFar.cartesian.x + b.bottomLeftNear.cartesian.x) / 2.0f; s.center.cartesian.y = (b.topRightFar.cartesian.y + b.bottomLeftNear.cartesian.y) / 2.0f; s.center.cartesian.z = (b.topRightFar.cartesian.z + b.bottomLeftNear.cartesian.z) / 2.0f; s.radius = vectorLength( vectorSubtract(b.topRightFar, s.center)); return s; }
int main() { // Create a drawing grid struct winsize terminal; ioctl(STDOUT_FILENO, TIOCGWINSZ, &terminal); int w = terminal.ws_col, h = terminal.ws_row - 1; Grid grid = gridInit(w, h); Vector v1 = vectorMake(20, 0, 0); Vector v2 = vectorMake(0, 10, 0); Vector center = vectorMake((int)w/2, (int)h, 0); Vector zero = vectorMake(0, 0, 0); Vector v3 = vectorSubtract(v1, v2); // A mechanism for delay between draws struct timespec t; t.tv_sec = 0; //1; t.tv_nsec = 1000 * 1000 * 100; // Rotation int degrees = 0, x = 0, y = 0, z = 0; double radians; Vector v4; int test = 1; while (test) { // Calculations v4 = vectorRotate(v1, degrees); degrees += 6; // Erase the grid //grid = gridInit(w, h); // Draw a vector drawVectorAtOrigin(v4, center, grid); // Flush grid to the terminal gridDraw(grid); //v1.y++; nanosleep(&t, NULL); } return 0; }
// Calculate the refraction when vector n1 goes from a material with refractive // index mu1 into one with refractive index mu2, via a surface with normal s // (s goes in the direction in to the new material, so may actually be the // inverse of the collision-object surface normal depending on if the ray is // entering or exiting the object) struct Vector3 vectorRefract(struct Vector3 n1, struct Vector3 s, int mu1, int mu2) { int n1DotS = vectorUnitDotProduct(n1,s); struct Vector3 firstTerm = vectorScalarMultiply(s,n1DotS); int sqrtTerm = fp_sqrt( (fp_mult(mu2,mu2)) - \ (fp_mult(mu1,mu1)) + \ (fp_mult(n1DotS,n1DotS)) ); struct Vector3 result = \ vectorAdd( vectorSubtract(n1, firstTerm), vectorScalarMultiply(s, sqrtTerm) ); return result; }
void v2c (const VECTOR3 * const vector, int * x, int * y) { int xGrid, yGrid, i = 0; VECTOR3 offset, centre; assert (x != NULL && y != NULL); xGrid = (int)(vector->x / 45.0); yGrid = (int)((vector->z - xGrid * 26.0) / 52.0); centre = hex_xyCoord2Space (xGrid, yGrid); offset = vectorSubtract (vector, ¢re); if (pointInHex (&offset)) { *x = xGrid; *y = yGrid; //printf ("%.2f, %.2f -> %d, %d\n", vector->x, vector->z, *x, *y); return; } while (i < 6) { centre = hex_xyCoord2Space (xGrid + XY[i][X], yGrid + XY[i][Y]); offset = vectorSubtract (vector, ¢re); if (pointInHex (&offset)) { *x = xGrid + XY[i][X]; *y = yGrid + XY[i][Y]; //printf ("%.2f, %.2f -> %d, %d\n", vector->x, vector->z, *x, *y); return; } i++; } assert (false); }
bool line_triHit (const LINE3 * const line, const VECTOR3 * const tri, float * tAtIntersection) { VECTOR3 u, v, triPlane, hit; LINE3 transLine; float t, weight[3]; u = vectorSubtract (&tri[2], &tri[0]); v = vectorSubtract (&tri[1], &tri[0]); triPlane = vectorCross (&u, &v); // the planeHit code doesn't have a magnitude argument so it's always a test against the plane through the origin. thus to accurately test we have to translate the line so that it's positioned relative to the plane origin (which we're arbitrarily using tri->pts[0] as) - xph 02 13 2012 transLine.origin = vectorSubtract (&line->origin, &tri[0]); transLine.dir = line->dir; if (!line_planeHit (&transLine, &triPlane, &t)) return false; hit = vectorCreate ( transLine.origin.x + line->dir.x * t, transLine.origin.y + line->dir.y * t, transLine.origin.z + line->dir.z * t ); baryWeights (&hit, &u, &v, weight); if (weight[0] >= 0.00 && weight[0] <= 1.00 && weight[1] >= 0.00 && weight[1] <= 1.00 && weight[2] >= 0.00 && weight[2] <= 1.00) { if (tAtIntersection) *tAtIntersection = t; return true; } return false; }
//check if two objects have collided with one another, return true if collided bool checkCollision(movableObject& obj1, movableObject& obj2, bool bBall) { vector2 vDifference = vectorSubtract(obj1.v2Position, obj2.v2Position); float fMag = getMagnitude(vDifference); if( fMag > 0 && fMag < obj1.iHeight ) { if( !bBall ) { //collide obj1.v2Speed = multiplyScalar( getNormal(vDifference), 5 ); obj2.v2Speed = multiplyScalar( getNormal(vDifference), -5 ); } return true; } return false; }
void textureDrawLine (TEXTURE t, VECTOR3 start, VECTOR3 end) { VECTOR3 diff = vectorSubtract (&end, &start), norm = vectorNormalize (&diff), current = start; /* i'm using i/max as a counter since due to floating point rounding error * it's not feasible to use vector_cmp (¤t, &end), which is the only * other way i can think of to check for when the line is actually done * - xph 2011 08 27 */ int i = 0, max = vectorMagnitude (&diff) + 1; /* if start is out of bounds skip ahead until it isn't (if it isn't), and * if it goes out of bounds again then it's not coming back. this is * important if start is out of bounds but end isn't (or if they're both * oob but they cross the image edge at some point); the start of the line * won't be drawn but stopping after the first oob coordiante would be * wrong * (there's a better way to do this: if either value is oob, calculate the * intersection of the line w/ the screen edges and jump to that point * without needing to loop) * - xph 2011 08 27 */ while (textureOOB (t, current) && i < max) { current = vectorAdd (¤t, &norm); i++; } while (i < max) { if (textureOOB (t, current)) break; textureDrawPixel (t, current); current = vectorAdd (¤t, &norm); i++; } }
void gluLookAt( vec3_t vEye, vec3_t vLookat, vec3_t vUp ,matrix_t fModelView) { vec3_t vN,vU,vV; // determine the new n vectorSubtract(vEye,vLookat,vN); // determine the new u by crossing with the up vector vectorCrossProduct(vUp, vN, vU) ; // normalize both the u and n vectors normalize(vU) ; normalize(vN); // determine v by crossing n and u vectorCrossProduct(vN,vU,vV); // create a model view matrix fModelView[0] = vU[0]; fModelView[4] = vU[1]; fModelView[8] = vU[2]; fModelView[12] = - DotProduct(vEye,vU); fModelView[1] = vV[0]; fModelView[5] = vV[1]; fModelView[9] = vV[2]; fModelView[13] = - DotProduct(vEye,vV); fModelView[2] = vN[0]; fModelView[6] = vN[1]; fModelView[10]= vN[2]; fModelView[14]= - DotProduct(vEye,vN); fModelView[3]= 0.0f; fModelView[7]= 0.0f; fModelView[11]= 0.0f; fModelView[15]= 1.0f; }
void drawTriangleToRaster(OWRaster *raster, OWTriangle& triangle, OWMaterial material, OWScene scene, bool phong, OWVector4* camPosition) { OWColorFloat* fillcolorF = material.color; unsigned rasterHeight = raster->getHeight(); unsigned rasterWidth = raster->getWidth(); float lambda1; float lambda2; float lambda3; float zDepth; lambda1=lambda3=lambda2=0.0f; float zb1=triangle.zBuffer[0]; float zb2=triangle.zBuffer[1]; float zb3=triangle.zBuffer[2]; float xLength = scene.maxX - scene.minX; float yLength = scene.maxY - scene.minY; float x1,x2,x3,y1,y2,y3,z1,z2,z3; x1 = triangle.getVec1().getX(); x2 = triangle.getVec2().getX(); x3 = triangle.getVec3().getX(); y1 = triangle.getVec1().getY(); y2 = triangle.getVec2().getY(); y3 = triangle.getVec3().getY(); z1 = triangle.getVec1().getZ(); z2 = triangle.getVec2().getZ(); z3 = triangle.getVec3().getZ(); float maxTX=fminf(scene.maxX,fmaxf(x1, fmaxf(x2, x3))); float maxTY=fminf(scene.maxY,fmaxf(y1, fmaxf(y2, y3))); float minTX=fmaxf(scene.minX,fminf(x1, fminf(x2, x3))); float minTY=fmaxf(scene.minY,fminf(y1, fminf(y2, y3))); unsigned maxRX = ceilf(fminf(rasterWidth, (maxTX - scene.minX)/xLength*(float)rasterWidth)); unsigned minRX = floorf(fmaxf(0.0f, (minTX - scene.minX)/xLength*(float)rasterWidth)); unsigned maxRY = ceilf(fminf(rasterWidth, (maxTY - scene.minY)/yLength*(float)rasterHeight)); unsigned minRY = floorf(fmaxf(0.0f, (minTY - scene.minY)/yLength*(float)rasterHeight)); if (maxRX > rasterWidth) { printf("raster x max bound error.\n"); //system("pause"); maxRX = rasterWidth; } if (maxRY > rasterHeight) { printf("raster y max bound error.\n"); //system("pause"); maxRY = rasterHeight; } for (unsigned y=minRY; y<maxRY; y++) { for (unsigned x=minRX; x<maxRX; x++) { float fx=((float)x/(float)rasterWidth) * xLength+scene.minX; float fy=((float)y/(float)rasterHeight)* yLength+scene.minY; calculateTriBarycentricCoordinates(triangle, fx, fy, &lambda1, &lambda2, &lambda3); zDepth = zb1*lambda1 + zb2*lambda2 + zb3*lambda3; if( lambda1 >= 0.0f && lambda2 >= 0.0f && lambda3 >= 0.0f //&& (lambda1 <= 0.02f || lambda2 <= 0.02f || lambda3 <= 0.02f) && raster->z_buffer[x + y * rasterWidth] > zDepth //lambda1 <= 1.0f && lambda2 <= 1.0f && lambda3 <= 1.0f ) { raster->z_buffer[x + y * rasterWidth] = zDepth; OWColorChannelFloat red,green,blue; red = fillcolorF[0].r * lambda1 + fillcolorF[1].r * lambda2 + fillcolorF[2].r * lambda3; green = fillcolorF[0].g * lambda1 + fillcolorF[1].g * lambda2 + fillcolorF[2].g * lambda3; blue = fillcolorF[0].b * lambda1 + fillcolorF[1].b * lambda2 + fillcolorF[2].b * lambda3; if (phong == true) { /***Phong Mode*************************************************************************************/ for (list<OWLight>::iterator iterLight = scene.lightList.begin(); iterLight != scene.lightList.end(); iterLight++) { OWVector4* currVector = new OWVector4; OWVector4* n = new OWVector4; currVector->setX(triangle.worldCoorVec[0].getX() * lambda1 + triangle.worldCoorVec[1].getX() * lambda2 + triangle.worldCoorVec[2].getX() * lambda3); currVector->setY(triangle.worldCoorVec[0].getY() * lambda1 + triangle.worldCoorVec[1].getY() * lambda2 + triangle.worldCoorVec[2].getY() * lambda3); currVector->setZ(triangle.worldCoorVec[0].getZ() * lambda1 + triangle.worldCoorVec[1].getZ() * lambda2 + triangle.worldCoorVec[2].getZ() * lambda3); for (int i=0; i<3; i++) { triangle.norVec[i].normalise(); } n->setX(triangle.norVec[0].getX() * lambda1 + triangle.norVec[1].getX() * lambda2 + triangle.norVec[2].getX() * lambda3); n->setY(triangle.norVec[0].getY() * lambda1 + triangle.norVec[1].getY() * lambda2 + triangle.norVec[2].getY() * lambda3); n->setZ(triangle.norVec[0].getZ() * lambda1 + triangle.norVec[1].getZ() * lambda2 + triangle.norVec[2].getZ() * lambda3); OWVector4* l = vectorSubtract((*iterLight).myPosition, currVector); l->normalise(); n->normalise(); float l_dot_n = l->dotProduct(*n); float diffContr = fmaxf(0.0f, l_dot_n); n->scale(2*l_dot_n); OWVector4* r = vectorSubtract(n,l); OWVector4* v = vectorSubtract(camPosition, currVector); r->normalise(); v->normalise(); OWColorFloat Idif; if (diffContr < 0.0f) { diffContr = 0.0f; } Idif.a=1.0f; Idif.r=(*iterLight).myColor.r * red * diffContr; Idif.g=(*iterLight).myColor.g * green * diffContr; Idif.b=(*iterLight).myColor.b * blue * diffContr; OWColorFloat shininessColor = material.shininessColor; OWColorFloat Ispec; float specContri = powf(v->dotProduct(*r), shininessColor.a); //float specContri = v->dotProduct(*r); if ( l_dot_n >= 0.0f && specContri >= 0.0f ) { Ispec.a = 1.0f; Ispec.r = (*iterLight).myColor.r * shininessColor.r * specContri; Ispec.g = (*iterLight).myColor.g * shininessColor.g * specContri; Ispec.b = (*iterLight).myColor.b * shininessColor.b * specContri; }else{ Ispec.a = 0.0f; Ispec.r = 0.0f; Ispec.g = 0.0f; Ispec.b = 0.0f; } scene.ambient.a = 0.0f; //OWColorFloat tempColor = Idif; //OWColorFloat tempColor = Ispec; //OWColorFloat tempColor = scene.ambient; //OWColorFloat tempColor = colorAdd(Idif, scene.ambient); //OWColorFloat tempColor = colorAdd(Idif, Ispec); OWColorFloat tempColor = colorAdd(Idif, colorAdd(Ispec, scene.ambient)); colorNormalise(tempColor); red = tempColor.r; green = tempColor.g; blue = tempColor.b; } } raster->pixels[x + y * rasterWidth] = drawARGBColorFromFloatColor(red, green, blue); } } } //triangle.printMyself(); }
void MD5_GenerateLightingInfo (md5_mesh_t* mesh) { int verticesCounter; int weightCounter; //User for tangent space generation vec3_t v1,v2,normal; vec3_t* normalAccumulator; vec3_t* normalWeightAccumulator; vec3_t tangent; float coef; vec3_t jointSpaceTangent; vec2_t st1,st2; vec3_t* tangentAccumulator; vec3_t* tangentWeightAccumulator; vertex_t* currentVertex = NULL; md5_vertex_t* md5Vertex; int facesCounter; md5_weight_t* weight; md5_bone_t* bone; md5_triangle_t* currentFace; vec3_t jointSpaceNormal; normalAccumulator = calloc(mesh->numVertices, sizeof(vec3_t)); normalWeightAccumulator = calloc(mesh->numWeights, sizeof(vec3_t)); tangentAccumulator = calloc(mesh->numVertices, sizeof(vec3_t)); tangentWeightAccumulator= calloc(mesh->numWeights, sizeof(vec3_t)); //printf("\nGenerating normal and tangents.\n"); //Generate the normal and tangent per face currentFace = mesh->triangles; for(facesCounter = 0; facesCounter < mesh->numTriangles ; facesCounter++,currentFace++) { // Normal part vectorSubtract(mesh->vertexArray[currentFace->index[2]].pos , mesh->vertexArray[currentFace->index[0]].pos, v1); vectorSubtract(mesh->vertexArray[currentFace->index[1]].pos , mesh->vertexArray[currentFace->index[0]].pos, v2); vectorCrossProduct(v2,v1,normal); normalize(normal); vectorAdd(normalAccumulator[currentFace->index[0]],normal,normalAccumulator[currentFace->index[0]]); vectorAdd(normalAccumulator[currentFace->index[1]],normal,normalAccumulator[currentFace->index[1]]); vectorAdd(normalAccumulator[currentFace->index[2]],normal,normalAccumulator[currentFace->index[2]]); // The following part is from "Mathematic for 3D programming" by Eric Lengyel // Tangent part vector2Subtract(mesh->vertexArray[currentFace->index[2]].text,mesh->vertexArray[currentFace->index[0]].text,st1); vector2Subtract(mesh->vertexArray[currentFace->index[1]].text,mesh->vertexArray[currentFace->index[0]].text,st2); vector2Scale(st1,1/(float)32767,st1); vector2Scale(st2,1/(float)32767,st2); if (st1[0] == 0.0f && st2[0] == 0.0f) { st1[0] = 0.1f ; st2[0] = 0.1f; } if (st1[1] == 0.0f && st2[1] == 0.0f) { st1[1] = 0.1f ; st2[1] = 0.1f; } coef = 1/ (st1[0] * st2[1] - st2[0] * st1[1]); tangent[0] = coef * (v1[0] * st2[1] + v2[0] * -st1[1]); tangent[1] = coef * (v1[1] * st2[1] + v2[1] * -st1[1]); tangent[2] = coef * (v1[2] * st2[1] + v2[2] * -st1[1]); normalize(tangent); vectorAdd(tangentAccumulator[currentFace->index[0]],tangent,tangentAccumulator[currentFace->index[0]]); vectorAdd(tangentAccumulator[currentFace->index[1]],tangent,tangentAccumulator[currentFace->index[1]]); vectorAdd(tangentAccumulator[currentFace->index[2]],tangent,tangentAccumulator[currentFace->index[2]]); } //Normalize accumulated normal and tangent for(verticesCounter=0 ; verticesCounter < mesh->numVertices ; verticesCounter++,currentVertex++) { normalize(normalAccumulator[verticesCounter]); // printf("normalized accumulated normal [%d][%.2f,%.2f,%.2f]\n",verticesCounter,normalAccumulator[verticesCounter][0],normalAccumulator[verticesCounter][1],normalAccumulator[verticesCounter][2]); normalize(tangentAccumulator[verticesCounter]); // printf("normalized accumulated tangent [%d][%.2f,%.2f,%.2f]\n",verticesCounter,tangentAccumulator[verticesCounter][0],tangentAccumulator[verticesCounter][1],tangentAccumulator[verticesCounter][2]); } //Now we have all the normal for this model, but need to transform them in bone space for re-usage // Translating the normal orientation from object to joint space and Store normals inside weights, md5Vertex = mesh->vertices; currentVertex = mesh->vertexArray; for(verticesCounter=0 ; verticesCounter < mesh->numVertices ; verticesCounter++,md5Vertex++) { for (weightCounter = 0; weightCounter < md5Vertex->count; weightCounter++) { weight = &mesh->weights[md5Vertex->start + weightCounter]; bone = &mesh->bones[weight->boneId]; multiplyByInvertQuaternion(normalAccumulator[verticesCounter],bone->orientation,jointSpaceNormal); vectorAdd(normalWeightAccumulator[md5Vertex->start + weightCounter],jointSpaceNormal,normalWeightAccumulator[md5Vertex->start + weightCounter]); multiplyByInvertQuaternion(tangentAccumulator[verticesCounter],bone->orientation,jointSpaceTangent); vectorAdd(tangentWeightAccumulator[md5Vertex->start + weightCounter],jointSpaceTangent,tangentWeightAccumulator[md5Vertex->start + weightCounter]); } } weight = mesh->weights; for (weightCounter = 0; weightCounter < mesh->numWeights; weightCounter++,weight++) { normalize(normalWeightAccumulator[weightCounter]); vectorScale(normalWeightAccumulator[weightCounter],32767,weight->boneSpaceNormal); normalize(tangentWeightAccumulator[weightCounter]); vectorScale(tangentWeightAccumulator[weightCounter],32767,weight->boneSpaceTangent); } free(normalAccumulator); free(normalWeightAccumulator); free(tangentAccumulator); free(tangentWeightAccumulator); }
void Lines::update() { //Skip update if count hasn't changed //To force update, set geometry->reload = true if (reload) elements = 0; if (elements > 0 && (linetotal == (unsigned int)elements || total == 0)) return; tris->clear(); tris->setView(view); //Count 2d lines linetotal = 0; for (unsigned int i=0; i<geom.size(); i++) { //Force true as default here, global default is false for "flat" if (all2d || (geom[i]->draw->properties.getBool("flat", true) && !geom[i]->draw->properties["tubes"])) linetotal += geom[i]->count; } //Copy data to Vertex Buffer Object // VBO - copy normals/colours/positions to buffer object unsigned char *p, *ptr; ptr = p = NULL; int datasize = sizeof(float) * 3 + sizeof(Colour); //Vertex(3), and 32-bit colour int bsize = linetotal * datasize; if (linetotal > 0) { //Initialise vertex buffer if (!vbo) glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); if (glIsBuffer(vbo)) { glBufferData(GL_ARRAY_BUFFER, bsize, NULL, GL_STATIC_DRAW); debug_print(" %d byte VBO created for LINES, holds %d vertices\n", bsize, bsize/datasize); ptr = p = (unsigned char*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); GL_Error_Check; } if (!p) abort_program("VBO setup failed"); } clock_t t1,t2,tt; tt=clock(); counts.clear(); counts.resize(geom.size()); any3d = false; for (unsigned int i=0; i<geom.size(); i++) { t1=tt=clock(); Properties& props = geom[i]->draw->properties; //Calibrate colour maps on range for this object geom[i]->colourCalibrate(); float limit = props["limit"]; bool linked = props["link"]; if (all2d || (props.getBool("flat", true) && !props["tubes"])) { int hasColours = geom[i]->colourCount(); int colrange = hasColours ? geom[i]->count / hasColours : 1; if (colrange < 1) colrange = 1; debug_print("Using 1 colour per %d vertices (%d : %d)\n", colrange, geom[i]->count, hasColours); Colour colour; for (unsigned int v=0; v < geom[i]->count; v++) { if (!internal && geom[i]->filter(i)) continue; //Check length limit if applied (used for periodic boundary conditions) //NOTE: will not work with linked lines, require separated segments if (!linked && v%2 == 0 && v < geom[i]->count-1 && limit > 0.f) { Vec3d line; vectorSubtract(line, geom[i]->vertices[v+1], geom[i]->vertices[v]); if (line.magnitude() > limit) { //Skip next two vertices v++; continue; } } //Have colour values but not enough for per-vertex, spread over range (eg: per segment) int cidx = v / colrange; if (cidx >= hasColours) cidx = hasColours - 1; geom[i]->getColour(colour, cidx); //if (cidx%100 ==0) printf("COLOUR %d => %d,%d,%d\n", cidx, colour.r, colour.g, colour.b); //Write vertex data to vbo assert((int)(ptr-p) < bsize); //Copies vertex bytes memcpy(ptr, &geom[i]->vertices[v][0], sizeof(float) * 3); ptr += sizeof(float) * 3; //Copies colour bytes memcpy(ptr, &colour, sizeof(Colour)); ptr += sizeof(Colour); //Count of vertices actually plotted counts[i]++; } t2 = clock(); debug_print(" %.4lf seconds to reload %d vertices\n", (t2-t1)/(double)CLOCKS_PER_SEC, counts[i]); t1 = clock(); elements += counts[i]; } else { any3d = true; //Flag 3d tubes drawn //Create a new data store for output geometry tris->add(geom[i]->draw); //3d lines - using triangle sub-renderer geom[i]->draw->properties.data["lit"] = true; //Override lit //Draw as 3d cylinder sections int quality = 4 * (int)props["glyphs"]; float scaling = props["scalelines"]; //Don't apply object scaling to internal lines objects if (!internal) scaling *= (float)props["scaling"]; float radius = scaling*0.1; float* oldpos = NULL; Colour colour; for (unsigned int v=0; v < geom[i]->count; v++) { if (v%2 == 0 && !linked) oldpos = NULL; float* pos = geom[i]->vertices[v]; if (oldpos) { tris->drawTrajectory(geom[i]->draw, oldpos, pos, radius, radius, -1, view->scale, limit, quality); //Per line colours (can do this as long as sub-renderer always outputs same tri count) geom[i]->getColour(colour, v); tris->read(geom[i]->draw, 1, lucRGBAData, &colour.value); } oldpos = pos; } //Adjust bounding box tris->compareMinMax(geom[i]->min, geom[i]->max); } } if (linetotal > 0) { glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, 0); } GL_Error_Check; t1 = clock(); debug_print("Plotted %d lines in %.4lf seconds\n", linetotal, (t1-tt)/(double)CLOCKS_PER_SEC); tris->update(); }
void GenerateLightingInfo (const md5_mesh_t *mesh, md5_joint_t *skeleton) { int verticesCounter; int weightCounter; //User for tangent space generation vec3_t v1,v2,normal; vec3_t* normalAccumulator; vec3_t* normalWeightAccumulator; #ifdef TANGENT_ENABLED vec3_t tangent; float coef; vec3_t jointSpaceTangent; vec2_t st1,st2; vec3_t* tangentAccumulator; vec3_t* tangentWeightAccumulator; #endif vertex_t* currentVertex = NULL; md5_vertex_t* md5Vertex; int facesCounter; md5_weight_t* weight; md5_joint_t* joint; md5_triangle_t* currentFace; vec3_t jointSpaceNormal; normalAccumulator = calloc(mesh->num_verts, sizeof(vec3_t)); normalWeightAccumulator = calloc(mesh->num_weights, sizeof(vec3_t)); #ifdef TANGENT_ENABLED tangentAccumulator = calloc(mesh->num_verts, sizeof(vec3_t)); tangentWeightAccumulator = calloc(mesh->num_weights, sizeof(vec3_t)); #endif //Set all textures coordinate once for all. currentVertex = mesh->vertexArray; for(verticesCounter=0 ; verticesCounter < mesh->num_verts ; verticesCounter++,currentVertex++) { currentVertex->text[0] = mesh->vertices[verticesCounter].st[0]; currentVertex->text[1] = mesh->vertices[verticesCounter].st[1]; } currentFace = mesh->triangles; for(facesCounter = 0; facesCounter < mesh->num_tris ; facesCounter++,currentFace++) { // Normal part vectorSubtract(mesh->vertexArray[currentFace->index[2]].pos , mesh->vertexArray[currentFace->index[0]].pos, v1); vectorSubtract(mesh->vertexArray[currentFace->index[1]].pos , mesh->vertexArray[currentFace->index[0]].pos, v2); vectorCrossProduct(v2,v1,normal); vectorAdd(normalAccumulator[currentFace->index[0]],normal,normalAccumulator[currentFace->index[0]]); vectorAdd(normalAccumulator[currentFace->index[1]],normal,normalAccumulator[currentFace->index[1]]); vectorAdd(normalAccumulator[currentFace->index[2]],normal,normalAccumulator[currentFace->index[2]]); // The following part is from "Mathematic for 3D programming" by Eric Lengyel // Tangent part #ifdef TANGENT_ENABLED vector2Subtract(mesh->vertexArray[currentFace->index[2]].text,mesh->vertexArray[currentFace->index[0]].text,st1); vector2Subtract(mesh->vertexArray[currentFace->index[1]].text,mesh->vertexArray[currentFace->index[0]].text,st2); coef = 1/ (st1[0] * st2[1] - st2[0] * st1[1]); tangent[0] = coef * (v1[0] * st2[1] + v2[0] * -st1[1]); tangent[1] = coef * (v1[1] * st2[1] + v2[1] * -st1[1]); tangent[2] = coef * (v1[2] * st2[1] + v2[2] * -st1[1]); vectorAdd(tangentAccumulator[currentFace->index[0]],tangent,tangentAccumulator[currentFace->index[0]]); vectorAdd(tangentAccumulator[currentFace->index[1]],tangent,tangentAccumulator[currentFace->index[1]]); vectorAdd(tangentAccumulator[currentFace->index[2]],tangent,tangentAccumulator[currentFace->index[2]]); #endif } for(verticesCounter=0 ; verticesCounter < mesh->num_verts ; verticesCounter++,currentVertex++) { normalize(normalAccumulator[verticesCounter]); #ifdef TANGENT_ENABLED normalize(tangentAccumulator[verticesCounter]); #endif } //Now we have all the normal for this model, but need to transform them in bone space for re-usage // Translating the normal orientation from object to joint space and Store normals inside weights, md5Vertex = mesh->vertices; currentVertex = mesh->vertexArray; for(verticesCounter=0 ; verticesCounter < mesh->num_verts ; verticesCounter++,md5Vertex++) { for (weightCounter = 0; weightCounter < md5Vertex->count; weightCounter++) { weight = &mesh->weights[md5Vertex->start + weightCounter]; joint = &skeleton[weight->joint]; multiplyByInvertQuaternion(normalAccumulator[verticesCounter],joint->orient,jointSpaceNormal); vectorAdd(normalWeightAccumulator[md5Vertex->start + weightCounter],jointSpaceNormal,normalWeightAccumulator[md5Vertex->start + weightCounter]); #ifdef TANGENT_ENABLED multiplyByInvertQuaternion(tangentAccumulator[verticesCounter],joint->orient,jointSpaceTangent); vectorAdd(tangentWeightAccumulator[md5Vertex->start + weightCounter],jointSpaceTangent,tangentWeightAccumulator[md5Vertex->start + weightCounter]); #endif } } weight = mesh->weights; for (weightCounter = 0; weightCounter < mesh->num_weights; weightCounter++,weight++) { normalize(normalWeightAccumulator[weightCounter]); vectorScale(normalWeightAccumulator[weightCounter],32767,weight->normal); #ifdef TANGENT_ENABLED normalize(tangentWeightAccumulator[weightCounter]); vectorScale(tangentWeightAccumulator[weightCounter],32767,weight->tangent); #endif } free(normalAccumulator); free(normalWeightAccumulator); #ifdef TANGENT_ENABLED free(tangentAccumulator); free(tangentWeightAccumulator); #endif }
// Returns (b-a) x (c-a) inline C3DTVector vectorCrossProductTri(const C3DTVector a, const C3DTVector b, const C3DTVector c) { return vectorCrossProduct(vectorSubtract(b,a), vectorSubtract(c,a)); }
// calculate height at (x,y) with plane float Terrain::getHeight (float x_float, float z_float, Angle &a) { Vector v1, v2, v3, normal, ab, bc; Plane plane; bool up; int res_int = (int) res; int x = (int) (x_float); int z = (int) (z_float); int xs, zs; xs = (int) ((x+size/2) / res_int) * res_int - (size/2); zs = (int) ((z+size/2) / res_int) * res_int - (size/2); // FIND PLANE EQUATION (Ax + By + Cz + D) // find triangle - START // mi servono i vertici della diagonale -> 0 e 2 v1.x = xs; v1.z = zs; v1.y = getHeightFromMap (v1.x+size/2, v1.z+size/2); v3.x = xs + res; v3.z = zs + res; v3.y = getHeightFromMap (v3.x+size/2, v3.z+size/2); // calcolo la retta passante per i punti float rect_z = v3.z * ((xs-v1.x)/(v3.x-v1.x)); if (z_float > rect_z) up = true; else up = false; // find triangle - END if (up) { v2.x = xs; v2.z = zs + res; v2.y = getHeightFromMap (v2.x+size/2, v2.z+size/2); } else { v2.x = xs + res; v2.z = zs; v2.y = getHeightFromMap (v2.x+size/2, v2.z+size/2); } // calculate plane equation vectorSubtract (v1, v2, ab); vectorSubtract (v2, v3, bc); crossProduct (ab, bc, normal); makePlane (v1, normal, plane); // calculate height float height = (plane.d - (plane.a * x_float) - (plane.c * z_float)) / plane.b; // calculate angle x Vector temp_vec; temp_vec.x = 1.0; temp_vec.y = 0.0; temp_vec.z = 0.0; float temp_angle_x = vectorAngle (temp_vec, normal); a.x = 90.0 - temp_angle_x; // calculate angle z temp_vec.x = 0.0; temp_vec.y = 0.0; temp_vec.z = 1.0; float temp_angle_z = vectorAngle (temp_vec, normal); a.z = 90.0 - temp_angle_z; // return height return height; }