bool CalculatePolygonNormalFlat(float* position, float* buffer, int bufferLength, int elementSize, int polygonVertices) { for (int i = 0; i < bufferLength; i += (elementSize * polygonVertices)) { float v1[3], v2[3], n[3], sum[] = {0.0f, 0.0f, 0.0f}; for (int j = 0; j < polygonVertices - 2; ++j) { float *p1 = &position[i], *p2 = &position[i + (j + 2) * elementSize], *p3 = &position[i + (j + 1) * elementSize]; MINUS3(p2, p1, v1); MINUS3(p3, p1, v2); CROSS3(v1, v2, n); normalize3(n); PLUS3(n, sum, sum); } for (int j = 0; j < polygonVertices; ++j) { COPY3(&buffer[i + j * elementSize], sum); } } return true; }
bool CalculateGridNormalFlat(float* position, float* buffer, int bufferLength, int elementSize) { if (elementSize < 3) { return false; } for (int i = 0; i < bufferLength; i += 4 * elementSize) { float *p1 = &position[i], *p2 = &position[i + elementSize], *p3 = &position[i + 2 * elementSize], *p4 = &position[i + 3 * elementSize]; float v1[3], v2[3], n1[3], n2[3], n1pn2[3]; //v1 = p2-p1 MINUS3(p2, p1, v1); MINUS3(p4, p1, v2); //n1 = v1 x v2 CROSS3(v1, v2, n1); MINUS3(p4, p1, v1); MINUS3(p3, p1, v2); CROSS3(v1, v2, n2); normalize3(n1); normalize3(n2); PLUS3(n1, n2, n1pn2); normalize3(n1pn2); COPY3(&buffer[i], n1pn2); COPY3(&buffer[i + elementSize], n1pn2); COPY3(&buffer[i + 2 * elementSize], n1pn2); COPY3(&buffer[i + 3 * elementSize], n1pn2); } return true; }
void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec, GLfloat u, GLfloat v ) { GLuint attr; for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) { struct gl_2d_map *map = exec->eval.map2[attr].map; if (map) { GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; GLfloat data[4]; ASSIGN_4V(data, 0, 0, 0, 1); _math_horner_bezier_surf(map->Points, data, uu, vv, exec->eval.map2[attr].sz, map->Uorder, map->Vorder); COPY_SZ_4V( exec->vtx.attrptr[attr], exec->vtx.attrsz[attr], data ); } } /** Vertex -- EvalCoord2f is a noop if this map not enabled: **/ if (exec->eval.map2[0].map) { struct gl_2d_map *map = exec->eval.map2[0].map; GLfloat uu = (u - map->u1) * map->du; GLfloat vv = (v - map->v1) * map->dv; GLfloat vertex[4]; ASSIGN_4V(vertex, 0, 0, 0, 1); if (exec->ctx->Eval.AutoNormal) { GLfloat normal[4]; GLfloat du[4], dv[4]; _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, exec->eval.map2[0].sz, map->Uorder, map->Vorder); if (exec->eval.map2[0].sz == 4) { du[0] = du[0]*vertex[3] - du[3]*vertex[0]; du[1] = du[1]*vertex[3] - du[3]*vertex[1]; du[2] = du[2]*vertex[3] - du[3]*vertex[2]; dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0]; dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1]; dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2]; } CROSS3(normal, du, dv); NORMALIZE_3FV(normal); normal[3] = 1.0; COPY_SZ_4V( exec->vtx.attrptr[VBO_ATTRIB_NORMAL], exec->vtx.attrsz[VBO_ATTRIB_NORMAL], normal ); } else { _math_horner_bezier_surf(map->Points, vertex, uu, vv, exec->eval.map2[0].sz, map->Uorder, map->Vorder); } if (exec->vtx.attrsz[0] == 4) CALL_Vertex4fv(GET_DISPATCH(), ( vertex )); else CALL_Vertex3fv(GET_DISPATCH(), ( vertex )); } }
bool CalculateGridNormalSmooth(float* position, float* buffer, int bufferLength, int elementSize, int numX, int numY) { if (elementSize < 3) { return false; } for (int i = 0; i < bufferLength; i += 4 * elementSize) { float *p1 = &position[i], *p2 = &position[i + elementSize], *p3 = &position[i + 2 * elementSize], *p4 = &position[i + 3 * elementSize]; float v1[3], v2[3], n1[3], n2[3], n1pn2[3]; //v1 = p2-p1 MINUS3(p2, p1, v1); MINUS3(p4, p1, v2); //n1 = v1 x v2 CROSS3(v1, v2, n1); MINUS3(p4, p1, v1); MINUS3(p3, p1, v2); CROSS3(v1, v2, n2); normalize3(n1); normalize3(n2); PLUS3(n1, n2, n1pn2); normalize3(n1pn2); COPY3(&buffer[i], n1pn2); COPY3(&buffer[i + elementSize], n1); COPY3(&buffer[i + 2 * elementSize], n2); COPY3(&buffer[i + 3 * elementSize], n1pn2); } // average normals in x axis for (int i = 0; i < numX - 1; ++i) { for (int j = 0; j < numY - 2; ++j) { float sum[3]; float *p2, *p3, *pj0, *pj1; p2 = getGridNormal(buffer, numX, numY, elementSize, i, j, 2); p3 = getGridNormal(buffer, numX, numY, elementSize, i, j, 3); pj0 = getGridNormal(buffer, numX, numY, elementSize, i, j + 1, 0); pj1 = getGridNormal(buffer, numX, numY, elementSize, i, j + 1, 1); PLUS3(pj0, p2, sum); COPY3(p2, sum); COPY3(pj0, sum); PLUS3(pj1, p3, sum); COPY3(p3, sum); COPY3(pj1, sum); } } // average normals in y axis for (int j = 0; j < numY - 1; ++j) { for (int i = 0; i < numX - 2; ++i) { float sum[3]; float *p1, *p3, *pi0, *pi2; p1 = getGridNormal(buffer, numX, numY, elementSize, i, j, 1); p3 = getGridNormal(buffer, numX, numY, elementSize, i, j, 3); pi0 = getGridNormal(buffer, numX, numY, elementSize, i + 1, j, 0); pi2 = getGridNormal(buffer, numX, numY, elementSize, i + 1, j, 2); PLUS3(pi0, p1, sum); COPY3(p1, sum); COPY3(pi0, sum); PLUS3(pi2, p3, sum); COPY3(p3, sum); COPY3(pi2, sum); } } return true; }
/** * Determine type and flags from scratch. * * \param mat matrix. * * This is expensive enough to only want to do it once. */ static void analyse_from_scratch( GLmatrix *mat ) { const GLfloat *m = mat->m; GLuint mask = 0; GLuint i; for (i = 0 ; i < 16 ; i++) { if (m[i] == 0.0) mask |= (1<<i); } if (m[0] == 1.0F) mask |= (1<<16); if (m[5] == 1.0F) mask |= (1<<21); if (m[10] == 1.0F) mask |= (1<<26); if (m[15] == 1.0F) mask |= (1<<31); mat->flags &= ~MAT_FLAGS_GEOMETRY; /* Check for translation - no-one really cares */ if ((mask & MASK_NO_TRX) != MASK_NO_TRX) mat->flags |= MAT_FLAG_TRANSLATION; /* Do the real work */ if (mask == (GLuint) MASK_IDENTITY) { mat->type = MATRIX_IDENTITY; } else if ((mask & MASK_2D_NO_ROT) == (GLuint) MASK_2D_NO_ROT) { mat->type = MATRIX_2D_NO_ROT; if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE) mat->flags |= MAT_FLAG_GENERAL_SCALE; } else if ((mask & MASK_2D) == (GLuint) MASK_2D) { GLfloat mm = DOT2(m, m); GLfloat m4m4 = DOT2(m+4,m+4); GLfloat mm4 = DOT2(m,m+4); mat->type = MATRIX_2D; /* Check for scale */ if (SQ(mm-1) > SQ(1e-6) || SQ(m4m4-1) > SQ(1e-6)) mat->flags |= MAT_FLAG_GENERAL_SCALE; /* Check for rotation */ if (SQ(mm4) > SQ(1e-6)) mat->flags |= MAT_FLAG_GENERAL_3D; else mat->flags |= MAT_FLAG_ROTATION; } else if ((mask & MASK_3D_NO_ROT) == (GLuint) MASK_3D_NO_ROT) { mat->type = MATRIX_3D_NO_ROT; /* Check for scale */ if (SQ(m[0]-m[5]) < SQ(1e-6) && SQ(m[0]-m[10]) < SQ(1e-6)) { if (SQ(m[0]-1.0) > SQ(1e-6)) { mat->flags |= MAT_FLAG_UNIFORM_SCALE; } } else { mat->flags |= MAT_FLAG_GENERAL_SCALE; } } else if ((mask & MASK_3D) == (GLuint) MASK_3D) { GLfloat c1 = DOT3(m,m); GLfloat c2 = DOT3(m+4,m+4); GLfloat c3 = DOT3(m+8,m+8); GLfloat d1 = DOT3(m, m+4); GLfloat cp[3]; mat->type = MATRIX_3D; /* Check for scale */ if (SQ(c1-c2) < SQ(1e-6) && SQ(c1-c3) < SQ(1e-6)) { if (SQ(c1-1.0) > SQ(1e-6)) mat->flags |= MAT_FLAG_UNIFORM_SCALE; /* else no scale at all */ } else { mat->flags |= MAT_FLAG_GENERAL_SCALE; } /* Check for rotation */ if (SQ(d1) < SQ(1e-6)) { CROSS3( cp, m, m+4 ); SUB_3V( cp, cp, (m+8) ); if (LEN_SQUARED_3FV(cp) < SQ(1e-6)) mat->flags |= MAT_FLAG_ROTATION; else mat->flags |= MAT_FLAG_GENERAL_3D; } else { mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */ } } else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) { mat->type = MATRIX_PERSPECTIVE; mat->flags |= MAT_FLAG_GENERAL; } else { mat->type = MATRIX_GENERAL; mat->flags |= MAT_FLAG_GENERAL; } }