void line(float x0, float y0, float x1, float y1, GzRender *render) { float dx = x1 - x0; float dy = y1 - y0; float m = dy/dx; float x = x0, y = y0; for(x = x0; x <= x1; x++) { GzIntensity red, green, blue, alpha; GzDepth oldZ; GzGetDisplay(render->display,x,y,&red,&green,&blue,&alpha,&oldZ); GzPutDisplay(render->display,x,y,ctoi(render->flatcolor[0]),ctoi(render->flatcolor[1]),ctoi(render->flatcolor[2]),alpha,oldZ); y = y + m; } }
void DoLEE(GzRender* render, GzCoord* tri) { /* float x1, y1, z1; float x2, y2, z2; float x3, y3, z3; */ GzPixel* pixel; vert vert1,vert2,vert3; edge triEdge[3]; checkBound bound; plane triPlane; //GzCoord *tri = (GzCoord*)verts[0]; GzDepth orgZ = 0; //depth //put value into verts putVertValue(tri[0], &vert1.coord); putVertValue(tri[1], &vert2.coord); putVertValue(tri[2], &vert3.coord); //sort verts using Y value getTri(&vert1, &vert2, &vert3, triEdge); getPlane(triEdge[0], triEdge[1], &triPlane, vert1); //get a rectangle bound to check value getCheckBound(&bound, vert1, vert2, vert3); //TRACE("minX: %f, maxX: %f, minY: %f, maxY: %f \n", bound.minX, bound.maxX,bound.minY, bound.maxY); for(int i = bound.minY; i <= bound.maxY; i++) { for(int j = bound.minX; j <=bound.maxX; j++) { if(checkValid(j, i, triEdge)){ //implement later if((orgZ = getFbuf(render, j, i)) == -1)/*render->display->fbuf[RENDARRAY(j,i)].z;*/ { continue; } //TRACE("orgZ = %d\n", orgZ); if(checkZBuffer(j, i, triPlane,&orgZ)){ GzPutDisplay(render->display, j, i, ctoi(render->flatcolor[0]), ctoi(render->flatcolor[1]), ctoi(render->flatcolor[2]), 1, orgZ); //GzPutDisplay } } } } }
int render(BackBuffer* bf) { BitBlt(bf->back_dc, 0, 0, bf->width, bf->height, NULL, 0, 0, BLACKNESS ); //Render teapot to refraction texture render_teapot_refraction(renderer); GzCopyDisplay(refraction_display, renderer->display); //Render the model itself. //render_teapot(renderer); //skip rendering the teapot to save some time render_water_plane(renderer); //blend for(int i=0; i<refraction_display->xres; i++) { for(int j=0; j<refraction_display->yres; j++) { GzIntensity r,g,b,a; GzDepth z; GzGetDisplay(refraction_display, i, j, &r, &g, &b, &a, &z); if(a > 0) { GzIntensity r1,g1,b1,a1; GzDepth z1; GzGetDisplay(renderer->display, i, j, &r1, &g1, &b1, &a1, &z1); //blend with 0.6, 0.4 float blend_des = 0.6f, blend_src = 0.4f; r = r1*blend_des+ r*blend_src; g = g1*blend_des + g*blend_src; b = b1*blend_des + b*blend_src; GzPutDisplay(renderer->display, i,j,r,g,b,a,z); } } } flush_display(renderer->display, bf); return 0; }
//------------------------------------------------------------------------------ int GzPutTriangle(GzRender *render, int numParts, GzToken *nameList, GzPointer *valueList) { /* numParts : how many names and values */ // Do some sanity checking if(NULL == render || NULL == nameList || NULL == valueList || numParts != 3) { return GZ_FAILURE; } Matrix *Xsm = render->xStack.leftMulMatricesOnStack(); if (Xsm == NULL) { fprintf(stderr, "Got NULL from stack in GzPutTriangle.\n"); } GzCoord *c_old; GzCoord *n; GzColor triEdgeColors[3]; GzTextureIndex *triTextures; for (int i = 0; i < numParts; i++) { int name = nameList[i]; switch(name) { case GZ_POSITION: { // Get ready to read coordinates void *l1 = valueList; GzCoord **l2 = static_cast<GzCoord **> (l1); c_old = static_cast<GzCoord *> (l2[i]); break; } case GZ_NORMAL: { void *l1 = valueList; GzCoord **l2 = static_cast<GzCoord **> (l1); n = static_cast<GzCoord *> (l2[i]); if (render->interp_mode == GZ_COLOR) { for (int k = 0; k < 3; k++) calc_color(render, n[k], triEdgeColors[k], (render->tex_fun == false)); } break; } case GZ_TEXTURE_INDEX: { void *l1 = valueList; GzTextureIndex **l2 = static_cast<GzTextureIndex**> (l1); triTextures = l2[i]; break; } default: return GZ_FAILURE; }// end of switch statement }//end of for loop GzCoord c[3]; // Transform triangle coordinates into screen coordinates for(int i = 0; i < 3 ; i++) { float array[4] = {c_old[i][0], c_old[i][1], c_old[i][2], 1}; float rMulResult[4] ={0, 0, 0, 0}; Xsm->rightMultiply(array, 4, rMulResult); c[i][X] = rMulResult[0] + render->aa_delta_x; c[i][Y] = rMulResult[1] + render->aa_delta_y; c[i][Z] = rMulResult[2]; } // Lets see if all 3 triangle coordinates are viewable or not. if(isBehindViewPlane(render, c) || isClipped(render, c)) return GZ_FAILURE; // Find bounding box int x_min = floor(findMin(c, 0, 3)); int x_max = ceil (findMax(c, 0, 3)); int y_min = floor(findMin(c, 1, 3)); int y_max = ceil (findMax(c, 1, 3)); // Iterate over every pixel in the bounding box for(int j = y_min; j <= y_max; j++) for(int i = x_min; i <= x_max; i++) { // Calculate Barycentric coordinates GzCoord p = {float(i), float(j), 0}; float alpha = f(c[1], c[2], p) / f(c[1], c[2], c[0]); float beta = f(c[2], c[0], p) / f(c[2], c[0], c[1]); float gamma = f(c[0], c[1], p) / f(c[0], c[1], c[2]); // Litmus Test: Is pixel (i,j) inside triangle? if ( alpha > 0 && beta > 0 && gamma > 0) { //interpolate z value float newZ = alpha*(c[0][2]) + beta*(c[1][2]) + gamma*(c[2][2]); // Get current Z value for this specific pixel (i,j) GzIntensity dummy; GzDepth oldZ; GzGetDisplay(render->display, i, j, &dummy, &dummy, &dummy, &dummy, &oldZ); // Check will this pixel be displayed or not if(newZ < oldZ) { GzColor interpColor = {0, 0, 0}; GzColor color = {1.0f, 1.0f, 1.0f}; // color coming from texture if(render->tex_fun != false) calcTexture(render, triTextures, c, newZ, alpha, beta, gamma, color); if(render->interp_mode == GZ_NORMALS) // Phong Shading { GzCoord interpN = {0,0,0}; for (int k = 0; k < 3; k++) interpN[k] = alpha*n[0][k] + beta*n[1][k] + gamma*n[2][k]; if(render->tex_fun != false) { memcpy(render->Ka, color, sizeof (GzColor)); memcpy(render->Kd, color, sizeof (GzColor)); } calc_color(render, interpN, interpColor, true); GzPutDisplay(render->display, i, j, ctoi(interpColor[X]), ctoi(interpColor[Y]), ctoi(interpColor[Z]), 1, newZ); } else if(render->interp_mode == GZ_COLOR) // Gouraud Shading { float r = alpha * triEdgeColors[0][X] + beta * triEdgeColors[1][X] + gamma * triEdgeColors[2][X]; float g = alpha * triEdgeColors[0][Y] + beta * triEdgeColors[1][Y] + gamma * triEdgeColors[2][Y]; float b = alpha * triEdgeColors[0][Z] + beta * triEdgeColors[1][Z] + gamma * triEdgeColors[2][Z]; // Multiply by Kt which is in color due to earlier texture calculation r *= color[RED]; g *= color[GREEN]; b *= color[BLUE]; GzPutDisplay(render->display, i, j, ctoi(r), ctoi(g), ctoi(b), 1, newZ); } // FLAT Shading //GzPutDisplay(render->display, i, j, ctoi(render->flatcolor[0]), //ctoi(render->flatcolor[1]), ctoi(render->flatcolor[2]), 1, newZ); } }// end of litmus test if } return GZ_SUCCESS; }
int GzPutTriangle(GzRender *render, int numParts, GzToken *nameList, GzPointer *valueList) /* numParts : how many names and values */ { /* - pass in a triangle description with tokens and values corresponding to GZ_POSITION:3 vert positions in model space - Xform positions of verts using matrix on top of stack - Clip - just discard any triangle with any vert(s) behind view plane - optional: test for triangles with all three verts off-screen (trivial frustum cull) - invoke triangle rasterizer */ if ((NULL == render) || (NULL == nameList) || (NULL == valueList)) { return GZ_FAILURE; } for (int nCnt = 0; nCnt < numParts; nCnt++) { if (nameList[nCnt] == GZ_POSITION) { GzCoord* acGzCoord; acGzCoord = (GzCoord*)(valueList[nCnt]); GzMatrix topMat; int top = render->matlevel; memcpy(topMat, render->Ximage[top], sizeof(GzMatrix)); float aCoordMat[4][4] = { { acGzCoord[0][0], acGzCoord[1][0], acGzCoord[2][0], 0 }, { acGzCoord[0][1], acGzCoord[1][1], acGzCoord[2][1], 0 }, { acGzCoord[0][2], acGzCoord[1][2], acGzCoord[2][2], 0 }, { 1, 1, 1, 0 } }; float aCoordMatProduct[4][4]; MatrixProduct(topMat, aCoordMat, aCoordMatProduct); if ((aCoordMatProduct[3][0] == 0) || (aCoordMatProduct[3][1] == 0) || (aCoordMatProduct[3][2] == 0)) { continue; } #if 1 GzCoord asGzCoordX = { aCoordMatProduct[0][0] / aCoordMatProduct[3][0], aCoordMatProduct[0][1] / aCoordMatProduct[3][1], aCoordMatProduct[0][2] / aCoordMatProduct[3][2] }; GzCoord asGzCoordY = { aCoordMatProduct[1][0] / aCoordMatProduct[3][0], aCoordMatProduct[1][1] / aCoordMatProduct[3][1], aCoordMatProduct[1][2] / aCoordMatProduct[3][2] }; GzCoord asGzCoordZ = { aCoordMatProduct[2][0] / aCoordMatProduct[3][0], aCoordMatProduct[2][1] / aCoordMatProduct[3][1], aCoordMatProduct[2][2] / aCoordMatProduct[3][2] }; // clipping part if ((asGzCoordX[X] < 0 || asGzCoordX[X] > (render->display->xres)) && (asGzCoordX[Y] < 0 || asGzCoordX[Y] > (render->display->xres)) && (asGzCoordX[Z] < 0 || asGzCoordX[Z] > (render->display->xres))) { return GZ_FAILURE; } if ((asGzCoordY[X] < 0 || asGzCoordY[X] > (render->display->yres)) && (asGzCoordY[Y] < 0 || asGzCoordY[Y] > (render->display->yres)) && (asGzCoordY[Z] < 0 || asGzCoordY[Z] > (render->display->yres))) { return GZ_FAILURE; } if (asGzCoordZ[X] < 0 && asGzCoordZ[Y] < 0 && asGzCoordZ[Z] < 0) { return GZ_FAILURE; } #else GzCoord asGzCoordX = { acGzCoord[0][0], acGzCoord[1][0], acGzCoord[2][0] }; GzCoord asGzCoordY = { acGzCoord[0][1], acGzCoord[1][1], acGzCoord[2][1] }; GzCoord asGzCoordZ = { acGzCoord[0][2], acGzCoord[1][2], acGzCoord[2][2] }; #endif //Sort the matrix according to Y for (int anSortYCnt = 1; anSortYCnt < 3; anSortYCnt++) { if (asGzCoordY[anSortYCnt - 1] > asGzCoordY[anSortYCnt]) { float afSortTemmp; afSortTemmp = asGzCoordX[anSortYCnt - 1]; asGzCoordX[anSortYCnt - 1] = asGzCoordX[anSortYCnt]; asGzCoordX[anSortYCnt] = afSortTemmp; afSortTemmp = asGzCoordY[anSortYCnt - 1]; asGzCoordY[anSortYCnt - 1] = asGzCoordY[anSortYCnt]; asGzCoordY[anSortYCnt] = afSortTemmp; afSortTemmp = asGzCoordZ[anSortYCnt - 1]; asGzCoordZ[anSortYCnt - 1] = asGzCoordZ[anSortYCnt]; asGzCoordZ[anSortYCnt] = afSortTemmp; } } float afGzCoordY_Min = asGzCoordY[0]; // find min y float afGzCoordY_Max = asGzCoordY[2]; // find max y float tmp; for (int anSortYCnt = 1; anSortYCnt < 3; anSortYCnt++) { if ((asGzCoordY[anSortYCnt - 1] == asGzCoordY[anSortYCnt]) && (asGzCoordX[anSortYCnt - 1] > asGzCoordX[anSortYCnt])) { float afSortTemmp; afSortTemmp = asGzCoordX[anSortYCnt - 1]; asGzCoordX[anSortYCnt - 1] = asGzCoordX[anSortYCnt]; asGzCoordX[anSortYCnt] = afSortTemmp; afSortTemmp = asGzCoordY[anSortYCnt - 1]; asGzCoordY[anSortYCnt - 1] = asGzCoordY[anSortYCnt]; asGzCoordY[anSortYCnt] = afSortTemmp; afSortTemmp = asGzCoordZ[anSortYCnt - 1]; asGzCoordZ[anSortYCnt - 1] = asGzCoordZ[anSortYCnt]; asGzCoordZ[anSortYCnt] = afSortTemmp; } } float afCoefA = asGzCoordY[2] - asGzCoordY[0]; float afCoefB = asGzCoordX[0] - asGzCoordX[2]; float afCoefC = -afCoefB*asGzCoordY[0] - afCoefA * asGzCoordX[0]; float acTestX = -(afCoefB*asGzCoordY[1] + afCoefC) / afCoefA; if (acTestX < asGzCoordX[1]) { tmp = asGzCoordY[2]; asGzCoordY[2] = asGzCoordY[1]; asGzCoordY[1] = tmp; tmp = asGzCoordX[2]; asGzCoordX[2] = asGzCoordX[1]; asGzCoordX[1] = tmp; tmp = asGzCoordZ[2]; asGzCoordZ[2] = asGzCoordZ[1]; asGzCoordZ[1] = tmp; } //find the max and min for X and Y float afMaxX, afMinX, afMaxY, afMinY; afMaxX = asGzCoordX[0]; afMinX = asGzCoordX[0]; afMaxY = asGzCoordY[0]; afMinY = asGzCoordY[0]; for (int anCntMinMaxCnt = 1; anCntMinMaxCnt < 3; anCntMinMaxCnt++) { if (afMaxX <= asGzCoordX[anCntMinMaxCnt]) { afMaxX = asGzCoordX[anCntMinMaxCnt]; } if (afMinX >= asGzCoordX[anCntMinMaxCnt]) { afMinX = asGzCoordX[anCntMinMaxCnt]; } if (afMaxY <= asGzCoordY[anCntMinMaxCnt]) { afMaxY = asGzCoordY[anCntMinMaxCnt]; } if (afMinY >= asGzCoordY[anCntMinMaxCnt]) { afMinY = asGzCoordY[anCntMinMaxCnt]; } } //set the boundary of x and y if (afMinX < 0) { afMinX = 0; } else if (afMinX > 255) { afMinX = 255; } if (afMaxX < 0){ afMaxX = 0; } else if (afMaxX > 255) { afMaxX = 255; } if (afMinY < 0){ afMinY = 0; } else if (afMinY > 255) { afMinY = 255; } if (afMaxY < 0){ afMaxY = 0; } else if (afMaxY > 255) { afMaxY = 255; } //set the variants of vertex Ax + By + C = 0 float afCoefA1, afCoefA2, afCoefA3, afCoefB1, afCoefB2, afCoefB3, afCoefC1, afCoefC2, afCoefC3; float AfDiff1, AfDiff2, AfDiff3; float afVar1, afVar2, afVar3, afVar4; GzIntensity asR, asG, asB, asAlpha; GzDepth anZ; int anInterZ; afCoefA1 = asGzCoordY[1] - asGzCoordY[0]; afCoefA2 = asGzCoordY[2] - asGzCoordY[1]; afCoefA3 = asGzCoordY[0] - asGzCoordY[2]; afCoefB1 = -(asGzCoordX[1] - asGzCoordX[0]); afCoefB2 = -(asGzCoordX[2] - asGzCoordX[1]); afCoefB3 = -(asGzCoordX[0] - asGzCoordX[2]); afCoefC1 = ((-(afCoefB1)*asGzCoordY[1]) - (afCoefA1 * asGzCoordX[1])); afCoefC2 = ((-(afCoefB2)*asGzCoordY[2]) - (afCoefA2 * asGzCoordX[2])); afCoefC3 = ((-(afCoefB3)*asGzCoordY[0]) - (afCoefA3 * asGzCoordX[0])); afVar1 = (((asGzCoordY[1] - asGzCoordY[0])*(asGzCoordZ[2] - asGzCoordZ[0])) - ((asGzCoordY[2] - asGzCoordY[0])*(asGzCoordZ[1] - asGzCoordZ[0]))); afVar2 = (((asGzCoordX[2] - asGzCoordX[0])*(asGzCoordZ[1] - asGzCoordZ[0])) - ((asGzCoordX[1] - asGzCoordX[0])*(asGzCoordZ[2] - asGzCoordZ[0]))); afVar3 = (((asGzCoordX[1] - asGzCoordX[0])*(asGzCoordY[2] - asGzCoordY[0])) - ((asGzCoordX[2] - asGzCoordX[0])*(asGzCoordY[1] - asGzCoordY[0]))); afVar4 = -((asGzCoordY[0] * (afVar2)) + (asGzCoordX[0] * (afVar1)) + (asGzCoordZ[0] * (afVar3))); for (int anCntRangeX = int(afMinX); (float)anCntRangeX < (afMaxX); anCntRangeX++){ for (int anCntRangeY = int(afMinY); (float)anCntRangeY < (afMaxY); anCntRangeY++){ AfDiff1 = (afCoefA1*anCntRangeX) + (afCoefB1*anCntRangeY) + afCoefC1; AfDiff2 = (afCoefA2*anCntRangeX) + (afCoefB2*anCntRangeY) + afCoefC2; AfDiff3 = (afCoefA3*anCntRangeX) + (afCoefB3*anCntRangeY) + afCoefC3; anInterZ = -(afVar1*anCntRangeX + afVar2*anCntRangeY + afVar4) / afVar3; if (!(AfDiff1 < 0 || AfDiff2 < 0 || AfDiff3 < 0)){ asR = 0; asG = 0; asB = 0; asAlpha = 0; anZ = 0; if (GZ_FAILURE == GzGetDisplay(render->display, anCntRangeX, anCntRangeY, &asR, &asG, &asB, &asAlpha, &anZ)) { return GZ_FAILURE; } if (anZ == 0 || anInterZ < anZ) { if (GZ_FAILURE == GzPutDisplay(render->display, anCntRangeX, anCntRangeY, ctoi(render->flatcolor[RED]), ctoi(render->flatcolor[GREEN]), ctoi(render->flatcolor[BLUE]), asAlpha, anInterZ)) { return GZ_FAILURE; } } } } } } else if (nameList[nCnt] == GZ_NULL_TOKEN) { continue; } } return GZ_SUCCESS; }
int Application1::Render() { int i, j; int xRes, yRes, dispClass; /* display parameters */ int status; status = 0; /* * initialize the display and the renderer */ m_nWidth = 512; // frame buffer and display width m_nHeight = 512; // frame buffer and display height status |= GzNewFrameBuffer(&m_pFrameBuffer, m_nWidth, m_nHeight); status |= GzNewDisplay(&m_pDisplay, GZ_RGBAZ_DISPLAY, m_nWidth, m_nHeight); status |= GzGetDisplayParams(m_pDisplay, &xRes, &yRes, &dispClass); status |= GzInitDisplay(m_pDisplay); /* init for new frame */ if (status) exit(GZ_FAILURE); // I/O File open FILE *infile; if( (infile = fopen( INFILE1 , "r" )) == NULL ) { AfxMessageBox( "The input file was not opened\n" ); return GZ_FAILURE; } FILE *outfile; if( (outfile = fopen( OUTFILE1 , "wb" )) == NULL ) { AfxMessageBox( "The output file was not opened\n" ); return GZ_FAILURE; } int ulx, uly, lrx, lry, r, g, b; while( fscanf(infile, "%d %d %d %d %d %d %d", &ulx, &uly, &lrx, &lry, &r, &g, &b) == 7) { for (j = uly; j <= lry; j++) { for (i = ulx; i <= lrx; i++) { GzPutDisplay(m_pDisplay, i, j, r, g, b, 1, 0); } } } GzFlushDisplay2File(outfile, m_pDisplay); /* write out or update display to file*/ GzFlushDisplay2FrameBuffer(m_pFrameBuffer, m_pDisplay); // write out or update display to frame buffer /* * Clean up and exit */ if( fclose( infile ) ) AfxMessageBox( "The input file was not closed\n" ); if( fclose( outfile ) ) AfxMessageBox( "The output file was not closed\n" ); status |= GzFreeDisplay(m_pDisplay); if (status) return(GZ_FAILURE); else return(GZ_SUCCESS); }
void GzRasterize(GzRender *render,GzCoord *triVertex) { //AfxMessageBox("Rasterize"); float x1 = triVertex[0][0]; float x2 = triVertex[1][0]; float x3 = triVertex[2][0]; float y1 = triVertex[0][1]; float y2 = triVertex[1][1]; float y3 = triVertex[2][1]; float z1 = triVertex[0][2]; float z2 = triVertex[1][2]; float z3 = triVertex[2][2]; float xMin,yMin,xMax,yMax; float a1,b1,c1,a2,b2,c2,a3,b3,c3; float aX,bY,cZ,d; int xStart,yStart,xEnd,yEnd; /* xMin, xMax, yMin, yMax are calculated for fixing the bounding box triangle */ xMin = min(x1,min(x2,x3)); xMax = max(x1,max(x2,x3)); yMin = min(y1,min(y2,y3)); yMax = max(y1,max(y2,y3)); /* Computing Line Equation coefficients */ // First Edge (x1,y1) -> (x2,y2) a1 = y1 - y2; b1 = x2 - x1; c1 = ((x1 - x2) * y2) - ((y1 - y2) * x2); //Second Edge (x2,y2) -> (x3,y3) a2 = y2 - y3; b2 = x3 - x2; c2 = ((x2 - x3) * y3) - ((y2 - y3) * x3); //Third Edge (x3,y3) -> (x1,y1) a3 = y3 - y1; b3 = x1 - x3; c3 = ((x3 - x1) * y1) - ((y3 - y1) * x1); /* Finding Crossproduct of 2 edges to obtain the plane equation for the triangle */ aX = (((y1 - y2) * (z2 - z3)) - ((z1 - z2) * (y2 - y3))); bY = -(((x1 - x2) * (z2 - z3)) - ((z1 - z2) * (x2 - x3))); cZ = (((x1 - x2) * (y2 - y3)) - ((y1 - y2) * (x2 - x3))); d = -(aX * x1 + bY * y1 + cZ * z1); xStart = max(int(ceil((xMin))),0); yStart = max(int(ceil((yMin))),0); xEnd = min(int(floor((xMax))),render->display->xres); yEnd = min(int(floor((yMax))),render->display->yres); if(WIREFRAME) { line(x1,y1,x2,y2,render); line(x2,y2,x3,y3,render); line(x3,y3,x1,y1,render); } else{ for(int y = yStart; y <= yEnd; y++) { for(int x = xStart; x <= xEnd; x++) { //check if x,y lies outside the line. If yes, skip triangle and move to next if (a1 * x + b1 * y + c1 < 0) { continue; } if(a2 * x + b2 * y + c2 < 0) { continue; } if(a3 * x + b3 * y + c3 < 0) { continue; } GzDepth newZ = (GzDepth)(-(aX * x + bY * y + d) / cZ); if(newZ > 0) { GzIntensity red,green,blue,alpha; GzDepth oldZ; GzGetDisplay(render->display,x,y,&red,&green,&blue,&alpha,&oldZ); if(newZ < oldZ) { GzPutDisplay(render->display,x,y,ctoi(render->flatcolor[0]),ctoi(render->flatcolor[1]),ctoi(render->flatcolor[2]),alpha,newZ); } } } } } }
bool rastlee(GzRender* render, GzCoord* cord, GzCoord * norms, GzTextureIndex * Textcord) { //swap and sort Y of vertex //sort Y by ascending order for (int j = 0; j < 2; j++) { for (int k = 0; k < 2 - j; k++) { if (cord[k][Y]>cord[k + 1][Y]) { float tempx = cord[k][X]; float tempy = cord[k][Y]; float tempz = cord[k][Z]; cord[k][X] = cord[k + 1][X]; cord[k][Y] = cord[k + 1][Y]; cord[k][Z] = cord[k + 1][Z]; cord[k + 1][X] = tempx; cord[k + 1][Y] = tempy; cord[k + 1][Z] = tempz; float tempNx = norms[k][X]; float tempNy = norms[k][Y]; float tempNz = norms[k][Z]; norms[k][X] = norms[k + 1][X]; norms[k][Y] = norms[k + 1][Y]; norms[k][Z] = norms[k + 1][Z]; norms[k + 1][X] = tempNx; norms[k + 1][Y] = tempNy; norms[k + 1][Z] = tempNz; float tempU = Textcord[k][U]; float tempV = Textcord[k][V]; Textcord[k][U] = Textcord[k + 1][U]; Textcord[k][V] = Textcord[k + 1][V]; Textcord[k + 1][U] = tempU; Textcord[k + 1][V] = tempV; } } } // determine L/R CW //horizontal case have two top Y if (cord[0][Y] == cord[1][Y]) { if (cord[0][X] > cord[1][X]) { float tempx = cord[0][X]; float tempy = cord[0][Y]; float tempz = cord[0][Z]; cord[0][X] = cord[1][X]; cord[0][Y] = cord[1][Y]; cord[0][Z] = cord[1][Z]; cord[1][X] = tempx; cord[1][Y] = tempy; cord[1][Z] = tempz; float tempNx = norms[0][X]; float tempNy = norms[0][Y]; float tempNz = norms[0][Z]; norms[0][X] = norms[1][X]; norms[0][Y] = norms[1][Y]; norms[0][Z] = norms[1][Z]; norms[1][X] = tempNx; norms[1][Y] = tempNy; norms[1][Z] = tempNz; float tempU = Textcord[0][U]; float tempV = Textcord[0][V]; Textcord[0][U] = Textcord[1][U]; Textcord[0][V] = Textcord[1][V]; Textcord[1][U] = tempU; Textcord[1][V] = tempV; } } //horizontal case have two bot Y else if (cord[1][Y] == cord[2][Y]) { if (cord[2][X] > cord[1][X]) { float tempx = cord[2][X]; float tempy = cord[2][Y]; float tempz = cord[2][Z]; cord[2][X] = cord[1][X]; cord[2][Y] = cord[1][Y]; cord[2][Z] = cord[1][Z]; cord[1][X] = tempx; cord[1][Y] = tempy; cord[1][Z] = tempz; float tempNx = norms[2][X]; float tempNy = norms[2][Y]; float tempNz = norms[2][Z]; norms[2][X] = norms[1][X]; norms[2][Y] = norms[1][Y]; norms[2][Z] = norms[1][Z]; norms[1][X] = tempNx; norms[1][Y] = tempNy; norms[1][Z] = tempNz; float tempU = Textcord[2][U]; float tempV = Textcord[2][V]; Textcord[2][U] = Textcord[1][U]; Textcord[2][V] = Textcord[1][V]; Textcord[1][U] = tempU; Textcord[1][V] = tempV; } } //bound box int top = (int)floor(cord[0][Y]); int bot = (int)ceil(cord[2][Y]); int left = cord[0][X]; int right = cord[2][X]; for (int i = 0; i < 3; i++) { if (cord[i][X] < left) left = (int)floor(cord[i][X]); if (cord[i][X]>right) right = (int)ceil(cord[i][X]); } //interpolate z float interpz; GzCoord vec01, vec12; vec01[X] = cord[1][X] - cord[0][X]; vec01[Y] = cord[1][Y] - cord[0][Y]; vec01[Z] = cord[1][Z] - cord[0][Z]; vec12[X] = cord[2][X] - cord[1][X]; vec12[Y] = cord[2][Y] - cord[1][Y]; vec12[Z] = cord[2][Z] - cord[1][Z]; float A = vec01[Y] * vec12[Z] - vec01[Z] * vec12[Y]; float B = vec01[Z] * vec12[X] - vec01[X] * vec12[Z]; float C = vec01[X] * vec12[Y] - vec01[Y] * vec12[X]; float D = -(A*cord[0][X] + B*cord[0][Y] + C*cord[0][Z]); //Gouraud shading GzColor goudinter; GzColor color0, color1, color2; /* ShadingEquation(render, color0, norms[0]); ShadingEquation(render, color1, norms[1]); ShadingEquation(render, color2, norms[2]);*/ if (render->interp_mode == GZ_COLOR) { if (render->tex_fun == NULL) { ShadingEquation(render, color0, norms[0]); ShadingEquation(render, color1, norms[1]); ShadingEquation(render, color2, norms[2]); } else {//use texture function render->Ka[RED] =1; render->Ka[GREEN] =1; render->Ka[BLUE] = 1; render->Kd[RED] = 1; render->Kd[GREEN] =1; render->Kd[BLUE] = 1; render->Ks[RED] = 1; render->Ks[GREEN] =1; render->Ks[BLUE] = 1; ShadingEquation(render, color0, norms[0]); ShadingEquation(render, color1, norms[1]); ShadingEquation(render, color2, norms[2]); } } GzColor gA, gB, gC, gD; gA[RED] = vec01[Y] * (color2[RED] - color1[RED]) - (color1[RED] - color0[RED]) * vec12[Y]; gB[RED] = (color1[RED] - color0[RED]) * vec12[X] - vec01[X] * (color2[RED] - color1[RED]); gC[RED] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X]; gD[RED] = -(gA[RED]*cord[0][X] + gB[RED]*cord[0][Y] + gC[RED]*color0[RED]); gA[GREEN] = vec01[Y] * (color2[GREEN] - color1[GREEN]) - (color1[GREEN] - color0[GREEN]) * vec12[Y]; gB[GREEN] = (color1[GREEN] - color0[GREEN]) * vec12[X] - vec01[X] * (color2[GREEN] - color1[GREEN]); gC[GREEN] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X]; gD[GREEN] = -(gA[GREEN] * cord[0][X] + gB[GREEN] * cord[0][Y] + gC[GREEN] * color0[GREEN]); gA[BLUE] = vec01[Y] * (color2[BLUE] - color1[BLUE]) - (color1[BLUE] - color0[BLUE]) * vec12[Y]; gB[BLUE] = (color1[BLUE] - color0[BLUE]) * vec12[X] - vec01[X] * (color2[BLUE] - color1[BLUE]); gC[BLUE] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X]; gD[BLUE] = -(gA[BLUE] * cord[0][X] + gB[BLUE] * cord[0][Y] + gC[BLUE] * color0[BLUE]); //prepare for interp UV texture float Vzp;// Vz' GzTextureIndex* perspTextcord = new GzTextureIndex[3];//warp uv-> UV from image space to perspective space for each vertex for (int k = 0; k < 3; k++) { Vzp = cord[k][Z] / (INT_MAX - cord[k][Z]); perspTextcord[k][U] = Textcord[k][U] / (Vzp + 1); perspTextcord[k][V] = Textcord[k][V] / (Vzp + 1); } //if in bbox draw pixel for (int i = left; i < right; i++) { if (i<0 || i>render->display->xres) { continue; } for (int j = top; j < bot; j++) { if (j<0 || j>render->display->yres) { continue; } float a01 = cord[1][Y] - cord[0][Y]; float a12 = cord[2][Y] - cord[1][Y]; float a20 = cord[0][Y] - cord[2][Y]; float b01 = -(cord[1][X] - cord[0][X]); float b12 = -(cord[2][X] - cord[1][X]); float b20 = -(cord[0][X] - cord[2][X]); float c01 = -b01*cord[0][Y] - a01*cord[0][X]; float c12 = -b12*cord[1][Y] - a12*cord[1][X]; float c20 = -b20*cord[2][Y] - a20*cord[2][X]; float e01 = a01*(float)i + b01*(float)j + c01; float e12 = a12*(float)i + b12*(float)j + c12; float e20 = a20*(float)i + b20*(float)j + c20; if ((e01 == 0 || e12 == 0 || e20 == 0)||((e01 > 0) && (e12 > 0) && (e20 > 0)) || ((e01 < 0) && (e12 < 0) && (e20 < 0))) { interpz = (-(A*i) - (B*j) - D) / C; GzIntensity r, g, b, a; GzDepth z; GzGetDisplay(render->display, i, j, &r, &g, &b, &a, &z); if (interpz < z) { GzCoord pers01, pers12; pers01[U] = perspTextcord[1][U] - perspTextcord[0][U]; pers01[V] = perspTextcord[1][V] - perspTextcord[0][V]; pers12[U] = perspTextcord[2][U] - perspTextcord[1][U]; pers12[V] = perspTextcord[2][V] - perspTextcord[1][V]; // GzCoord intepcrossprod; //crossvector(pers01, pers12, intepcrossprod); GzTextureIndex tA, tB, tC, tD, textureinter, newuv; tA[U] = vec01[Y] * (pers12[U]) - (pers01[U]) * vec12[Y]; tB[U] = (pers01[U]) * vec12[X] - vec01[X] * (pers12[U]); tC[U] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X]; tD[U] = -(tA[U] * cord[0][X] + tB[U] * cord[0][Y] + tC[U] * perspTextcord[0][U]); tA[V] = vec01[Y] * (pers12[V]) - (pers01[V]) * vec12[Y]; tB[V] = (pers01[V]) * vec12[X] - vec01[X] * (pers12[V]); tC[V] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X]; tD[V] = -(tA[V] * cord[0][X] + tB[V] * cord[0][Y] + tC[V] * perspTextcord[0][V]); // interpolateUV to pixel /*textureinter[U] = -(tA[U] * i + tB[U] * j + tD[U]) / tC[U]; textureinter[V] = -(tA[V] * i + tB[V] * j + tD[V]) / tC[V];*/ textureinter[U] = interpolate(tA[U], tB[U], tC[U], tD[U], i, j); textureinter[V] = interpolate(tA[V], tB[V], tC[V], tD[V], i, j); //unwarping float Vzp = interpz / (INT_MAX - interpz); newuv[U] = textureinter[U] * (Vzp + 1); newuv[V] = textureinter[V] * (Vzp + 1); //texture color lookup with bilinear interpolation GzColor texColor; if (render->tex_fun != NULL) { render->tex_fun(newuv[U], newuv[V], texColor); } switch (render->interp_mode) { case GZ_FLAT: r = (GzIntensity)ctoi((float)render->flatcolor[0]); g = (GzIntensity)ctoi((float)render->flatcolor[1]); b = (GzIntensity)ctoi((float)render->flatcolor[2]); z = interpz; break; case GZ_COLOR://ground shading render->Ka[RED] = texColor[RED]; render->Ka[GREEN] = texColor[GREEN]; render->Ka[BLUE] = texColor[BLUE]; render->Kd[RED] = texColor[RED]; render->Kd[GREEN] = texColor[GREEN]; render->Kd[BLUE] = texColor[BLUE]; render->Ks[RED] = texColor[RED]; render->Ks[GREEN] = texColor[GREEN]; render->Ks[BLUE] = texColor[BLUE]; goudinter[RED] = -(gA[RED] * i + gB[RED] * j + gD[RED]) / gC[RED]; goudinter[GREEN] = -(gA[GREEN] * i + gB[GREEN] * j + gD[GREEN]) / gC[GREEN]; goudinter[BLUE] = -(gA[BLUE] * i + gB[BLUE] * j + gD[BLUE]) / gC[BLUE]; //texture color if (render->tex_fun != NULL) { goudinter[RED] *= texColor[RED] ; goudinter[GREEN] *= texColor[GREEN]; goudinter[BLUE] *= texColor[BLUE]; } if (goudinter[RED] > 1.0) goudinter[RED] = 1.0; if (goudinter[GREEN] > 1.0) goudinter[GREEN] = 1.0; if (goudinter[BLUE] > 1.0) goudinter[BLUE] = 1.0; r = (GzIntensity)ctoi(goudinter[RED]); g = (GzIntensity)ctoi(goudinter[GREEN]); b = (GzIntensity)ctoi(goudinter[BLUE]); z = interpz; break; case GZ_NORMALS: //interpolizing norms; GzColor pA, pB, pC, pD; pA[RED] = vec01[Y] * (norms[2][RED] - norms[1][RED]) - (norms[1][RED] - norms[0][RED]) * vec12[Y]; pB[RED] = (norms[1][RED] - norms[0][RED]) * vec12[X] - vec01[X] * (norms[2][RED] - norms[1][RED]); pC[RED] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X]; pD[RED] = -(pA[RED] * cord [0][X] + pB[RED] * cord[0][Y] + pC[RED] * norms[0][RED]); pA[GREEN] = vec01[Y] * (norms[2][GREEN] - norms[1][GREEN]) - (norms[1][GREEN] - norms[0][GREEN]) * vec12[Y]; pB[GREEN] = (norms[1][GREEN] - norms[0][GREEN]) * vec12[X] - vec01[X] * (norms[2][GREEN] - norms[1][GREEN]); pC[GREEN] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X]; pD[GREEN] = -(pA[GREEN] * cord[0][X] + pB[GREEN] * cord[0][Y] + pC[GREEN] * norms[0][GREEN]); pA[BLUE] = vec01[Y] * (norms[2][BLUE] - norms[1][BLUE]) - (norms[1][BLUE] - norms[0][BLUE]) * vec12[Y]; pB[BLUE] = (norms[1][BLUE] - norms[0][BLUE]) * vec12[X] - vec01[X] * (norms[2][BLUE] - norms[1][BLUE]); pC[BLUE] = vec01[X] * vec12[Y] - vec01[Y] * vec12[X]; pD[BLUE] = -(pA[BLUE] * cord[0][X] + pB[BLUE] * cord[0][Y] + pC[BLUE] * norms[0][BLUE]); GzColor phonginter; phonginter[0] = -(pA[0] * i + pB[0] * j + pD[0]) / pC[0]; phonginter[1] = -(pA[1] * i + pB[1] * j + pD[1]) / pC[1]; phonginter[2] = -(pA[2] * i + pB[2] * j + pD[2]) / pC[2]; NormVector(phonginter); //Then shading calculation with texture color used as Kd and Ka if (render->tex_fun != NULL) { render->Ka[RED] = render->Kd[RED] = texColor[RED]; render->Ka[GREEN] = render->Kd[GREEN] = texColor[GREEN]; render->Ka[BLUE] = render->Kd[BLUE] = texColor[BLUE]; } GzColor colorpix; ShadingEquation(render, colorpix, phonginter); r = (GzIntensity)ctoi(colorpix[RED]); g = (GzIntensity)ctoi(colorpix[GREEN]); b = (GzIntensity)ctoi(colorpix[BLUE]); z = interpz; break; } GzPutDisplay(render->display, i, j, r, g, b, a, z); } } } } return true; }
int Gz_LEE_Rasterization(GzRender *render, GzCoord vertex[3]) { GzIntensity Red, Green, Blue, alpha; //bubble sort for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { if (vertex[j][Y] > vertex[j + 1][Y]) { Gz_Swap_Vertex(vertex[j], vertex[j + 1]); } } } //I think there is no need to do clockwise, because I can use +/- common area //Gz_Make_CW(vertex[0], vertex[1], vertex[2]); //After the CW, vectors and a rectangle enclousing the triangle in 2D map GzCoord Vector_1_to_2; GzCoord Vector_2_to_3; GzCoord Vector_3_to_1; Vector_1_to_2[X] = vertex[1][X] - vertex[0][X]; Vector_1_to_2[Y] = vertex[1][Y] - vertex[0][Y]; Vector_1_to_2[Z] = vertex[1][Z] - vertex[0][Z]; Vector_2_to_3[X] = vertex[2][X] - vertex[1][X]; Vector_2_to_3[Y] = vertex[2][Y] - vertex[1][Y]; Vector_2_to_3[Z] = vertex[2][Z] - vertex[1][Z]; Vector_3_to_1[X] = vertex[0][X] - vertex[2][X]; Vector_3_to_1[Y] = vertex[0][Y] - vertex[2][Y]; Vector_3_to_1[Z] = vertex[0][Z] - vertex[2][Z]; //We use + area in this 3 vectors! //Because the coords may not be integer! But pixels are at integers! X grows right, Y grows down. int Xmin = floor(Find_x_min(vertex)); int Xmax = ceil(Find_x_max(vertex)); int Ymin = floor(vertex[0][Y]); int Ymax = ceil(vertex[2][Y]); //Calculate the Ax+By+Cz+D=0 A B C D use vectors float A; float B; float C; float D; A = Vector_1_to_2[Y] * (-Vector_3_to_1[Z]) - (-Vector_3_to_1[Y]) * Vector_1_to_2[Z]; B = Vector_1_to_2[Z] * (-Vector_3_to_1[X]) - (-Vector_3_to_1[Z]) * Vector_1_to_2[X]; C = Vector_1_to_2[X] * (-Vector_3_to_1[Y]) - (-Vector_3_to_1[X]) * Vector_1_to_2[Y]; D = -(A * vertex[0][X] + B * vertex[0][Y] + C * vertex[0][Z]); //Scan the pixels and draw! float Pixel_z; for (int i = Xmin; i <= Xmax; i++) { if (i < 0 || i > render->display->xres) continue; for (int j = Ymin; j <= Ymax; j++) { if (j < 0 || j > render->display->yres) continue; Pixel_z = -(A * i + B * j + D) / C; GzDepth tempz = 0; //get z from getdisplay /* Put point into the line fuctions: E1(x,y) E2(x,y) E3(x,y) the relationship with vectors in 2D map */ float Relationship_with_1_to_2 = Vector_1_to_2[Y] * (i - vertex[0][X]) - Vector_1_to_2[X] * (j - vertex[0][Y]); float Relationship_with_2_to_3 = Vector_2_to_3[Y] * (i - vertex[1][X]) - Vector_2_to_3[X] * (j - vertex[1][Y]); float Relationship_with_3_to_1 = Vector_3_to_1[Y] * (i - vertex[2][X]) - Vector_3_to_1[X] * (j - vertex[2][Y]); if (Relationship_with_1_to_2 == 0 || Relationship_with_2_to_3 == 0 || Relationship_with_3_to_1 == 0) { //one the line! GzGetDisplay(render->display, i, j, &Red, &Green, &Blue, &alpha, &tempz); if (Pixel_z < tempz) { Red = ctoi(render->flatcolor[0]); Green = ctoi(render->flatcolor[1]); Blue = ctoi(render->flatcolor[2]); GzPutDisplay(render->display, i, j, Red, Green, Blue, alpha, Pixel_z); } } else if ((Relationship_with_1_to_2 > 0 && Relationship_with_2_to_3 > 0 && Relationship_with_3_to_1 > 0) || (Relationship_with_1_to_2 < 0 && Relationship_with_2_to_3 < 0 && Relationship_with_3_to_1 < 0)) { GzGetDisplay(render->display, i, j, &Red, &Green, &Blue, &alpha, &tempz); if (Pixel_z < tempz) { Red = ctoi(render->flatcolor[0]); Green = ctoi(render->flatcolor[1]); Blue = ctoi(render->flatcolor[2]); GzPutDisplay(render->display, i, j, Red, Green, Blue, alpha, Pixel_z); } } } } return GZ_SUCCESS; }
void GzRasterize(GzRender *render,GzCoord *imageV, GzCoord *imageN,GzCoord *screenV,GzTextureIndex *textureC) { float xMin,xMax,yMin,yMax; float a1,b1,c1,a2,b2,c2,a3,b3,c3; float aX,bY,cZ,d; GzCoord v0,v1,v2; GzEdge edge[3]; GzCoord tempCoord1, tempCoord2; // gourad shading values GzColor cpA,cpB,cpC,cpD; // phong shading values GzCoord imageVa, imageVb, imageVc, imageVd; //image vertices GzCoord imageNa, imageNb, imageNc, imageNd; //image normals GzTextureIndex texCPa,texCPb,texCPc,texCPd; //Find xmin,xmax,ymin and ymax to obtain bounding rectangle for the triangle xMin = min(screenV[0][X],min(screenV[1][X],screenV[2][X])); yMin = min(screenV[0][Y],min(screenV[1][Y],screenV[2][Y])); xMax = max(screenV[0][X],max(screenV[1][X],screenV[2][X])); yMax = max(screenV[0][Y],max(screenV[1][Y],screenV[2][Y])); xMin = max((int)(ceil(xMin)),0); yMin = max((int)(ceil(yMin)),0); xMax = min((int)(floor(xMax)),render->display->xres); yMax = min((int)(floor(yMax)),render->display->yres); // Setting vertices of the triangle and the edges of the triangle in anti-clockwise direction for processing v0[X] = screenV[0][X]; v0[Y] = screenV[0][Y]; v0[Z] = screenV[0][Z]; v1[X] = screenV[1][X]; v1[Y] = screenV[1][Y]; v1[Z] = screenV[1][Z]; v2[X] = screenV[2][X]; v2[Y] = screenV[2][Y]; v2[Z] = screenV[2][Z]; //edge 0 v0 -> v2 edge[0].start[X] = v0[X]; edge[0].start[Y] = v0[Y]; edge[0].start[Z] = v0[Z]; edge[0].end[X] = v2[X]; edge[0].end[Y] = v2[Y]; edge[0].end[Z] = v2[Z]; //edge 1 v2 -> v1 edge[1].start[X] = v2[X]; edge[1].start[Y] = v2[Y]; edge[1].start[Z] = v2[Z]; edge[1].end[X] = v1[X]; edge[1].end[Y] = v1[Y]; edge[1].end[Z] = v1[Z]; //edge 2 v1 -> v0 edge[2].start[X] = v1[X]; edge[2].start[Y] = v1[Y]; edge[2].start[Z] = v1[Z]; edge[2].end[X] = v0[X]; edge[2].end[Y] = v0[Y]; edge[2].end[Z] = v0[Z]; /* Computing Line Equation coefficients */ a1 = edge[0].end[Y] - edge[0].start[Y]; b1 = edge[0].start[X] - edge[0].end[X]; c1 = (((edge[0].end[X] - edge[0].start[X]) * edge[0].start[Y]) - ((edge[0].end[Y] - edge[0].start[Y]) * edge[0].start[X])); a2 = edge[1].end[Y] - edge[1].start[Y]; b2 = edge[1].start[X] - edge[1].end[X]; c2 = (((edge[1].end[X] - edge[1].start[X]) * edge[1].start[Y]) - ((edge[1].end[Y] - edge[1].start[Y]) * edge[1].start[X])); a3 = edge[2].end[Y] - edge[2].start[Y]; b3 = edge[2].start[X] - edge[2].end[X]; c3 = (((edge[2].end[X] - edge[2].start[X]) * edge[2].start[Y]) - ((edge[2].end[Y] - edge[2].start[Y]) * edge[2].start[X])); /* Finding Crossproduct of 2 edges to obtain the plane equation for the triangle */ aX = (((edge[0].end[Y] - edge[0].start[Y]) * (edge[1].end[Z] - edge[1].start[Z])) - ((edge[0].end[Z] - edge[0].start[Z]) * (edge[1].end[Y] - edge[1].start[Y]))); bY = -(((edge[0].end[X] - edge[0].start[X]) * (edge[1].end[Z] - edge[1].start[Z])) - ((edge[0].end[Z] - edge[0].start[Z]) * (edge[1].end[X] - edge[1].start[X]))); cZ = (((edge[0].end[X] - edge[0].start[X]) * (edge[1].end[Y] - edge[1].start[Y])) - ((edge[0].end[Y] - edge[0].start[Y]) * (edge[1].end[X] - edge[1].start[X]))); d = -(aX * screenV[0][X] + bY * screenV[0][Y] + cZ * screenV[0][Z]); /* setting values for pixels which will be constant through the interpolation calculation */ tempCoord1[X] = edge[0].end[X] - edge[0].start[X]; tempCoord2[X] = edge[1].end[X] - edge[1].start[X]; tempCoord1[Y] = edge[0].end[Y] - edge[0].start[Y]; tempCoord2[Y] = edge[1].end[Y] - edge[1].start[Y]; //For Gourad Shading if(render->interp_mode == GZ_COLOR) { //calculate the color for each vertex and set up the interpolation plane coefficients GzColor vertexClr[3]; int dummy1 = 0,dummy2 = 0; GzShade(render,imageV[0],imageN[0],vertexClr[0],textureC[0],dummy1,dummy2); GzShade(render,imageV[1],imageN[1],vertexClr[1],textureC[1],dummy1,dummy2); GzShade(render,imageV[2],imageN[2],vertexClr[2],textureC[2],dummy1,dummy2); tempCoord1[Z] = vertexClr[2][0] - vertexClr[0][0]; tempCoord2[Z] = vertexClr[1][0] - vertexClr[2][0]; cpA[0] = tempCoord1[Y] * tempCoord2[Z] - tempCoord1[Z] * tempCoord2[Y]; cpB[0] = tempCoord1[Z] * tempCoord2[X] - tempCoord1[X] * tempCoord2[Z]; cpC[0] = tempCoord1[X] * tempCoord2[Y] - tempCoord1[Y] * tempCoord2[X]; cpD[0] = -(cpA[0] * edge[0].start[X] + cpB[0] * edge[0].start[Y] + cpC[0] * vertexClr[0][0]); tempCoord1[Z] = 0; tempCoord2[Z] = 0; tempCoord1[Z] = vertexClr[2][1] - vertexClr[0][1]; tempCoord2[Z] = vertexClr[1][1] - vertexClr[2][1]; cpA[1] = tempCoord1[Y] * tempCoord2[Z] - tempCoord1[Z] * tempCoord2[Y]; cpB[1] = tempCoord1[Z] * tempCoord2[X] - tempCoord1[X] * tempCoord2[Z]; cpC[1] = tempCoord1[X] * tempCoord2[Y] - tempCoord1[Y] * tempCoord2[X]; cpD[1] = -(cpA[1] * edge[0].start[X] + cpB[1] * edge[0].start[Y] + cpC[1] * vertexClr[0][1]); tempCoord1[Z] = 0; tempCoord2[Z] = 0; tempCoord1[Z] = vertexClr[2][2] - vertexClr[0][2]; tempCoord2[Z] = vertexClr[1][2] - vertexClr[2][2]; cpA[2] = tempCoord1[Y] * tempCoord2[Z] - tempCoord1[Z] * tempCoord2[Y]; cpB[2] = tempCoord1[Z] * tempCoord2[X] - tempCoord1[X] * tempCoord2[Z]; cpC[2] = tempCoord1[X] * tempCoord2[Y] - tempCoord1[Y] * tempCoord2[X]; cpD[2] = -(cpA[2] * edge[0].start[X] + cpB[2] * edge[0].start[Y] + cpC[2] * vertexClr[0][2]); tempCoord1[Z] = 0; tempCoord2[Z] = 0; } /* For phong shading */ else if(render->interp_mode == GZ_NORMALS) { /* calculate interpolation plane coefficient for planes and normals */ for(int i = 0; i < 3; i++) { /* For vertices */ tempCoord1[Z] = imageV[2][i] - imageV[0][i]; tempCoord2[Z] = imageV[1][i] - imageV[2][i]; imageVa[i] = tempCoord1[Y] * tempCoord2[Z] - tempCoord1[Z] * tempCoord2[Y]; imageVb[i] = tempCoord1[Z] * tempCoord2[X] - tempCoord1[X] * tempCoord2[Z]; imageVc[i] = tempCoord1[X] * tempCoord2[Y] - tempCoord1[Y] * tempCoord2[X]; imageVd[i] = -(imageVa[i] * edge[0].start[X] + imageVb[i] * edge[0].start[Y] + imageVc[i] * imageV[0][i]); /* For normals */ tempCoord1[Z] = imageN[2][i] - imageN[0][i]; tempCoord2[Z] = imageN[1][i] - imageN[2][i]; imageNa[i] = tempCoord1[Y] * tempCoord2[Z] - tempCoord1[Z] * tempCoord2[Y]; imageNb[i] = tempCoord1[Z] * tempCoord2[X] - tempCoord1[X] * tempCoord2[Z]; imageNc[i] = tempCoord1[X] * tempCoord2[Y] - tempCoord1[Y] * tempCoord2[X]; imageNd[i] = -(imageNa[i] * edge[0].start[X] + imageNb[i] * edge[0].start[Y] + imageNc[i] * imageN[0][i]); } GzTextureIndex perspTextC[3]; float screenSpaceZ[3]; for(int i = 0; i < 3; i++) { screenSpaceZ[i] = -(aX * screenV[i][X] + bY * screenV[i][Y] + d)/cZ; //transform from image space to perspective space by warping perspTextC[i][U] = textureC[i][U] / ((screenSpaceZ[i]/(INT_MAX - screenSpaceZ[i])) + 1); perspTextC[i][V] = textureC[i][V] / ((screenSpaceZ[i]/(INT_MAX - screenSpaceZ[i])) + 1); } for( int i = 0; i < 2; i++ ) { // set up interpolation coefficients for perspective space texture coordinate tempCoord1[Z] = perspTextC[2][i] - perspTextC[0][i]; tempCoord2[Z] = perspTextC[1][i] - perspTextC[2][i]; texCPa[i] = tempCoord1[Y] * tempCoord2[Z] - tempCoord1[Z] * tempCoord2[Y]; texCPb[i] = tempCoord1[Z] * tempCoord2[X] - tempCoord1[X] * tempCoord2[Z]; texCPc[i] = tempCoord1[X] * tempCoord2[Y] - tempCoord1[Y] * tempCoord2[X]; texCPd[i] = -(texCPa[i] * edge[0].start[X] + texCPb[i] * edge[0].start[Y] + texCPc[i] * perspTextC[0][i]); } } int zMax = 0; for( int y = yMin; y <= yMax; y++ ) { for( int x = xMin; x <= xMax; x++ ) { if((a1 * x + b1 * y + c1 > 0 && a2 * x + b2 * y + c2 > 0 && a3 * x + b3 * y + c3 > 0) || ((a1 * x + b1 * y + c1) <= 0 && (a2 * x + b2 * y + c2) <= 0 && (a3 * x + b3 * y + c3) <= 0)) { GzDepth newZ = (GzDepth)(-( aX * x + bY * y + d ) / cZ); // Check if the new value of z is in front of the camera if( newZ > 0 ) { if(newZ > zMax) { zMax = newZ; } GzIntensity r, g, b, a; GzDepth oldZ; GzGetDisplay( render->display, x, y, &r, &g, &b, &a, &oldZ); //If the value of new z id greater than old z then it can be skipped because it will be hidden if( newZ < oldZ ) { GzColor color; /* For Phong shading */ switch(render->interp_mode){ case GZ_NORMALS: { /* Perform biliniear interpolation, normalize it and calculate the color at the current pixel by calling GzShade*/ GzCoord imageVi, imageNi; GzTextureIndex textC; for(int i = 0; i < 3; i++) { imageVi[i] = -(imageVa[i] * x + imageVb[i] * y + imageVd[i]) / imageVc[i]; imageNi[i] = -(imageNa[i] * x + imageNb[i] * y + imageNd[i]) / imageNc[i]; } for( int i = 0; i < 2; i++ ) { //calculate interpolation plane for texture coords and unwarp it from perspective to image space textC[i] = -(texCPa[i] * x + texCPb[i] * y + texCPd[i]) / texCPc[i]; textC[i] = GzperspToimage( newZ, textC[i] ); } float normalizer = sqrt(imageNi[X] * imageNi[X] + imageNi[Y] * imageNi[Y] + imageNi[Z] * imageNi[Z]); imageNi[X] = imageNi[X]/normalizer; imageNi[Y] = imageNi[Y]/normalizer; imageNi[Z] = imageNi[Z]/normalizer; GzShade(render,imageVi,imageNi,color,textC,newZ,zMax); break; } case GZ_COLOR: { /* Interpolate the colors for Gourad Shading at each vertex */ color[RED] = -(cpA[0] * x + cpB[0] * y + cpD[0])/cpC[0]; color[GREEN] = -(cpA[1] * x + cpB[1] * y + cpD[1])/cpC[1]; color[BLUE] = -(cpA[2] * x + cpB[2] * y + cpD[2])/cpC[2]; break; } default: { /* Default flat shading */ color[RED] = render->flatcolor[RED]; color[GREEN] = render->flatcolor[GREEN]; color[BLUE] = render->flatcolor[BLUE]; break; } } /* Put the calculated values of the color onto the display */ if(GRAINY_NOISE_EFFECT) { float noise = scaled_octave_noise(8,0.75,2,0,4,x,y,newZ/(oldZ - newZ)); GzPutDisplay(render->display, x, y, int(ctoi(color[RED]) * noise),int(ctoi(color[GREEN]) * noise),int(ctoi(color[BLUE]) * noise),a,newZ); } else { GzPutDisplay(render->display, x, y, int(ctoi(color[RED])),int(ctoi(color[GREEN])),int(ctoi(color[BLUE])),a,newZ); } } } } } } }
int Rasterization( GzRender * render, GzCoord * vertex ) { float temp1=0.0,temp2=0.0,temp3=0.0,m=0.0,midPoint=0.0; float edges[3][6]; //x1,y1,z1,x2,y2,z2 float xDiffE0,yDiffE0,zDiffE0,xDiffE1,yDiffE1,zDiffE1,xDiffE2,yDiffE2,zDiffE2; float A,B,C,D; float a0,b0,c0,a1,b1,c1,a2,b2,c2; float lowerX=99999999.0,lowerY=99999999.0,upperX=0.0,upperY=0.0; float v0,v1,v2,v; GzIntensity r,g,b,a; GzDepth z; for(int i=0;i<2;i++) { for(int j=0;j<2-i;j++) { if( (vertex[j+1][1]<vertex[j][1])|| (vertex[j+1][0]<vertex[j][0] && vertex[j][1]==vertex[j+1][1])) { temp1=vertex[j][0];//x temp2=vertex[j][1];//y temp3=vertex[j][2];//z vertex[j][0]=vertex[j+1][0]; vertex[j][1]=vertex[j+1][1]; vertex[j][2]=vertex[j+1][2]; vertex[j+1][0]=temp1; vertex[j+1][1]=temp2; vertex[j+1][2]=temp3; } } } //get in anti clockwise if(vertex[1][1]==vertex[2][1]) { //edge 0-1 m=0.0; edges[0][0]=vertex[0][0];//x1 edges[0][3]=vertex[1][0];//x2 edges[0][1]=vertex[0][1];//y1 edges[0][4]=vertex[1][1];//y2 edges[0][2]=vertex[0][2];//z1 edges[0][5]=vertex[1][2];//z2 //edge 1-2 edges[1][0]=vertex[1][0]; edges[1][3]=vertex[2][0]; edges[1][1]=vertex[1][1]; edges[1][4]=vertex[2][1]; edges[1][2]=vertex[1][2]; edges[1][5]=vertex[2][2]; //edge 2-0 edges[2][0]=vertex[2][0]; edges[2][3]=vertex[0][0]; edges[2][1]=vertex[2][1]; edges[2][4]=vertex[0][1]; edges[2][2]=vertex[2][2]; edges[2][5]=vertex[0][2]; } else if(vertex[1][1]==vertex[0][1]) { m=0.0; //edge 1-0 edges[0][0]=vertex[1][0]; edges[0][3]=vertex[0][0]; edges[0][1]=vertex[1][1]; edges[0][4]=vertex[0][1]; edges[0][2]=vertex[1][2]; edges[0][5]=vertex[0][2]; //edge 0-2 edges[1][0]=vertex[0][0]; edges[1][3]=vertex[2][0]; edges[1][1]=vertex[0][1]; edges[1][4]=vertex[2][1]; edges[1][2]=vertex[0][2]; edges[1][5]=vertex[2][2]; //edge 2-1 edges[2][0]=vertex[2][0]; edges[2][3]=vertex[1][0]; edges[2][1]=vertex[2][1]; edges[2][4]=vertex[1][1]; edges[2][2]=vertex[2][2]; edges[2][5]=vertex[1][2]; } else { m=0.0; float slope=0.0; slope=(float)(vertex[2][1]-vertex[0][1])/(float)(vertex[2][0]-vertex[0][0]); midPoint= vertex[0][0]+( (vertex[1][1]-vertex[0][1])/slope ); if(midPoint<vertex[1][0]) { //edge 0-2 edges[0][0]=vertex[0][0]; edges[0][3]=vertex[2][0]; edges[0][1]=vertex[0][1]; edges[0][4]=vertex[2][1]; edges[0][2]=vertex[0][2]; edges[0][5]=vertex[2][2]; //edge 2-1 edges[1][0]=vertex[2][0]; edges[1][3]=vertex[1][0]; edges[1][1]=vertex[2][1]; edges[1][4]=vertex[1][1]; edges[1][2]=vertex[2][2]; edges[1][5]=vertex[1][2]; //edge 1-0 edges[2][0]=vertex[1][0]; edges[2][3]=vertex[0][0]; edges[2][1]=vertex[1][1]; edges[2][4]=vertex[0][1]; edges[2][2]=vertex[1][2]; edges[2][5]=vertex[0][2]; } else if(midPoint>vertex[1][0]) { m=0.0; //edge 0-1 edges[0][0]=vertex[0][0]; edges[0][3]=vertex[1][0]; edges[0][1]=vertex[0][1]; edges[0][4]=vertex[1][1]; edges[0][2]=vertex[0][2]; edges[0][5]=vertex[1][2]; //edge 1-2 edges[1][0]=vertex[1][0]; edges[1][3]=vertex[2][0]; edges[1][1]=vertex[1][1]; edges[1][4]=vertex[2][1]; edges[1][2]=vertex[1][2]; edges[1][5]=vertex[2][2]; //edge 2-0 edges[2][0]=vertex[2][0]; edges[2][3]=vertex[0][0]; edges[2][1]=vertex[2][1]; edges[2][4]=vertex[0][1]; edges[2][2]=vertex[2][2]; edges[2][5]=vertex[0][2]; } } xDiffE0=edges[0][3]-edges[0][0]; xDiffE1=edges[1][3]-edges[1][0]; xDiffE2=edges[2][3]-edges[2][0]; yDiffE0=edges[0][4]-edges[0][1]; yDiffE1=edges[1][4]-edges[1][1]; yDiffE2=edges[2][4]-edges[2][1]; zDiffE0=edges[0][5]-edges[0][2]; zDiffE1=edges[1][5]-edges[1][2]; zDiffE2=edges[2][5]-edges[2][2]; //get coefficients of line a0=yDiffE0; a1=yDiffE1; a2=yDiffE2; b0=-xDiffE0; b1=-xDiffE1; b2=-xDiffE2; c0=xDiffE0*edges[0][1] - yDiffE0*edges[0][0]; c1=xDiffE1*edges[1][1] - yDiffE1*edges[1][0]; c2=xDiffE2*edges[2][1] - yDiffE2*edges[2][0]; float temp=0.0; //get Ax+By+Cz+D A=yDiffE0*zDiffE1-yDiffE1*zDiffE0; B=xDiffE1*zDiffE0-xDiffE0*zDiffE1; C=xDiffE0*yDiffE1-xDiffE1*yDiffE0; temp=A*edges[1][0] + B*edges[1][1] + C*edges[1][2]; D=-temp; //construct bounding box for(int i=0;i<3;i++) { m=0.0; float temp=0.0; if(vertex[i][0]<lowerX) lowerX=vertex[i][0]; if(vertex[i][1]<lowerY) lowerY=vertex[i][1]; temp=lowerY-lowerX; if(vertex[i][0]>upperX) upperX=vertex[i][0]; if(vertex[i][1]>upperY) upperY=vertex[i][1]; } for(int i=lowerY;i<=upperY;i++) { for(int j=lowerX;j<=upperX;j++) { float temp=0.0; v =-(A*j+B*i+D)/C; v0=a0*j+b0*i+c0; v1=a1*j+b1*i+c1; temp=a2*j+b1*i; temp=-temp/C; v2=a2*j+b2*i+c2; if(v<0||v0<0||v1<0||v2<0) continue; int ret=GzGetDisplay(render->display,j,i,&r,&g,&b,&a,&z); float q1,q2,q3; q1=render->flatcolor[0]; q2=render->flatcolor[1]; q3=render->flatcolor[2]; if(z==0 || v < z) ret=GzPutDisplay(render->display,j,i,ctoi(q1),ctoi(q2),ctoi(q3),a,(GzDepth)v); } } return GZ_SUCCESS; }
void Rasterization( GzRender * render, GzCoord * vertex, GzCoord * normXY) { float temp1=0.0,temp2=0.0,temp3=0.0,temp4=0.0,m=0.0,midPoint=0.0; triEdge tEdges[3]; int flag =0; int defVertex[3]={0,1,2}; float xDiffE0,yDiffE0,zDiffE0,xDiffE1,yDiffE1,zDiffE1,xDiffE2,yDiffE2,zDiffE2; float A,B,C,D; float a0,b0,c0,a1,b1,c1,a2,b2,c2; float lowerX=99999999.0,lowerY=99999999.0,upperX=0.0,upperY=0.0; float v0,v1,v2,v; GzIntensity r,g,b,a; GzDepth z; //First sort the vertices by Y if Y is same sort it according to X sortTriangle(vertex,&defVertex[0]); //Assign edge in CCW if(vertex[0][1]== vertex[1][1]) { tEdges[0].x1= vertex[1][0]; tEdges[0].x2= vertex[0][0]; tEdges[0].y1= vertex[1][1]; tEdges[0].y2= vertex[0][1]; tEdges[0].z1= vertex[1][2]; tEdges[0].z2= vertex[0][2]; tEdges[1].x1= vertex[0][0]; tEdges[1].x2= vertex[2][0]; tEdges[1].y1= vertex[0][1]; tEdges[1].y2= vertex[2][1]; tEdges[1].z1= vertex[0][2]; tEdges[1].z2= vertex[2][2]; tEdges[2].x1= vertex[2][0]; tEdges[2].x2= vertex[1][0]; tEdges[2].y1= vertex[2][1]; tEdges[2].y2= vertex[1][1]; tEdges[2].z1= vertex[2][2]; tEdges[2].z2= vertex[1][2]; tEdges[0].tl= defVertex[1]; tEdges[0].hd= defVertex[0]; tEdges[1].tl= defVertex[0]; tEdges[1].hd= defVertex[2]; tEdges[2].tl= defVertex[2]; tEdges[2].hd= defVertex[1]; } if(vertex[1][1]== vertex[2][1]) { tEdges[0].x1= vertex[0][0]; tEdges[0].x2= vertex[1][0]; tEdges[0].y1= vertex[0][1]; tEdges[0].y2= vertex[1][1]; tEdges[0].z1= vertex[0][2]; tEdges[0].z2= vertex[1][2]; tEdges[1].x1= vertex[1][0]; tEdges[1].x2= vertex[2][0]; tEdges[1].y1= vertex[1][1]; tEdges[1].y2= vertex[2][1]; tEdges[1].z1= vertex[1][2]; tEdges[1].z2= vertex[2][2]; tEdges[2].x1= vertex[2][0]; tEdges[2].x2= vertex[0][0]; tEdges[2].y1= vertex[2][1]; tEdges[2].y2= vertex[0][1]; tEdges[2].z1= vertex[2][2]; tEdges[2].z2= vertex[0][2]; tEdges[0].tl= defVertex[0]; tEdges[0].hd= defVertex[1]; tEdges[1].tl= defVertex[1]; tEdges[1].hd= defVertex[2]; tEdges[2].tl= defVertex[2]; tEdges[2].hd= defVertex[0]; } else { float slope=0.0; slope= ( vertex[2][1] - vertex[0][1] ) / ( vertex[2][0] - vertex[0][0] ); midPoint=vertex[0][0]+( ( vertex[1][1] - vertex[0][1] ) / slope ) ; if( vertex[1][0]< midPoint ) { tEdges[0].x1= vertex[0][0]; tEdges[0].x2= vertex[1][0]; tEdges[0].y1= vertex[0][1]; tEdges[0].y2= vertex[1][1]; tEdges[0].z1= vertex[0][2]; tEdges[0].z2= vertex[1][2]; tEdges[1].x1= vertex[1][0]; tEdges[1].x2= vertex[2][0]; tEdges[1].y1= vertex[1][1]; tEdges[1].y2= vertex[2][1]; tEdges[1].z1= vertex[1][2]; tEdges[1].z2= vertex[2][2]; tEdges[2].x1= vertex[2][0]; tEdges[2].x2= vertex[0][0]; tEdges[2].y1= vertex[2][1]; tEdges[2].y2= vertex[0][1]; tEdges[2].z1= vertex[2][2]; tEdges[2].z2= vertex[0][2]; tEdges[0].tl= defVertex[0]; tEdges[0].hd= defVertex[1]; tEdges[1].tl= defVertex[1]; tEdges[1].hd= defVertex[2]; tEdges[2].tl= defVertex[2]; tEdges[2].hd= defVertex[0]; } else if( vertex[1][0]>midPoint ) { tEdges[0].x1= vertex[0][0]; tEdges[0].x2= vertex[2][0]; tEdges[0].y1= vertex[0][1]; tEdges[0].y2= vertex[2][1]; tEdges[0].z1= vertex[0][2]; tEdges[0].z2= vertex[2][2]; tEdges[1].x1= vertex[2][0]; tEdges[1].x2= vertex[1][0]; tEdges[1].y1= vertex[2][1]; tEdges[1].y2= vertex[1][1]; tEdges[1].z1= vertex[2][2]; tEdges[1].z2= vertex[1][2]; tEdges[2].x1= vertex[1][0]; tEdges[2].x2= vertex[0][0]; tEdges[2].y1= vertex[1][1]; tEdges[2].y2= vertex[0][1]; tEdges[2].z1= vertex[1][2]; tEdges[2].z2= vertex[0][2]; tEdges[0].tl= defVertex[0]; tEdges[0].hd= defVertex[2]; tEdges[1].tl= defVertex[2]; tEdges[1].hd= defVertex[1]; tEdges[2].tl= defVertex[1]; tEdges[2].hd= defVertex[0]; } } xDiffE0=tEdges[0].x2 - tEdges[0].x1; xDiffE1= tEdges[1].x2 - tEdges[1].x1; xDiffE2=tEdges[2].x2 - tEdges[2].x1; yDiffE0= tEdges[0].y2 - tEdges[0].y1; yDiffE1=tEdges[1].y2 - tEdges[1].y1; yDiffE2=tEdges[2].y2 - tEdges[2].y1; zDiffE0= tEdges[0].z2 - tEdges[0].z1; zDiffE1= tEdges[1].z2 - tEdges[1].z1; zDiffE2=tEdges[2].z2-tEdges[1].z1; //Find ABC value for the line equation a0 = yDiffE0; a1 = yDiffE1; a2 =yDiffE2; b0 = -xDiffE0; b1 = -xDiffE1; b2 = -xDiffE2; c0 = xDiffE0 * tEdges[0].y1 - yDiffE0 * tEdges[0].x1 ; c1 = xDiffE1 * tEdges[1].y1 - yDiffE1 * tEdges[1].x1 ; c2 = xDiffE2* tEdges[2].y1 - yDiffE2 * tEdges[2].x1 ; //Find Ax+By+Cz+d=0 float temp=0.0; A = yDiffE0 * zDiffE1 - zDiffE0 * yDiffE1; B = - xDiffE0 * zDiffE1 + zDiffE0 * xDiffE1 ; C = xDiffE0 * yDiffE1 - yDiffE0 * xDiffE1; temp=A* vertex[0][0] + B* vertex[0][1] + C* vertex[0][2]; D=-temp; //Find the bounding box for the triangle //construct bounding box createBoundingBox(vertex,&lowerX,&lowerY,&upperX,&upperY); if(render->interp_mode== GZ_NORMALS) { getPlaneCoeff(tEdges,normXY); } else if(render->interp_mode== GZ_COLOR) { GzColor c[3]; memset(c,0,sizeof(GzColor)*3); for( int p =0; p <3; p++ ) doShading(render,c[p],normXY[p]); getPlaneCoeff(tEdges,c); } //Check for each pixel within the bounding box whether it lies in the triangle for(int i=lowerY;i<= upperY; i++ ) { for(int j=lowerX;j<= upperX; j++ ) { GzIntensity r, g, b, a; GzDepth z; v =-(A*j+B*i+D)/C; v0 = a0 * j + b0 * i + c0; v1 = a1 * j + b1 * i + c1; v2 = a2 * j + b2 * i + c2; if(v<0||v0<0||v1<0||v2<0) continue; GzGetDisplay( render->display, j, i, &r, &g, &b, &a, &z ); //Check with prev Z vaule GzColor q; for(int k=0;k<3;k++) q[k] = -( pCof[k].planeA * j + pCof[k].planeB * i + pCof[k].planeD ) / pCof[k].planeC; if(render->interp_mode == GZ_FLAT) { for(int k=0;k<3;k++) q[k] = render->flatcolor[k]; if( v < z || z==0) GzPutDisplay(render->display,j,i,ctoi(q[0]),ctoi(q[1]),ctoi(q[2]),a,(GzDepth )v); } if(render->interp_mode == GZ_COLOR) { if( v < z || z==0) GzPutDisplay(render->display,j,i,ctoi(q[0]),ctoi(q[1]),ctoi(q[2]),a,(GzDepth )v); } else if(render->interp_mode == GZ_NORMALS) { GzColor c; memset(c,0,sizeof(GzColor)); getNormal(q); doShading(render,c,q); if( v < z || z==0) GzPutDisplay(render->display,j,i,ctoi(c[0]),ctoi(c[1]),ctoi(c[2]),a,(GzDepth )v); } } } }
int GzPutTriangle(GzRender *render, int numParts, GzToken *nameList, GzPointer *valueList) /* numParts : how many names and values */ { /* - pass in a triangle description with tokens and values corresponding to GZ_POSITION:3 vert positions in model space - Xform positions of verts - Clip - just discard any triangle with verts behind view plane // ALL OF THEM? or any one of them? - test for triangles with all three verts off-screen - invoke triangle rasterizer */ // error checking if (render == NULL) { return GZ_FAILURE; } if (nameList == NULL) { return GZ_FAILURE; } if (valueList == NULL) { return GZ_FAILURE; } // get Xsm if (render->matlevel > 0) { GzMatrix Xsm, temp; memcpy(Xsm, render->Ximage[0], sizeof(GzMatrix)); // copy first one //copyMatrix(Xsm, render->Ximage[0]); for (int i = 1; i <= render->matlevel; ++i) { memcpy(temp, Xsm, sizeof(GzMatrix)); //copyMatrix(temp, Xsm); Xsm[0][0] = temp[0][0]*render->Ximage[i][0][0] + temp[0][1]*render->Ximage[i][1][0] + temp[0][2]*render->Ximage[i][2][0] + temp[0][3]*render->Ximage[i][3][0]; Xsm[0][1] = temp[0][0]*render->Ximage[i][0][1] + temp[0][1]*render->Ximage[i][1][1] + temp[0][2]*render->Ximage[i][2][1] + temp[0][3]*render->Ximage[i][3][1]; Xsm[0][2] = temp[0][0]*render->Ximage[i][0][2] + temp[0][1]*render->Ximage[i][1][2] + temp[0][2]*render->Ximage[i][2][2] + temp[0][3]*render->Ximage[i][3][2]; Xsm[0][3] = temp[0][0]*render->Ximage[i][0][3] + temp[0][1]*render->Ximage[i][1][3] + temp[0][2]*render->Ximage[i][2][3] + temp[0][3]*render->Ximage[i][3][3]; ///// Xsm[1][0] = temp[1][0]*render->Ximage[i][0][0] + temp[1][1]*render->Ximage[i][1][0] + temp[1][2]*render->Ximage[i][2][0] + temp[1][3]*render->Ximage[i][3][0]; Xsm[1][1] = temp[1][0]*render->Ximage[i][0][1] + temp[1][1]*render->Ximage[i][1][1] + temp[1][2]*render->Ximage[i][2][1] + temp[1][3]*render->Ximage[i][3][1]; Xsm[1][2] = temp[1][0]*render->Ximage[i][0][2] + temp[1][1]*render->Ximage[i][1][2] + temp[1][2]*render->Ximage[i][2][2] + temp[1][3]*render->Ximage[i][3][2]; Xsm[1][3] = temp[1][0]*render->Ximage[i][0][3] + temp[1][1]*render->Ximage[i][1][3] + temp[1][2]*render->Ximage[i][2][3] + temp[1][3]*render->Ximage[i][3][3]; //////////// Xsm[2][0] = temp[2][0]*render->Ximage[i][0][0] + temp[2][1]*render->Ximage[i][1][0] + temp[2][2]*render->Ximage[i][2][0] + temp[2][3]*render->Ximage[i][3][0]; Xsm[2][1] = temp[2][0]*render->Ximage[i][0][1] + temp[2][1]*render->Ximage[i][1][1] + temp[2][2]*render->Ximage[i][2][1] + temp[2][3]*render->Ximage[i][3][1]; Xsm[2][2] = temp[2][0]*render->Ximage[i][0][2] + temp[2][1]*render->Ximage[i][1][2] + temp[2][2]*render->Ximage[i][2][2] + temp[2][3]*render->Ximage[i][3][2]; Xsm[2][3] = temp[2][0]*render->Ximage[i][0][3] + temp[2][1]*render->Ximage[i][1][3] + temp[2][2]*render->Ximage[i][2][3] + temp[2][3]*render->Ximage[i][3][3]; ///////////// Xsm[3][0] = temp[3][0]*render->Ximage[i][0][0] + temp[3][1]*render->Ximage[i][1][0] + temp[3][2]*render->Ximage[i][2][0] + temp[3][3]*render->Ximage[i][3][0]; Xsm[3][1] = temp[3][0]*render->Ximage[i][0][1] + temp[3][1]*render->Ximage[i][1][1] + temp[3][2]*render->Ximage[i][2][1] + temp[3][3]*render->Ximage[i][3][1]; Xsm[3][2] = temp[3][0]*render->Ximage[i][0][2] + temp[3][1]*render->Ximage[i][1][2] + temp[3][2]*render->Ximage[i][2][2] + temp[3][3]*render->Ximage[i][3][2]; Xsm[3][3] = temp[3][0]*render->Ximage[i][0][3] + temp[3][1]*render->Ximage[i][1][3] + temp[3][2]*render->Ximage[i][2][3] + temp[3][3]*render->Ximage[i][3][3]; } // POP EVERYTHING for (int i = render->matlevel; i >= 0; --i) { GzPopMatrix(render); } // push on Xsm GzPushMatrix(render, Xsm); } // Get vert positions for (int i = 0; i < numParts; ++i) { if (nameList[i] == GZ_POSITION) { // get points GzCoord* tri = (GzCoord*) valueList[i]; GzCoord* xformTri = new GzCoord[3]; bool behindVP = false; GzMatrix topMat; int top = render->matlevel; memcpy(topMat, render->Ximage[top], sizeof(GzMatrix)); //copyMatrix(topMat, render->xim float W; for (int j = 0; j < 3; ++j) { // xform verticies xformTri[j][X] = topMat[0][0]*tri[j][X] + topMat[0][1]*tri[j][Y] + topMat[0][2]*tri[j][Z] + topMat[0][3]*1.0; xformTri[j][Y] = topMat[1][0]*tri[j][X] + topMat[1][1]*tri[j][Y] + topMat[1][2]*tri[j][Z] + topMat[1][3]*1.0; xformTri[j][Z] = topMat[2][0]*tri[j][X] + topMat[2][1]*tri[j][Y] + topMat[2][2]*tri[j][Z] + topMat[2][3]*1.0; W = topMat[3][0]*tri[j][X] + topMat[3][1]*tri[j][Y] + topMat[3][2]*tri[j][Z] + topMat[3][3]*1; xformTri[j][X] /= W; xformTri[j][Y] /= W; xformTri[j][Z] /= W; // check if any vets in behind view plane if (xformTri[j][Z] < render->camera.position[Z]) { behindVP = true; break; } } // float x0 = tri[0][X]; // float x1 = tri[1][X]; // float x2 = tri[2][X]; // float tx0 = xformTri[0][X]; // float tx1 = xformTri[1][X]; // float tx2 = xformTri[2][X]; // float y0 = tri[0][Y]; // float y1 = tri[1][Y]; // float y2 = tri[2][Y]; // float ty0 = xformTri[0][Y]; // float ty1 = xformTri[1][Y]; // float ty2 = xformTri[2][Y]; // float z0 = tri[0][Z]; // float z1 = tri[1][Z]; // float z2 = tri[2][Z]; // float tz0 = xformTri[0][Z]; // float tz1 = xformTri[1][Z]; // float tz2 = xformTri[2][Z]; // this tri is in front of viewing plane if (behindVP == true) { break; } // CLIPPING //if (xformTri[0][Z] < render->camera.position[Z] // && xformTri[1][Z] < render->camera.position[Z] // && xformTri[2][Z] < render->camera.position[Z]) { // break; //} //if ((xformTri[0][X] < 0 && xformTri[1][ // check if all verts are in screen (think i handle this in my rasterizer) // RASTERIZE // sort by Y int minY = 0; for (int i = 0; i < 2; ++i) { minY = i; for (int j = i + 1; j < 3; ++j) { if (xformTri[minY][Y] > xformTri[j][Y]) { minY = j; } } // swapping if (minY != i) { float tempX = xformTri[i][X]; float tempY = xformTri[i][Y]; float tempZ = xformTri[i][Z]; xformTri[i][X] = xformTri[minY][X]; xformTri[i][Y] = xformTri[minY][Y]; xformTri[i][Z] = xformTri[minY][Z]; xformTri[minY][X] = tempX; xformTri[minY][Y] = tempY; xformTri[minY][Z] = tempZ; } } // Get bounding box int topY = floor(xformTri[0][Y]); int bottomY = ceil(xformTri[2][Y]); int leftX, rightX; // 0 comes before 1 if (xformTri[0][X] < xformTri[1][X]) { // 201 if (xformTri[2][X] < xformTri[0][X]) { leftX = floor(xformTri[2][X]); rightX = ceil(xformTri[1][X]); } else { //0 leftX = floor(xformTri[0][X]); // 021 if (xformTri[2][X] < xformTri[1][X]) { rightX = ceil(xformTri[1][X]); } else { // 012 rightX = ceil(xformTri[2][X]); } } } else { // 1 comes before 0 //210 if (xformTri[2][X] < xformTri[1][X]) { leftX = floor(xformTri[2][X]); rightX = ceil(xformTri[0][X]); } else { //1 leftX = floor(xformTri[1][X]); // 120 if (xformTri[2][X] < xformTri[0][X]) { rightX = ceil(xformTri[0][X]); } else { // 102 rightX = ceil(xformTri[2][X]); } } } // For Z Interpolation // Ax + By + Cz + D = 0; // xformTri[0] x xformTri[1] = (A, B, C) GzCoord edge01; edge01[X] = xformTri[1][X]- xformTri[0][X]; edge01[Y] = xformTri[1][Y] - xformTri[0][Y]; edge01[Z] = xformTri[1][Z] - xformTri[0][Z]; GzCoord edge12; edge12[X] = xformTri[2][X] - xformTri[1][X]; edge12[Y] = xformTri[2][Y] - xformTri[1][Y]; edge12[Z] = xformTri[2][Z] - xformTri[1][Z]; float A = edge01[Y]*edge12[Z] - edge01[Z]*edge12[Y]; float B = edge01[Z]*edge12[X] - edge01[X]*edge12[Z]; float C = edge01[X]*edge12[Y] - edge01[Y]*edge12[X]; // get D float D = -(A*xformTri[0][X]) - (B*xformTri[0][Y]) - (C*xformTri[0][Z]); // DRAW PIXELS float interpZ; for (int i = leftX; i < rightX; ++i) { // bounds check if (i < 0 || i > render->display->xres) { continue; } for (int j = topY; j < bottomY; ++j) { //// bounds check if (j < 0 || j > render->display->yres) { continue; } // Compute LEES // E(x, y) = dY(x-X) - dX(y-Y) // EDGE 0-1 float e01 = (xformTri[1][Y] - xformTri[0][Y])*((float)i - xformTri[0][X]) - (xformTri[1][X] - xformTri[0][X])*((float)j - xformTri[0][Y]); // EDGE 1-2 float e12 = (xformTri[2][Y] - xformTri[1][Y])*((float)i - xformTri[1][X]) - (xformTri[2][X] - xformTri[1][X])*((float)j - xformTri[1][Y]); // EDGE 2-0 float e20 = (xformTri[0][Y] - xformTri[2][Y])*((float)i - xformTri[2][X]) - (xformTri[0][X] - xformTri[2][X])*((float)j - xformTri[2][Y]); // if all have same sign then this pixel should be drawn if (e01 == 0 || e12 == 0 || e20 == 0) { interpZ = (-(A*i) - (B*j) - D) / C; // get current z at this pixel GzIntensity r, g, b, a; GzDepth z = 0; GzGetDisplay(render->display, i, j, &r, &g, &b, &a, &z); // compare, if interpZ less than draw over if (interpZ < z) { r = (GzIntensity ) ctoi((float) render->flatcolor[0]); g = (GzIntensity ) ctoi((float)render->flatcolor[1]); b = (GzIntensity ) ctoi((float)render->flatcolor[2]); z = interpZ; GzPutDisplay(render->display, i, j, r, g, b, a, z); } } else if ( ((e01 > 0) && (e12 > 0) && (e20 > 0)) || ((e01 < 0) && (e12 < 0) && (e20 < 0))) { //(e01 == 0 && e12 == 0 && e20 == 0) // Interpolate Z value interpZ = (-(A*i) - (B*j) - D) / C; // get current z at this pixel GzIntensity r, g, b, a; GzDepth z = 0; GzGetDisplay(render->display, i, j, &r, &g, &b, &a, &z); // compare, if interpZ less than draw over if (interpZ < z) { r = (GzIntensity ) ctoi((float) render->flatcolor[0]); g = (GzIntensity ) ctoi((float)render->flatcolor[1]); b = (GzIntensity ) ctoi((float)render->flatcolor[2]); z = interpZ; GzPutDisplay(render->display, i, j, r, g, b, a, z); } } } } } } return GZ_SUCCESS; }
int GzPutTriangle(GzRender *render, int numParts, GzToken *nameList, GzPointer *valueList) /* numParts : how many names and values */ { /* - pass in a triangle description with tokens and values corresponding to GZ_POSITION:3 vert positions in model space - Xform positions of verts - Clip - just discard any triangle with verts behind view plane - test for triangles with all three verts off-screen - invoke triangle rasterizer */ if(nameList[0]==GZ_POSITION) { int status=0; GzIntensity red,green,blue,alpha; GzDepth z=INT_MAX; GzCoord v[3],n[3],edge,edge10,edge21,point,nrml,nrml21,nrmlpoint; int inside; float intz; for(int i=0;i<3;i++) for(int j=0;j<3;j++) v[i][j]=((GzCoord*)valueList[0])[i][j]; float Xformvert[4]; for(int i=0; i<3; i++) { float vert4d[4] = {v[i][0],v[i][1],v[i][2],1}; for(int j=0; j<4; j++) { Xformvert[j]=0; for(int k=0;k<4;k++) Xformvert[j]+=(render->Ximage[render->matlevel][j][k]*vert4d[k]); } v[i][0] = Xformvert[0]/Xformvert[3]; v[i][1] = Xformvert[1]/Xformvert[3]; v[i][2] = Xformvert[2]/Xformvert[3]; } for(int i=0;i<3;i++) for(int j=0;j<3;j++) n[i][j]=((GzCoord*)valueList[1])[i][j]; float Xformnorm[4]; for(int i=0; i<3; i++) { float norm4d[4] = {n[i][0],n[i][1],n[i][2],1}; for(int j=0; j<4; j++) { Xformnorm[j]=0; for(int k=0;k<4;k++) Xformnorm[j]+=(render->Xnorm[render->matlevel][j][k]*norm4d[k]); } n[i][0] = Xformnorm[0]/Xformnorm[3]; n[i][1] = Xformnorm[1]/Xformnorm[3]; n[i][2] = Xformnorm[2]/Xformnorm[3]; } float xmax, xmin, ymax, ymin; ymin=xmin=INT_MAX; ymax=xmax=0; for(int i=0;i<3;i++) { if(v[i][0]<xmin) xmin=v[i][0]; if(v[i][0]>xmax) xmax=v[i][0]; if(v[i][1]<ymin) ymin=v[i][1]; if(v[i][1]>ymax) ymax=v[i][1]; } edge10[0] = v[1][0] - v[0][0]; edge10[1] = v[1][1] - v[0][1]; edge10[2] = v[1][2] - v[0][2]; edge21[0] = v[2][0] - v[1][0]; edge21[1] = v[2][1] - v[1][1]; edge21[2] = v[2][2] - v[1][2]; crossproduct(edge21, edge10, nrml21); edge10[2] = 0; edge21[2] = 0; crossproduct(edge21, edge10, nrml); float A, B, C, D; A = nrml21[0]; B = nrml21[1]; C = nrml21[2]; D = -(A*v[1][0] + B*v[1][1] + C*v[1][2]); GzCoord E,colorsA,colorsB,colorsC,colorsD,color[3]; GzCoord normA,normB,normC,normD; E[0] = 0; E[1] = 0; E[2] =-1; for(int i=0;i<3;i++) { GzCoord tempcolor; GzCoord tempnormal; for(int j=0;j<3;j++) tempnormal[j]=n[i][j]; computecolor(render,E,tempnormal,tempcolor); for(int j=0;j<3;j++) color[i][j]=tempcolor[j]; } if(render->interp_mode == GZ_COLOR) { GzCoord colornormal[3]; for(int i=0; i<3; i++) { edge10[2] = color[1][i] - color[0][i]; edge21[2] = color[2][i] - color[1][i]; crossproduct(edge21, edge10, colornormal[i]); colorsA[i] = colornormal[i][0]; colorsB[i] = colornormal[i][1]; colorsC[i] = colornormal[i][2]; colorsD[i] = -(colorsA[i]*v[0][0] + colorsB[i]*v[0][1] + colorsC[i]*color[0][i]); } } else if(render->interp_mode == GZ_NORMALS) { GzCoord interN[3]; for(int i=0; i<3; i++) { edge10[2] = n[1][i]-n[0][i]; edge21[2] = n[2][i]-n[1][i]; crossproduct(edge21,edge10,interN[i]); normA[i] = interN[i][0]; normB[i] = interN[i][1]; normC[i] = interN[i][2]; normD[i] = -(normA[i]*v[0][0] + normB[i]*v[0][1] + normC[i]*n[0][i]); } } for(int x=floor(xmin);x<=ceil(xmax) && x<(render->display->xres);x++) { if(x<0) x=0; for(int y=floor(ymin);y<=ceil(ymax) && y<(render->display->yres);y++) { if(y<0) y=0; inside=0; for(int i=0; i<3; i++) { edge[0] = v[(i+1)%3][0] - v[i][0]; edge[1] = v[(i+1)%3][1] - v[i][1]; edge[2] = 0; point[0] = v[(i+1)%3][0] - x; point[1] = v[(i+1)%3][1] - y; point[2] = 0; crossproduct(edge, point, nrmlpoint); float cond = dotproduct(nrml,nrmlpoint); if(cond > 0) inside=inside+1; else break; } if(inside==3) { intz = -(A*x+B*y+D)/C; status=GzGetDisplay(render->display,x,y,&red,&green,&blue,&alpha,&z); if(intz<z) { GzCoord tempcolor; if(render->interp_mode==GZ_NORMALS) { GzCoord intnormal; for(int i=0;i<3;i++) intnormal[i]=-(normA[i]*x + normB[i]*y + normD[i])/normC[i]; normalize(intnormal); computecolor(render,E,intnormal,tempcolor); } else if(render->interp_mode==GZ_COLOR) { for(int i=0;i<3;i++) tempcolor[i]=-(colorsA[i]*x+colorsB[i]*y+colorsD[i])/colorsC[i]; } status=GzPutDisplay(render->display,x,y,ctoi(tempcolor[0]),ctoi(tempcolor[1]),ctoi(tempcolor[2]),1,intz); } } } } } return GZ_SUCCESS; }
int GzPutTriangle(GzRender *render, int numParts, GzToken *nameList, GzPointer *valueList) /* numParts : how many names and values */ { /* - pass in a triangle description with tokens and values corresponding to GZ_POSITION:3 vert positions in model space - Xform positions of verts - Clip - just discard any triangle with verts behind view plane - test for triangles with all three verts off-screen - invoke triangle rasterizer */ if (render == NULL){ return GZ_FAILURE; } for (int i = 0; i < numParts; i++){ if (nameList[i] == GZ_NULL_TOKEN){ return GZ_FAILURE; } if (nameList[i] == GZ_POSITION){ float* vertices = (float*)valueList[0]; float x1 = *(vertices); float y1 = *(vertices + 1); float z1 = *(vertices + 2); float x2 = *(vertices + 3); float y2 = *(vertices + 4); float z2 = *(vertices + 5); float x3 = *(vertices + 6); float y3 = *(vertices + 7); float z3 = *(vertices + 8); //homogeneous matrix float coord_x[4], coord_y[4], coord_z[4]; coord_x[0] = x1; coord_x[1] = y1; coord_x[2] = z1; coord_x[3] = 1; coord_y[0] = x2; coord_y[1] = y2; coord_y[2] = z2; coord_y[3] = 1; coord_z[0] = x3; coord_z[1] = y3; coord_z[2] = z3; coord_z[3] = 1; float resultant_x[4][1], resultant_y[4][1],resultant_z[4][1]; for (int i = 0; i < 4; i++){ resultant_x[i][0] = 0; for (int j = 0; j < 4; j++){ resultant_x[i][0] = resultant_x[i][0] + ((render->Ximage[render->matlevel][i][j]) * coord_x[j]); } } for (int i = 0; i < 4; i++){ resultant_y[i][0] = 0; for (int j = 0; j < 4; j++){ resultant_y[i][0] = resultant_y[i][0] + ((render->Ximage[render->matlevel][i][j]) * coord_y[j]); } } for (int i = 0; i < 4; i++){ resultant_z[i][0] = 0; for (int j = 0; j < 4; j++){ resultant_z[i][0] = resultant_z[i][0] + ((render->Ximage[render->matlevel][i][j]) * coord_z[j]); } } GzCoord x, y, z; x[X] = resultant_x[0][0] / resultant_x[3][0]; x[Y] = resultant_y[0][0] / resultant_y[3][0]; x[Z] = resultant_z[0][0] / resultant_z[3][0]; y[X] = resultant_x[1][0] / resultant_x[3][0]; y[Y] = resultant_y[1][0] / resultant_y[3][0]; y[Z] = resultant_z[1][0] / resultant_z[3][0]; z[X] = resultant_x[2][0] / resultant_x[3][0]; z[Y] = resultant_y[2][0] / resultant_y[3][0]; z[Z] = resultant_z[2][0] / resultant_z[3][0]; // clipping part if ((x[X] < 0 || x[X] > (render->display->xres)) && (x[Y] < 0 || x[Y] > (render->display->xres)) && (x[Z] < 0 || x[Z] > (render->display->xres))){ return GZ_FAILURE; } if ((y[X] < 0 || y[X] > (render->display->yres)) && (y[Y] < 0 || y[Y] > (render->display->yres)) && (y[Z] < 0 || y[Z] > (render->display->yres))){ return GZ_FAILURE; } if (z[X] < 0 && z[Y] < 0 && z[Z] < 0){ return GZ_FAILURE; } GzCoord tempx = { x1, x2, x3 }; float y_min, y_max; sort_on_y(x, y, z); //sort on y y_min = y[0]; // find minimum y for boundary box y_max = y[2]; // find maximum y for boundary box float tmp; if ((y[1] == y[0]) || (x[1] < x[0])) { tmp = x[0]; x[0] = x[1]; x[1] = tmp; tmp = y[0]; y[0] = y[1]; y[1] = tmp; tmp = z[0]; z[0] = z[1]; z[1] = tmp; } else if ((y[1] == y[2]) || (x[1] > x[2])){ tmp = x[1]; x[1] = x[2]; x[2] = tmp; tmp = y[1]; y[1] = y[2]; y[2] = tmp; tmp = z[1]; z[1] = z[2]; z[2] = tmp; } float coefA = (y[2] - y[0]); float coefB = -(x[2] - x[0]); float coefC = (-coefB*y[0]) - (coefA * x[0]); float xx1 = (-coefB*y[1] - coefC) / coefA; if (xx1 < x[1]){ tmp = y[2]; y[2] = y[1]; y[1] = tmp; tmp = x[2]; x[2] = x[1]; x[1] = tmp; tmp = z[2]; z[2] = z[1]; z[1] = tmp; } // find minimum and maximum x for boundary box float x_min, x_max; if (x[0] < x[1] && x[0] < x[2]){ x_min = x[0]; } else{ if (x[1] < x[2] && x[1] < x[0]){ x_min = x[1]; } else{ x_min = x[2]; } } if (x[0] > x[1] && x[0] > x[2]){ x_max = x[0]; } else{ if (x[1] > x[2] && x[1] > x[0]){ x_max = x[1]; } else{ x_max = x[2]; } } //check boundary conditions if (x_min < 0){ x_min = 0; } if (x_min > 255){ x_min = 255; } if (x_max < 0){ x_max = 0; } if (x_max > 255){ x_max = 255; } if (y_min < 0){ y_min = 0; } if (y_min > 255){ y_min = 255; } if (y_max < 0){ y_max = 0; } if (y_max > 255){ y_max = 255; } float coefA1 = (y[1] - y[0]); float coefA2 = (y[2] - y[1]); float coefA3 = (y[0] - y[2]); float coefB1 = -(x[1] - x[0]); float coefB2 = -(x[2] - x[1]); float coefB3 = -(x[0] - x[2]); float coefC1 = ((-(coefB1)*y[1]) - (coefA1 * x[1])); float coefC2 = ((-(coefB2)*y[2]) - (coefA2 * x[2])); float coefC3 = ((-(coefB3)*y[0]) - (coefA3 * x[0])); float d1, d2, d3; float A, B, C, D; float x11, x22, y11, y22, z11, z22; x11 = (x[1] - x[0]); y11 = (y[1] - y[0]); z11 = (z[1] - z[0]); x22 = (x[2] - x[0]); y22 = (y[2] - y[0]); z22 = (z[2] - z[0]); A = ((y11*z22) - (y22*z11)); B = ((x22*z11) - (x11*z22)); C = ((x11*y22) - (x22*y11)); D = ((y[0] * (B)) + (x[0] * (A)) + (z[0] * (C))) * (-1); int z_inter = 0; for (int i = floor(x_min); i < ceil(x_max); i++){ for (int j = floor(y_min); j < ceil(y_max); j++){ d1 = (coefA1*i) + (coefB1*j) + coefC1; d2 = (coefA2*i) + (coefB2*j) + coefC2; d3 = (coefA3*i) + (coefB3*j) + coefC3; z_inter = -(A*i + B*j + D) / C; if (!(d1 < 0 || d2 < 0 || d3 < 0)){ GzIntensity a, b, c, d; GzDepth z; GzGetDisplay(render->display, i, j, &a, &b, &c, &d, &z); if (z_inter < z || z == 0) { GzPutDisplay(render->display, i, j, ctoi(render->flatcolor[RED]), ctoi(render->flatcolor[GREEN]), ctoi(render->flatcolor[BLUE]), a, z_inter); } } } } } } return GZ_SUCCESS; }
int GzPutTriangle(GzRender *render, int numParts, GzToken *nameList, GzPointer *valueList) /* numParts - how many names and values */ { /* - pass in a triangle description with tokens and values corresponding to GZ_NULL_TOKEN: do nothing - no values GZ_POSITION: 3 vert positions - Invoke the scan converter and return an error code */ if (NULL != nameList && NULL != render && NULL != valueList) { int nLowestY = 0; for (int i = 0; i < numParts; i++) { if (nameList[i] == GZ_POSITION) { // get points GzCoord* gzPoints = (GzCoord*)valueList[i]; // sort the vertices by Y using bubble sort technique for (int i = 0; i <= 1; i++) { nLowestY = i; for (int j = i + 1; j <= 2; j++) { if (gzPoints[nLowestY][Y] > gzPoints[j][Y]) { nLowestY = j; } } if (nLowestY != i) { SwapVertices(gzPoints, nLowestY, i); } } if (gzPoints[0][Y] == gzPoints[1][Y]) { if (gzPoints[0][X] > gzPoints[1][X]) { SwapVertices(gzPoints, 0, 1); } } else if (gzPoints[1][Y] == gzPoints[2][Y]) { if (gzPoints[1][X] < gzPoints[2][X]) { SwapVertices(gzPoints, 2, 1); } } // Find two Edges of the triangle to compute the normal vector GzCoord Triedge12; Triedge12[X] = gzPoints[1][X] - gzPoints[0][X]; Triedge12[Y] = gzPoints[1][Y] - gzPoints[0][Y]; Triedge12[Z] = gzPoints[1][Z] - gzPoints[0][Z]; GzCoord Triedge23; Triedge23[X] = gzPoints[2][X] - gzPoints[1][X]; Triedge23[Y] = gzPoints[2][Y] - gzPoints[1][Y]; Triedge23[Z] = gzPoints[2][Z] - gzPoints[1][Z]; // compute the normal vector by doing the cross product of two edges float fOutvectorX = Triedge12[Y] * Triedge23[Z] - Triedge12[Z] * Triedge23[Y]; float fOutvectorY = Triedge12[Z] * Triedge23[X] - Triedge12[X] * Triedge23[Z]; float fOutvectorZ = Triedge12[X] * Triedge23[Y] - Triedge12[Y] * Triedge23[X]; //Ax + By + Cz + D = 0 ------- [1] float D = -(fOutvectorX * gzPoints[0][X]) - (fOutvectorY * gzPoints[0][Y]) - (fOutvectorZ * gzPoints[0][Z]); int nLeft = 0, nRight = 0; GetBoundingBoxWidth(nLeft, nRight, gzPoints); // get the T/B from the sorted Y vertices int nTop = (int)floor(gzPoints[0][Y]); int nBottom = (int)ceil(gzPoints[2][Y]); float interpolatedZ = 0.0f; // for each pixel(x,y) in the bounding box evaluate equation [1] for (int x = nLeft; x < nRight; x++) { for (int y = nTop; y < nBottom; y++) { float Edge12 = 0.0f, Edge23 = 0.0f, Edge31 = 0.0f; Edge12 = (gzPoints[1][Y] - gzPoints[0][Y])*((float)x - gzPoints[0][X]) - (gzPoints[1][X] - gzPoints[0][X])*((float)y - gzPoints[0][Y]); Edge23 = (gzPoints[2][Y] - gzPoints[1][Y])*((float)x - gzPoints[1][X]) - (gzPoints[2][X] - gzPoints[1][X])*((float)y - gzPoints[1][Y]); Edge31 = (gzPoints[0][Y] - gzPoints[2][Y])*((float)x - gzPoints[2][X]) - (gzPoints[0][X] - gzPoints[2][X])*((float)y - gzPoints[2][Y]); if (((Edge12 > 0) && (Edge23 > 0) && (Edge31 > 0)) || ((Edge12 < 0) && (Edge23 < 0) && (Edge31 < 0)) || (Edge12 == 0 || Edge23 == 0 || Edge31 == 0)) { // Z - buffer to remove hidden surfaces interpolatedZ = (- (fOutvectorX * x) - (fOutvectorY * y) - D) / fOutvectorZ; GzDepth zCurrentValFb = 0; GzIntensity red = 0; GzIntensity green = 0; GzIntensity blue = 0; GzIntensity alpha = 0; // get the current values from the frambuffer GzGetDisplay(render->display, x, y, &red, &green, &blue, &alpha, &zCurrentValFb); // Compare between computed Zpix versus framebuffer Z value. If lesser write new pixel color, else dont do anything if (interpolatedZ < zCurrentValFb) { zCurrentValFb = interpolatedZ; red = (GzIntensity)ctoi((float)render->flatcolor[Red]); green = (GzIntensity)ctoi((float)render->flatcolor[Green]); blue = (GzIntensity)ctoi((float)render->flatcolor[Blue]); //Writing new pixel value to the framebuffer GzPutDisplay(render->display, x, y, red, green, blue, alpha, zCurrentValFb); } } } } } if (nameList[i] == GZ_NULL_TOKEN) { //Do nothing continue; } } return GZ_SUCCESS; } else { return GZ_FAILURE; } }
int GzPutTriangle(GzRender *render, int numParts, GzToken *nameList, GzPointer *valueList) /* numParts - how many names and values */ { /* - pass in a triangle description with tokens and values corresponding to GZ_NULL_TOKEN: do nothing - no values GZ_POSITION: 3 vert positions - Invoke the scan converter and return an error code */ if ((NULL == render) || (NULL == nameList) || (NULL == valueList)) { return GZ_FAILURE; } for (int nCnt = 0; nCnt < numParts; nCnt++) { if (nameList[nCnt] == GZ_POSITION) { GzCoord* acGzCoord; acGzCoord = (GzCoord*)(valueList[nCnt]); GzCoord asGzCoordX = { acGzCoord[0][0], acGzCoord[1][0], acGzCoord[2][0] }; GzCoord asGzCoordY = { acGzCoord[0][1], acGzCoord[1][1], acGzCoord[2][1] }; GzCoord asGzCoordZ = { acGzCoord[0][2], acGzCoord[1][2], acGzCoord[2][2] }; //Sort the matrix according to Y for (int anSortYCnt = 1; anSortYCnt < 3; anSortYCnt++) { if (asGzCoordY[anSortYCnt - 1] > asGzCoordY[anSortYCnt]) { float afSortTemmp; afSortTemmp = asGzCoordX[anSortYCnt - 1]; asGzCoordX[anSortYCnt - 1] = asGzCoordX[anSortYCnt]; asGzCoordX[anSortYCnt] = afSortTemmp; afSortTemmp = asGzCoordY[anSortYCnt - 1]; asGzCoordY[anSortYCnt - 1] = asGzCoordY[anSortYCnt]; asGzCoordY[anSortYCnt] = afSortTemmp; afSortTemmp = asGzCoordZ[anSortYCnt - 1]; asGzCoordZ[anSortYCnt - 1] = asGzCoordZ[anSortYCnt]; asGzCoordZ[anSortYCnt] = afSortTemmp; } } float afGzCoordY_Min = asGzCoordY[0]; // find min y float afGzCoordY_Max = asGzCoordY[2]; // find max y float tmp; for (int anSortYCnt = 1; anSortYCnt < 3; anSortYCnt++) { if ((asGzCoordY[anSortYCnt - 1] == asGzCoordY[anSortYCnt]) && (asGzCoordX[anSortYCnt - 1] > asGzCoordX[anSortYCnt])) { float afSortTemmp; afSortTemmp = asGzCoordX[anSortYCnt - 1]; asGzCoordX[anSortYCnt - 1] = asGzCoordX[anSortYCnt]; asGzCoordX[anSortYCnt] = afSortTemmp; afSortTemmp = asGzCoordY[anSortYCnt - 1]; asGzCoordY[anSortYCnt - 1] = asGzCoordY[anSortYCnt]; asGzCoordY[anSortYCnt] = afSortTemmp; afSortTemmp = asGzCoordZ[anSortYCnt - 1]; asGzCoordZ[anSortYCnt - 1] = asGzCoordZ[anSortYCnt]; asGzCoordZ[anSortYCnt] = afSortTemmp; } } float afCoefA = asGzCoordY[2] - asGzCoordY[0]; float afCoefB = asGzCoordX[0] - asGzCoordX[2]; float afCoefC = -afCoefB*asGzCoordY[0] - afCoefA * asGzCoordX[0]; float acTestX = -(afCoefB*asGzCoordY[1] + afCoefC) / afCoefA; if (acTestX < asGzCoordX[1]) { tmp = asGzCoordY[2]; asGzCoordY[2] = asGzCoordY[1]; asGzCoordY[1] = tmp; tmp = asGzCoordX[2]; asGzCoordX[2] = asGzCoordX[1]; asGzCoordX[1] = tmp; tmp = asGzCoordZ[2]; asGzCoordZ[2] = asGzCoordZ[1]; asGzCoordZ[1] = tmp; } //find the max and min for X and Y float afMaxX, afMinX, afMaxY, afMinY; afMaxX = asGzCoordX[0]; afMinX = asGzCoordX[0]; afMaxY = asGzCoordY[0]; afMinY = asGzCoordY[0]; for (int anCntMinMaxCnt = 1; anCntMinMaxCnt < 3; anCntMinMaxCnt++) { if (afMaxX <= asGzCoordX[anCntMinMaxCnt]) { afMaxX = asGzCoordX[anCntMinMaxCnt]; } if (afMinX >= asGzCoordX[anCntMinMaxCnt]) { afMinX = asGzCoordX[anCntMinMaxCnt]; } if (afMaxY <= asGzCoordY[anCntMinMaxCnt]) { afMaxY = asGzCoordY[anCntMinMaxCnt]; } if (afMinY >= asGzCoordY[anCntMinMaxCnt]) { afMinY = asGzCoordY[anCntMinMaxCnt]; } } //set the boundary of x and y if (afMinX < 0) { afMinX = 0; } else if (afMinX > 255) { afMinX = 255; } if (afMaxX < 0){ afMaxX = 0; } else if (afMaxX > 255) { afMaxX = 255; } if (afMinY < 0){ afMinY = 0; } else if (afMinY > 255) { afMinY = 255; } if (afMaxY < 0){ afMaxY = 0; } else if (afMaxY > 255) { afMaxY = 255; } //set the variants of vertex Ax + By + C = 0 float afCoefA1, afCoefA2, afCoefA3, afCoefB1, afCoefB2, afCoefB3, afCoefC1, afCoefC2, afCoefC3; float AfDiff1, AfDiff2, AfDiff3; float afVar1, afVar2, afVar3, afVar4; GzIntensity asR, asG, asB, asAlpha; GzDepth anZ; int anInterZ; afCoefA1 = asGzCoordY[1] - asGzCoordY[0]; afCoefA2 = asGzCoordY[2] - asGzCoordY[1]; afCoefA3 = asGzCoordY[0] - asGzCoordY[2]; afCoefB1 = -(asGzCoordX[1] - asGzCoordX[0]); afCoefB2 = -(asGzCoordX[2] - asGzCoordX[1]); afCoefB3 = -(asGzCoordX[0] - asGzCoordX[2]); afCoefC1 = ((-(afCoefB1)*asGzCoordY[1]) - (afCoefA1 * asGzCoordX[1])); afCoefC2 = ((-(afCoefB2)*asGzCoordY[2]) - (afCoefA2 * asGzCoordX[2])); afCoefC3 = ((-(afCoefB3)*asGzCoordY[0]) - (afCoefA3 * asGzCoordX[0])); afVar1 = (((asGzCoordY[1] - asGzCoordY[0])*(asGzCoordZ[2] - asGzCoordZ[0])) - ((asGzCoordY[2] - asGzCoordY[0])*(asGzCoordZ[1] - asGzCoordZ[0]))); afVar2 = (((asGzCoordX[2] - asGzCoordX[0])*(asGzCoordZ[1] - asGzCoordZ[0])) - ((asGzCoordX[1] - asGzCoordX[0])*(asGzCoordZ[2] - asGzCoordZ[0]))); afVar3 = (((asGzCoordX[1] - asGzCoordX[0])*(asGzCoordY[2] - asGzCoordY[0])) - ((asGzCoordX[2] - asGzCoordX[0])*(asGzCoordY[1] - asGzCoordY[0]))); afVar4 = -((asGzCoordY[0] * (afVar2)) + (asGzCoordX[0] * (afVar1)) + (asGzCoordZ[0] * (afVar3))); for (int anCntRangeX = int(afMinX); (float)anCntRangeX < (afMaxX); anCntRangeX++){ for (int anCntRangeY = int(afMinY); (float)anCntRangeY < (afMaxY); anCntRangeY++){ AfDiff1 = (afCoefA1*anCntRangeX) + (afCoefB1*anCntRangeY) + afCoefC1; AfDiff2 = (afCoefA2*anCntRangeX) + (afCoefB2*anCntRangeY) + afCoefC2; AfDiff3 = (afCoefA3*anCntRangeX) + (afCoefB3*anCntRangeY) + afCoefC3; anInterZ = -(afVar1*anCntRangeX + afVar2*anCntRangeY + afVar4) / afVar3; if (!(AfDiff1 < 0 || AfDiff2 < 0 || AfDiff3 < 0)){ asR = 0; asG = 0; asB = 0; asAlpha = 0; anZ = 0; if (GZ_FAILURE == GzGetDisplay(render->display, anCntRangeX, anCntRangeY, &asR, &asG, &asB, &asAlpha, &anZ)) { return GZ_FAILURE; } if (anZ == 0||anInterZ < anZ) { if (GZ_FAILURE == GzPutDisplay(render->display, anCntRangeX, anCntRangeY, ctoi(render->flatcolor[RED]), ctoi(render->flatcolor[GREEN]), ctoi(render->flatcolor[BLUE]), asAlpha, anInterZ)) { return GZ_FAILURE; } } } } } } else if (nameList[nCnt] == GZ_NULL_TOKEN) { continue; } } return GZ_SUCCESS; }
int GzPutTriangle(GzRender *render, int numParts, GzToken *nameList, GzPointer *valueList) /* numParts - how many names and values */ { /* - pass in a triangle description with tokens and values corresponding to GZ_NULL_TOKEN: do nothing - no values GZ_POSITION: 3 vert positions - Invoke the scan converter and return an error code */ if (NULL == render || NULL == nameList || NULL == valueList || numParts == 0) return GZ_FAILURE; GzCoord * pre_vertexList, *cur_vertexList, *pre_normalList, *cur_normalList; GzTextureIndex * pre_uvList, * pre_wrapeduvList, * cur_wrapeduvList; bool Triangle_Hidden = false, Triangle_Out = false; for (int i = 0; i < numParts; i++) { //GzMatrix transform_matrix; if (nameList[i] == GZ_POSITION) { pre_vertexList = (GzCoord*)(valueList[i]); cur_vertexList = new GzCoord[3]; for (int i = 0; i < 3; i++) { Transformation(pre_vertexList[i], cur_vertexList[i], render->Ximage[render->matlevel]); cur_vertexList[i][X] += render->Xshift; cur_vertexList[i][Y] += render->Yshift; } } else if (nameList[i] == GZ_NORMAL) { pre_normalList = (GzCoord*)(valueList[i]); cur_normalList = new GzCoord[3]; for (int i = 0; i < 3; i++) Transformation(pre_normalList[i], cur_normalList[i], render->Xnorm[render->matlevel]); } else if (nameList[i] == GZ_TEXTURE_INDEX) { pre_uvList = (GzTextureIndex*)valueList[i]; } else if (nameList[i] == GZ_NULL_TOKEN) { return GZ_SUCCESS; } } cur_wrapeduvList = new GzTextureIndex[2]; //Warp u,v to perspective space (U,V) at verts for (int i = 0; i < 3; i++) { float Vz = cur_vertexList[i][Z] / (INT_MAX - cur_vertexList[i][Z]); cur_wrapeduvList[i][U] = pre_uvList[i][U] / (Vz + 1); cur_wrapeduvList[i][V] = pre_uvList[i][V] / (Vz + 1); } //sort vertexes asa based on the y coordinates then x coordinates in ascendent order, cur_vertexList[2] has the most high y coordinates value float temp_x, temp_y, temp_z; for (int m = 0; m < 2; m++) { for (int n = 0; n < 2 - m; n++) { //aaaading: if 3 vertex is in a line if vertex are overlap each other if ((cur_vertexList[n][Y] > cur_vertexList[n + 1][Y]) || (cur_vertexList[n][X] >cur_vertexList[n + 1][X] && cur_vertexList[n][Y] == cur_vertexList[n + 1][Y])) { //sort vertex temp_x = cur_vertexList[n][X]; temp_y = cur_vertexList[n][Y]; temp_z = cur_vertexList[n][Z]; cur_vertexList[n][X] = cur_vertexList[n + 1][X]; cur_vertexList[n][Y] = cur_vertexList[n + 1][Y]; cur_vertexList[n][Z] = cur_vertexList[n + 1][Z]; cur_vertexList[n + 1][X] = temp_x; cur_vertexList[n + 1][Y] = temp_y; cur_vertexList[n + 1][Z] = temp_z; //sort vertex normal vector temp_x = cur_normalList[n][X]; temp_y = cur_normalList[n][Y]; temp_z = cur_normalList[n][Z]; cur_normalList[n][X] = cur_normalList[n + 1][X]; cur_normalList[n][Y] = cur_normalList[n + 1][Y]; cur_normalList[n][Z] = cur_normalList[n + 1][Z]; cur_normalList[n + 1][X] = temp_x; cur_normalList[n + 1][Y] = temp_y; cur_normalList[n + 1][Z] = temp_z; //sort vertex normal vector temp_x = cur_wrapeduvList[n][X]; temp_y = cur_wrapeduvList[n][Y]; cur_wrapeduvList[n][X] = cur_wrapeduvList[n + 1][X]; cur_wrapeduvList[n][Y] = cur_wrapeduvList[n + 1][Y]; cur_wrapeduvList[n + 1][X] = temp_x; cur_wrapeduvList[n + 1][Y] = temp_y; } } } //Frustums and Clipping if (cur_vertexList[0][Y] < 0 && cur_vertexList[1][Y] < 0 && cur_vertexList[2][Y] < 0) Triangle_Out = true; else if (cur_vertexList[0][Y] > render->display->yres && cur_vertexList[1][Y] > render->display->yres && cur_vertexList[2][Y] > render->display->yres) Triangle_Out = true; else if (cur_vertexList[0][X] < 0 && cur_vertexList[1][X] < 0 && cur_vertexList[2][X] < 0) Triangle_Out = true; else if (cur_vertexList[0][X] > render->display->xres && cur_vertexList[1][X] > render->display->xres && cur_vertexList[2][X] > render->display->xres) Triangle_Out = true; else Triangle_Out = false; for (int n = 0; n < 3; n++) { if (cur_vertexList[n][Z] < 0) { Triangle_Hidden = true; break; } } if (Triangle_Hidden || Triangle_Out) return GZ_SUCCESS; //CW order int cw_flag; float dX_edge[3], dY_edge[3], dZ_edge[3]; // dX_edge_0 represents the edge originates from vertex 0 // horizontal edges situation, include the situation of both horizontal and vertical edges if (cur_vertexList[1][Y] == cur_vertexList[2][Y]) { cw_flag = 1; } else if (cur_vertexList[0][Y] == cur_vertexList[1][Y]) { cw_flag = 2; } // only vertical edges situation else if (cur_vertexList[0][X] == cur_vertexList[1][X]) { if (cur_vertexList[2][X] > cur_vertexList[1][X]){ cw_flag = 1; } else { cw_flag = 2; } } else if (cur_vertexList[0][X] == cur_vertexList[2][X]){ if (cur_vertexList[1][X] < cur_vertexList[2][X]){ cw_flag = 1; } else { cw_flag = 2; } } else if (cur_vertexList[1][X] == cur_vertexList[2][X]){ if (cur_vertexList[0][X] < cur_vertexList[1][X]){ cw_flag = 2; } else { cw_flag = 1; } } // the situation of none horizontal and vertical edges else { float slope_2_0 = (cur_vertexList[2][Y] - cur_vertexList[0][Y]) / (cur_vertexList[2][X] - cur_vertexList[0][X]); float mid_Y_vertex = cur_vertexList[0][X] + ((cur_vertexList[1][Y] - cur_vertexList[0][Y]) / slope_2_0); if (mid_Y_vertex < cur_vertexList[1][X]) { // long edge in the left cw_flag = 2; } else { // long edge in the right cw_flag = 1; } } VectorCW(dX_edge, dY_edge, dZ_edge, cur_vertexList, cw_flag); //get coefficients of edge 0 1 2 dYx + (-dX)y + (dXY - dYX) = 0 Ax + By + C = 0 XY means the vector tail coordinates float A_edge_0, B_edge_0, C_edge_0, A_edge_1, B_edge_1, C_edge_1, A_edge_2, B_edge_2, C_edge_2; A_edge_0 = dY_edge[0]; //A = dY B_edge_0 = -dX_edge[0]; //B = -dX C_edge_0 = dX_edge[0] * cur_vertexList[0][Y] - dY_edge[0] * cur_vertexList[0][X]; //C = dXY - DYX A_edge_1 = dY_edge[1]; B_edge_1 = -dX_edge[1]; C_edge_1 = dX_edge[1] * cur_vertexList[1][Y] - dY_edge[1] * cur_vertexList[1][X]; A_edge_2 = dY_edge[2]; B_edge_2 = -dX_edge[2]; C_edge_2 = dX_edge[2] * cur_vertexList[2][Y] - dY_edge[2] * cur_vertexList[2][X]; //get cofficient for plane equation Ax + By + Cz + D = 0 float A_plane, B_plane, C_plane, D_plane; //(Ax, Ay, Az) X (Bx, By, Bz) = (AyBz - AzBy, AzBx - AxBz, AxBy - AyBx) = (A, B, C), take (A, B, C) into Ax+By+Cz+D = 0 to caculate D //(dX_edge_0, dY_edge_0, dZ_edge_0) X (dX_edge_1, dY_edge_1, dZ_edge_1) A_plane = dY_edge[0] * dZ_edge[1] - dZ_edge[0] * dY_edge[1]; B_plane = dZ_edge[0] * dX_edge[1] - dX_edge[0] * dZ_edge[1]; C_plane = dX_edge[0] * dY_edge[1] - dY_edge[0] * dX_edge[1]; D_plane = 0 - (A_plane * cur_vertexList[0][X] + B_plane * cur_vertexList[0][Y] + C_plane * cur_vertexList[0][Z]); /* Rasterization */ float A_cof_color[3], B_cof_color[3], C_cof_color[3], D_cof_color[3]; float sign_edge_0, sign_edge_1, sign_edge_2; GzDepth pixel_z, pixel_depth; GzIntensity red, green, blue, alpha; GzColor pixel_color, pixel_norm, pixel_wrapeduv; float A_cof_norm[3], B_cof_norm[3], C_cof_norm[3], D_cof_norm[3]; //Interpolation of Color/Normal and caculate coefficients if (render->interp_mode == GZ_COLOR) { GzColor cur_colorList[3]; if (render->tex_fun) { for (int i = 0; i < 3; i++) { // i means the order of the color of three vertex PixelColorShading(render, cur_normalList[i], cur_colorList[i], NULL, GOURAUD_TEXTURE); //Gouraud Shading with texture } } else { for (int i = 0; i < 3; i++) { PixelColorShading(render, cur_normalList[i], cur_colorList[i], NULL, NON_TEXTURE); //Gouraud Shading without texture } } //interpolate color as Z for (int i = 0; i < 3; i++) { /*three different group of X Y Z for each vertex, Z comes from cur_normalList, the first round for vertex 0 is {cur_vertexList[0][X], cur_vertexList[0][Y], cur_normalList[0][X]} */ cur_vertexList[0][Z] = cur_colorList[0][i]; // i = 0 => RED i = 0 => GREEN i = 0 => BLUE cur_vertexList[1][Z] = cur_colorList[1][i]; cur_vertexList[2][Z] = cur_colorList[2][i]; VectorCW(dX_edge, dY_edge, dZ_edge, cur_vertexList, cw_flag); A_cof_color[i] = dY_edge[0] * dZ_edge[1] - dZ_edge[0] * dY_edge[1]; B_cof_color[i] = dZ_edge[0] * dX_edge[1] - dX_edge[0] * dZ_edge[1]; C_cof_color[i] = dX_edge[0] * dY_edge[1] - dY_edge[0] * dX_edge[1]; D_cof_color[i] = 0 - (A_cof_color[i] * cur_vertexList[0][X] + B_cof_color[i] * cur_vertexList[0][Y] + C_cof_color[i] * cur_vertexList[0][Z]); } } else if (render->interp_mode == GZ_NORMALS) { //interpolate normal as Z for (int i = 0; i < 3; i++) { //cof[X] for normal coordinate x interpolation //X Y Z: Screen Space normalized vector(cur_normalList) , light direction : affine/image space cur_vertexList[0][Z] = cur_normalList[0][i]; // i = 0 => X i = 0 => Y i = 0 => Z cur_vertexList[1][Z] = cur_normalList[1][i]; cur_vertexList[2][Z] = cur_normalList[2][i]; VectorCW(dX_edge, dY_edge, dZ_edge, cur_vertexList, cw_flag); A_cof_norm[i] = dY_edge[0] * dZ_edge[1] - dZ_edge[0] * dY_edge[1]; B_cof_norm[i] = dZ_edge[0] * dX_edge[1] - dX_edge[0] * dZ_edge[1]; C_cof_norm[i] = dX_edge[0] * dY_edge[1] - dY_edge[0] * dX_edge[1]; D_cof_norm[i] = 0 - (A_cof_norm[i] * cur_vertexList[0][X] + B_cof_norm[i] * cur_vertexList[0][Y] + C_cof_norm[i] * cur_vertexList[0][Z]); } } //interpolate texture as Z float A_cof_wrapeduv[2], B_cof_wrapeduv[2], C_cof_wrapeduv[2], D_cof_wrapeduv[2]; for (int i = 0; i < 2; i++) { //cof[X] for normal coordinate x interpolation cur_vertexList[0][Z] = cur_wrapeduvList[0][i]; // i = 0 => U i = 1 => V cur_vertexList[1][Z] = cur_wrapeduvList[1][i]; cur_vertexList[2][Z] = cur_wrapeduvList[2][i]; VectorCW(dX_edge, dY_edge, dZ_edge, cur_vertexList, cw_flag); A_cof_wrapeduv[i] = dY_edge[0] * dZ_edge[1] - dZ_edge[0] * dY_edge[1]; B_cof_wrapeduv[i] = dZ_edge[0] * dX_edge[1] - dX_edge[0] * dZ_edge[1]; C_cof_wrapeduv[i] = dX_edge[0] * dY_edge[1] - dY_edge[0] * dX_edge[1]; D_cof_wrapeduv[i] = 0 - (A_cof_wrapeduv[i] * cur_vertexList[0][X] + B_cof_wrapeduv[i] * cur_vertexList[0][Y] + C_cof_wrapeduv[i] * cur_vertexList[0][Z]); } //bounding rectangle float left_boundary = 256.0, top_boundary = 256.0, right_boundary = 0.0, bottom_boundary = 0.0; ////revise here!!!! for (int i = 0; i<3; i++) { if (cur_vertexList[i][X] < left_boundary) left_boundary = cur_vertexList[i][X]; if (cur_vertexList[i][Y] < top_boundary) top_boundary = cur_vertexList[i][Y]; if (cur_vertexList[i][X] > right_boundary) right_boundary = cur_vertexList[i][X]; if (cur_vertexList[i][Y] > bottom_boundary) bottom_boundary = cur_vertexList[i][Y]; } for (int pixel_y = top_boundary; pixel_y <= bottom_boundary; pixel_y++) { for (int pixel_x = left_boundary; pixel_x <= right_boundary; pixel_x++) { // interpolate Z // z = -(Ax + By + D) / C pixel_z = (GzDepth)(-(A_plane * pixel_x + B_plane * pixel_y + D_plane) / C_plane); sign_edge_0 = A_edge_0 * pixel_x + B_edge_0 * pixel_y + C_edge_0; sign_edge_1 = A_edge_1 * pixel_x + B_edge_1 * pixel_y + C_edge_1; sign_edge_2 = A_edge_2 * pixel_x + B_edge_2 * pixel_y + C_edge_2; if (pixel_z >= 0 && sign_edge_0 >= 0 && sign_edge_1 >= 0 && sign_edge_2 >= 0) { // compute interpolated pixel wraped pixel pixel_wrapeduv[U] = -(A_cof_wrapeduv[U] * pixel_x + B_cof_wrapeduv[U] * pixel_y + D_cof_wrapeduv[U]) / C_cof_wrapeduv[U]; pixel_wrapeduv[V] = -(A_cof_wrapeduv[V] * pixel_x + B_cof_wrapeduv[V] * pixel_y + D_cof_wrapeduv[V]) / C_cof_wrapeduv[V]; //unwarp U,V float pixel_unwrapeduv[2]; float Vz = pixel_z * 1.0 / (INT_MAX - pixel_z); pixel_unwrapeduv[U] = pixel_wrapeduv[U] * (Vz + 1); pixel_unwrapeduv[V] = pixel_wrapeduv[V] * (Vz + 1); GzColor pixel_tex; if (render->tex_fun) render->tex_fun(pixel_unwrapeduv[U], pixel_unwrapeduv[V], pixel_tex); GzGetDisplay(render->display, pixel_x, pixel_y, &red, &green, &blue, &alpha, &pixel_depth); if (pixel_depth == 0 || pixel_z < pixel_depth) { //float pixel_red, pixel_green, pixel_blue; if (render->interp_mode == GZ_FLAT) { pixel_color[RED] = render->flatcolor[RED]; pixel_color[GREEN] = render->flatcolor[GREEN]; pixel_color[BLUE] = render->flatcolor[BLUE]; } else if (render->interp_mode == GZ_COLOR) { //for(int k=0;k<3;k++) //q[k] = -(pCof[k].planeA * j + pCof[k].planeB * i + pCof[k].planeD) / pCof[k].planeC; pixel_color[RED] = -(A_cof_color[RED] * pixel_x + B_cof_color[RED] * pixel_y + D_cof_color[RED]) / C_cof_color[RED]; pixel_color[GREEN] = -(A_cof_color[GREEN] * pixel_x + B_cof_color[GREEN] * pixel_y + D_cof_color[GREEN]) / C_cof_color[GREEN]; pixel_color[BLUE] = -(A_cof_color[BLUE] * pixel_x + B_cof_color[BLUE] * pixel_y + D_cof_color[BLUE]) / C_cof_color[BLUE]; if (render->tex_fun) { pixel_color[RED] *= pixel_tex[RED]; pixel_color[GREEN] *= pixel_tex[GREEN]; pixel_color[BLUE] *= pixel_tex[BLUE]; } CHECK_OVERFLOW(pixel_color[RED]); CHECK_OVERFLOW(pixel_color[GREEN]); CHECK_OVERFLOW(pixel_color[BLUE]); } else if (render->interp_mode == GZ_NORMALS) { //Phong Shading //getNormal(q); //for(int k=0;k<3;k++) //q[k] = -( pCof[k].planeA * j + pCof[k].planeB * i + pCof[k].planeD ) / pCof[k].planeC; pixel_norm[X] = -(A_cof_norm[X] * pixel_x + B_cof_norm[X] * pixel_y + D_cof_norm[X]) / C_cof_norm[X]; pixel_norm[Y] = -(A_cof_norm[Y] * pixel_x + B_cof_norm[Y] * pixel_y + D_cof_norm[Y]) / C_cof_norm[Y]; pixel_norm[Z] = -(A_cof_norm[Z] * pixel_x + B_cof_norm[Z] * pixel_y + D_cof_norm[Z]) / C_cof_norm[Z]; if (render->tex_fun) PixelColorShading(render, pixel_norm, pixel_color, pixel_tex, PHONG_TEXTURE); else PixelColorShading(render, pixel_norm, pixel_color, NULL, NON_TEXTURE); } else { return GZ_FAILURE; } GzPutDisplay(render->display, pixel_x, pixel_y, ctoi(pixel_color[RED]), ctoi(pixel_color[GREEN]), ctoi(pixel_color[BLUE]), alpha, pixel_z); } } } } return GZ_SUCCESS; }