/// Draw the shadow for a shape static void pie_DrawShadow(iIMDShape *shape, int flag, int flag_data, Vector3f* light) { unsigned int i, j, n; Vector3f *pVertices; iIMDPoly *pPolys; unsigned int edge_count = 0; static EDGE *edgelist = NULL; static unsigned int edgelistsize = 256; EDGE *drawlist = NULL; if(!edgelist) { edgelist = (EDGE*)malloc(sizeof(EDGE)*edgelistsize); } pVertices = shape->points; if( flag & pie_STATIC_SHADOW && shape->shadowEdgeList ) { drawlist = shape->shadowEdgeList; edge_count = shape->nShadowEdges; } else { for (i = 0, pPolys = shape->polys; i < shape->npolys; ++i, ++pPolys) { Vector3f p[3]; int current, first; for(j = 0; j < 3; j++) { current = pPolys->pindex[j]; p[j] = Vector3f(pVertices[current].x, scale_y(pVertices[current].y, flag, flag_data), pVertices[current].z); } Vector3f normal = crossProduct(p[2] - p[0], p[1] - p[0]); if (normal * *light > 0) { first = pPolys->pindex[0]; for (n = 1; n < pPolys->npnts; n++) { // link to the previous vertex addToEdgeList(pPolys->pindex[n-1], pPolys->pindex[n], edgelist, &edge_count, pVertices); // check if the edgelist is still large enough if(edge_count >= edgelistsize-1) { // enlarge EDGE* newstack; edgelistsize *= 2; newstack = (EDGE *)realloc(edgelist, sizeof(EDGE) * edgelistsize); if (newstack == NULL) { debug(LOG_FATAL, "pie_DrawShadow: Out of memory!"); abort(); return; } edgelist = newstack; debug(LOG_WARNING, "new edge list size: %u", edgelistsize); } } // back to the first addToEdgeList(pPolys->pindex[pPolys->npnts-1], first, edgelist, &edge_count, pVertices); } } //debug(LOG_WARNING, "we have %i edges", edge_count); drawlist = edgelist; if(flag & pie_STATIC_SHADOW) { // first compact the current edgelist for(i = 0, j = 0; i < edge_count; i++) { if(edgelist[i].from < 0) { continue; } edgelist[j] = edgelist[i]; j++; } edge_count = j; // then store it in the imd shape->nShadowEdges = edge_count; shape->shadowEdgeList = (EDGE *)realloc(shape->shadowEdgeList, sizeof(EDGE) * shape->nShadowEdges); memcpy(shape->shadowEdgeList, edgelist, sizeof(EDGE) * shape->nShadowEdges); } } // draw the shadow volume glBegin(GL_QUADS); glNormal3f(0.0, 1.0, 0.0); for(i=0;i<edge_count;i++) { int a = drawlist[i].from, b = drawlist[i].to; if(a < 0) { continue; } glVertex3f(pVertices[b].x, scale_y(pVertices[b].y, flag, flag_data), pVertices[b].z); glVertex3f(pVertices[b].x+light->x, scale_y(pVertices[b].y, flag, flag_data)+light->y, pVertices[b].z+light->z); glVertex3f(pVertices[a].x+light->x, scale_y(pVertices[a].y, flag, flag_data)+light->y, pVertices[a].z+light->z); glVertex3f(pVertices[a].x, scale_y(pVertices[a].y, flag, flag_data), pVertices[a].z); } glEnd(); #ifdef SHOW_SHADOW_EDGES glDisable(GL_DEPTH_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColor4ub(0xFF, 0, 0, 0xFF); glBegin(GL_LINES); for(i = 0; i < edge_count; i++) { int a = drawlist[i].from, b = drawlist[i].to; if(a < 0) { continue; } glVertex3f(pVertices[b].x, scale_y(pVertices[b].y, flag, flag_data), pVertices[b].z); glVertex3f(pVertices[a].x, scale_y(pVertices[a].y, flag, flag_data), pVertices[a].z); } glEnd(); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glEnable(GL_DEPTH_TEST); #endif }
/// Draw the shadow for a shape static void pie_DrawShadow(iIMDShape *shape, int flag, int flag_data, const glm::vec4 &light) { unsigned int i, j, n; Vector3f *pVertices; iIMDPoly *pPolys; static std::vector<EDGE> edgelist; // Static, to save allocations. static std::vector<EDGE> edgelistFlipped; // Static, to save allocations. static std::vector<EDGE> edgelistFiltered; // Static, to save allocations. EDGE *drawlist = NULL; unsigned edge_count; pVertices = shape->points; if( flag & pie_STATIC_SHADOW && shape->shadowEdgeList ) { drawlist = shape->shadowEdgeList; edge_count = shape->nShadowEdges; } else { edgelist.clear(); for (i = 0, pPolys = shape->polys; i < shape->npolys; ++i, ++pPolys) { glm::vec3 p[3]; for(j = 0; j < 3; j++) { int current = pPolys->pindex[j]; p[j] = glm::vec3(pVertices[current].x, scale_y(pVertices[current].y, flag, flag_data), pVertices[current].z); } if (glm::dot(glm::cross(p[2] - p[0], p[1] - p[0]), glm::vec3(light)) > 0.0f) { for (n = 1; n < 3; n++) { // link to the previous vertex addToEdgeList(pPolys->pindex[n-1], pPolys->pindex[n], edgelist); } // back to the first (FIXME - should be 0, not 2?) addToEdgeList(pPolys->pindex[2], pPolys->pindex[0], edgelist); } } // Remove duplicate pairs from the edge list. For example, in the list ((1 2), (2 6), (6 2), (3, 4)), remove (2 6) and (6 2). edgelistFlipped = edgelist; std::for_each(edgelistFlipped.begin(), edgelistFlipped.end(), flipEdge); std::sort(edgelist.begin(), edgelist.end(), edgeLessThan); std::sort(edgelistFlipped.begin(), edgelistFlipped.end(), edgeLessThan); edgelistFiltered.resize(edgelist.size()); edgelistFiltered.erase(std::set_difference(edgelist.begin(), edgelist.end(), edgelistFlipped.begin(), edgelistFlipped.end(), edgelistFiltered.begin(), edgeLessThan), edgelistFiltered.end()); drawlist = &edgelistFiltered[0]; edge_count = edgelistFiltered.size(); //debug(LOG_WARNING, "we have %i edges", edge_count); if(flag & pie_STATIC_SHADOW) { // then store it in the imd shape->nShadowEdges = edge_count; shape->shadowEdgeList = (EDGE *)realloc(shape->shadowEdgeList, sizeof(EDGE) * shape->nShadowEdges); std::copy(drawlist, drawlist + edge_count, shape->shadowEdgeList); } } // draw the shadow volume glBegin(GL_QUADS); glNormal3f(0.0, 1.0, 0.0); for(i=0;i<edge_count;i++) { int a = drawlist[i].from, b = drawlist[i].to; glVertex3f(pVertices[b].x, scale_y(pVertices[b].y, flag, flag_data), pVertices[b].z); glVertex3f(pVertices[b].x + light[0], scale_y(pVertices[b].y, flag, flag_data) + light[1], pVertices[b].z + light[2]); glVertex3f(pVertices[a].x + light[0], scale_y(pVertices[a].y, flag, flag_data) + light[1], pVertices[a].z + light[2]); glVertex3f(pVertices[a].x, scale_y(pVertices[a].y, flag, flag_data), pVertices[a].z); } glEnd(); }
/// Draw the shadow for a shape static void pie_DrawShadow(iIMDShape *shape, int flag, int flag_data, Vector3f* light) { unsigned int i, j, n; Vector3f *pVertices; iIMDPoly *pPolys; static std::vector<EDGE> edgelist; // Static, to save allocations. static std::vector<EDGE> edgelistFlipped; // Static, to save allocations. static std::vector<EDGE> edgelistFiltered; // Static, to save allocations. EDGE *drawlist = NULL; unsigned edge_count; pVertices = shape->points; if( flag & pie_STATIC_SHADOW && shape->shadowEdgeList ) { drawlist = shape->shadowEdgeList; edge_count = shape->nShadowEdges; } else { edgelist.clear(); for (i = 0, pPolys = shape->polys; i < shape->npolys; ++i, ++pPolys) { Vector3f p[3]; for(j = 0; j < 3; j++) { int current = pPolys->pindex[j]; p[j] = Vector3f(pVertices[current].x, scale_y(pVertices[current].y, flag, flag_data), pVertices[current].z); } Vector3f normal = crossProduct(p[2] - p[0], p[1] - p[0]); if (normal * *light > 0) { for (n = 1; n < pPolys->npnts; n++) { // link to the previous vertex addToEdgeList(pPolys->pindex[n-1], pPolys->pindex[n], edgelist); } // back to the first addToEdgeList(pPolys->pindex[pPolys->npnts-1], pPolys->pindex[0], edgelist); } } // Remove duplicate pairs from the edge list. For example, in the list ((1 2), (2 6), (6 2), (3, 4)), remove (2 6) and (6 2). edgelistFlipped = edgelist; std::for_each(edgelistFlipped.begin(), edgelistFlipped.end(), flipEdge); std::sort(edgelist.begin(), edgelist.end(), edgeLessThan); std::sort(edgelistFlipped.begin(), edgelistFlipped.end(), edgeLessThan); edgelistFiltered.resize(edgelist.size()); edgelistFiltered.erase(std::set_difference(edgelist.begin(), edgelist.end(), edgelistFlipped.begin(), edgelistFlipped.end(), edgelistFiltered.begin(), edgeLessThan), edgelistFiltered.end()); drawlist = &edgelistFiltered[0]; edge_count = edgelistFiltered.size(); //debug(LOG_WARNING, "we have %i edges", edge_count); if(flag & pie_STATIC_SHADOW) { // then store it in the imd shape->nShadowEdges = edge_count; shape->shadowEdgeList = (EDGE *)realloc(shape->shadowEdgeList, sizeof(EDGE) * shape->nShadowEdges); std::copy(drawlist, drawlist + edge_count, shape->shadowEdgeList); } } // draw the shadow volume glBegin(GL_QUADS); glNormal3f(0.0, 1.0, 0.0); for(i=0;i<edge_count;i++) { int a = drawlist[i].from, b = drawlist[i].to; glVertex3f(pVertices[b].x, scale_y(pVertices[b].y, flag, flag_data), pVertices[b].z); glVertex3f(pVertices[b].x+light->x, scale_y(pVertices[b].y, flag, flag_data)+light->y, pVertices[b].z+light->z); glVertex3f(pVertices[a].x+light->x, scale_y(pVertices[a].y, flag, flag_data)+light->y, pVertices[a].z+light->z); glVertex3f(pVertices[a].x, scale_y(pVertices[a].y, flag, flag_data), pVertices[a].z); } glEnd(); #ifdef SHOW_SHADOW_EDGES glDisable(GL_DEPTH_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColor4ub(0xFF, 0, 0, 0xFF); glBegin(GL_LINES); for(i = 0; i < edge_count; i++) { int a = drawlist[i].from, b = drawlist[i].to; if(a < 0) { continue; } glVertex3f(pVertices[b].x, scale_y(pVertices[b].y, flag, flag_data), pVertices[b].z); glVertex3f(pVertices[a].x, scale_y(pVertices[a].y, flag, flag_data), pVertices[a].z); } glEnd(); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glEnable(GL_DEPTH_TEST); #endif }