int handle_get_stats(struct cfg *cf, struct rtpp_command *cmd, int verbose) { int len, i, rval; len = 0; for (i = 1; i < cmd->argc && len < (sizeof(cmd->buf_t) - 2); i++) { if (i > 1) { CHECK_OVERFLOW(); len += snprintf(cmd->buf_t + len, sizeof(cmd->buf_t) - len, " "); } if (verbose != 0) { CHECK_OVERFLOW(); len += snprintf(cmd->buf_t + len, sizeof(cmd->buf_t) - len, "%s=", \ cmd->argv[i]); } CHECK_OVERFLOW(); rval = CALL_METHOD(cf->stable->rtpp_stats, nstr, cmd->buf_t + len, sizeof(cmd->buf_t) - len, cmd->argv[i]); if (rval < 0) { return (ECODE_STSFAIL); } len += rval; } CHECK_OVERFLOW(); len += snprintf(cmd->buf_t + len, sizeof(cmd->buf_t) - len, "\n"); rtpc_doreply(cf, cmd->buf_t, len, cmd, 0); return (0); }
int PixelColorShading(GzRender* render, GzCoord pixel_norm, GzColor pixel_color, GzColor pixel_tex, int flag) { GzCoord E = { 0.0, 0.0, -1.0 }; //Light GzCoord R; //Reflection //normarlize vector NormalizeVector(pixel_norm); float specular_component[3], diffuse_component[3], ambient_component[3]; for (int i = 0; i < 3; i++) { specular_component[i] = 0; diffuse_component[i] = 0; } float NE, NL, RE; for (int light_no = 0; light_no < render->numlights; light_no++) { NE = DOTPRODUCT_VECTOR(pixel_norm, E); NormalizeVector(render->lights[light_no].direction); NL = DOTPRODUCT_VECTOR(pixel_norm, render->lights[light_no].direction); //Both negative: flip normal and compute lighting model on backside of surface if (NE < 0 && NL < 0) { pixel_norm[X] *= -1; pixel_norm[Y] *= -1; pixel_norm[Z] *= -1; NE *= -1; NL *= -1; } //Each has different sign: light and eye are on opposite sides of the surface so the light contributes zero else if (NE * NL < 0) { continue; } //calculate Reflection, R = 2(N•L)N - L R[X] = 2 * NL * pixel_norm[X] - render->lights[light_no].direction[X]; R[Y] = 2 * NL * pixel_norm[Y] - render->lights[light_no].direction[Y]; R[Z] = 2 * NL * pixel_norm[Z] - render->lights[light_no].direction[Z]; NormalizeVector(R); RE = DOTPRODUCT_VECTOR(R, E); //RE calculations must be clamped to zero to maintain [0, 1] bounded range if (RE < 0) RE = 0; specular_component[RED] += render->lights[light_no].color[RED] * pow(RE, render->spec); specular_component[GREEN] += render->lights[light_no].color[GREEN] * pow(RE, render->spec); specular_component[BLUE] += render->lights[light_no].color[BLUE] * pow(RE, render->spec); diffuse_component[RED] += render->lights[light_no].color[RED] * NL; diffuse_component[GREEN] += render->lights[light_no].color[GREEN] * NL; diffuse_component[BLUE] += render->lights[light_no].color[BLUE] * NL; } if (flag == NON_TEXTURE) { pixel_color[RED] = render->Ks[RED] * specular_component[RED] + render->Kd[RED] * diffuse_component[RED] + render->Ka[RED] * render->ambientlight.color[RED]; pixel_color[GREEN] = render->Ks[GREEN] * specular_component[GREEN] + render->Kd[GREEN] * diffuse_component[GREEN] + render->Ka[GREEN] * render->ambientlight.color[GREEN]; pixel_color[BLUE] = render->Ks[BLUE] * specular_component[BLUE] + render->Kd[BLUE] * diffuse_component[BLUE] + render->Ka[BLUE] * render->ambientlight.color[BLUE]; } else if (flag == GOURAUD_TEXTURE) { pixel_color[RED] = specular_component[RED] + diffuse_component[RED] + render->ambientlight.color[RED]; pixel_color[GREEN] = specular_component[GREEN] + diffuse_component[GREEN] + render->ambientlight.color[GREEN]; pixel_color[BLUE] = specular_component[BLUE] + diffuse_component[BLUE] + render->ambientlight.color[BLUE]; } else if (flag == PHONG_TEXTURE) { pixel_color[RED] = render->Ks[RED] * specular_component[RED] + pixel_tex[RED] * diffuse_component[RED] + pixel_tex[RED] * render->ambientlight.color[RED]; pixel_color[GREEN] = render->Ks[GREEN] * specular_component[GREEN] + pixel_tex[GREEN] * diffuse_component[GREEN] + pixel_tex[GREEN] * render->ambientlight.color[GREEN]; pixel_color[BLUE] = render->Ks[BLUE] * specular_component[BLUE] + pixel_tex[BLUE] * diffuse_component[BLUE] + pixel_tex[BLUE] * render->ambientlight.color[BLUE]; } CHECK_OVERFLOW(pixel_color[RED]); CHECK_OVERFLOW(pixel_color[GREEN]); CHECK_OVERFLOW(pixel_color[BLUE]); 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; }