void select_glDrawElements(const pointer_state_t* vtx, GLenum mode, GLuint count, GLenum type, GLvoid * indices) { if (count == 0) return; if (vtx->pointer == NULL) return; GLushort *ind = (GLushort*)indices; GLsizei min, max; getminmax_indices(indices, &max, &min, count); max++; GLfloat *vert = copy_gl_array(vtx->pointer, vtx->type, vtx->size, vtx->stride, GL_FLOAT, 3, 0, max); GLfloat tmp[3]; init_select(); GLfloat zmin=1.0f, zmax=0.0f; for (int i=min; i<max; i++) { select_transform(vert+i*3); if (vert[i*3+2]<zmin) zmin=vert[i*3+2]; if (vert[i*3+2]>zmax) zmax=vert[i*3+2]; } if (zmin<0.0f) zmin = 0.0f; if (zmax>1.0f) zmax = 1.0f; #define FOUND() { \ if (zmin<state.selectbuf.zmin) state.selectbuf.zmin=zmin; \ if (zmax>state.selectbuf.zmax) state.selectbuf.zmax=zmax; \ state.selectbuf.hit = 1; \ free(vert); \ return; \ } for (int i=0; i<count; i++) { switch (mode) { case GL_POINTS: if (select_point_in_viewscreen(vert+ind[i]*3)) FOUND(); break; case GL_LINES: if (i%2==1) { if (select_segment_in_viewscreen(vert+ind[(i-1)]*3, vert+ind[i]*3)) FOUND(); } break; case GL_LINE_STRIP: case GL_LINE_LOOP: //FIXME: the last "loop" segment is missing here if (i>0) { if (select_segment_in_viewscreen(vert+ind[(i-1)]*3, vert+ind[i]*3)) FOUND(); } break; case GL_TRIANGLES: if (i%3==2) { if (select_triangle_in_viewscreen(vert+ind[(i-2)]*3, vert+ind[(i-1)]*3, vert+ind[i]*3)) FOUND(); } break; case GL_TRIANGLE_STRIP: if (i>1) { if (select_triangle_in_viewscreen(vert+ind[(i-2)]*3, vert+ind[(i-1)]*3, vert+ind[i]*3)) FOUND(); } break; case GL_TRIANGLE_FAN: if (i>1) { if (select_triangle_in_viewscreen(vert+ind[0]*3, vert+ind[(i-1)]*3, vert+ind[i]*3)) FOUND(); } break; default: return; // Should never go there! } } free(vert); #undef FOUND }
void select_glDrawElements(const pointer_state_t* vtx, GLenum mode, GLuint count, GLenum type, GLvoid * indices) { if (count == 0) return; if (vtx->pointer == NULL) return; GLushort *ind = (GLushort*)indices; GLsizei min, max; getminmax_indices(indices, &max, &min, count); max++; GLfloat *vert = copy_gl_array(vtx->pointer, vtx->type, vtx->size, vtx->stride, GL_FLOAT, 4, 0, max); init_select(); GLfloat zmin=1e10f, zmax=-10e6f; int found = 0; for (int i=min; i<max; i++) { select_transform(vert+i*4); ZMinMax(&glstate->selectbuf.zminoverall, &glstate->selectbuf.zmaxoverall, vert+i*4); } #define FOUND() { \ found = 1; \ glstate->selectbuf.hit = 1; \ } for (int i=0; i<count; i++) { switch (mode) { case GL_POINTS: if (select_point_in_viewscreen(vert+ind[i]*4)) { ZMinMax(&zmin, &zmax, vert+ind[i]*4); FOUND(); } break; case GL_LINES: if (i%2==1) { if (select_segment_in_viewscreen(vert+ind[(i-1)]*4, vert+ind[i]*4)) { ZMinMax(&zmin, &zmax, vert+ind[i-1]*4); ZMinMax(&zmin, &zmax, vert+ind[i]*4); FOUND(); } } break; case GL_LINE_STRIP: case GL_LINE_LOOP: //FIXME: the last "loop" segment is missing here if (i>0) { if (select_segment_in_viewscreen(vert+ind[(i-1)]*4, vert+ind[i]*4)) { ZMinMax(&zmin, &zmax, vert+ind[i-1]*4); ZMinMax(&zmin, &zmax, vert+ind[i]*4); FOUND(); } } break; case GL_TRIANGLES: if (i%3==2) { if (select_triangle_in_viewscreen(vert+ind[(i-2)]*4, vert+ind[(i-1)]*4, vert+ind[i]*4)) { ZMinMax(&zmin, &zmax, vert+ind[i-2]*4); ZMinMax(&zmin, &zmax, vert+ind[i-1]*4); ZMinMax(&zmin, &zmax, vert+ind[i]*4); FOUND(); } } break; case GL_TRIANGLE_STRIP: if (i>1) { if (select_triangle_in_viewscreen(vert+ind[(i-2)]*4, vert+ind[(i-1)]*4, vert+ind[i]*4)) { ZMinMax(&zmin, &zmax, vert+ind[i-2]*4); ZMinMax(&zmin, &zmax, vert+ind[i-1]*4); ZMinMax(&zmin, &zmax, vert+ind[i]*4); FOUND(); } } break; case GL_TRIANGLE_FAN: if (i>1) { if (select_triangle_in_viewscreen(vert+ind[0]*4, vert+ind[(i-1)]*4, vert+ind[i]*4)) ZMinMax(&zmin, &zmax, vert+ind[0]*4); ZMinMax(&zmin, &zmax, vert+ind[i-1]*4); ZMinMax(&zmin, &zmax, vert+ind[i]*4); FOUND(); } break; default: return; // Should never go there! } } free(vert); if(found) { if (zmin<glstate->selectbuf.zmin) glstate->selectbuf.zmin=zmin; if (zmax>glstate->selectbuf.zmax) glstate->selectbuf.zmax=zmax; } #undef FOUND }