int main(){ V3f x(0,0,1); V3f xr(rot_x(x, 0.87)); same("x rotation", x.dot(xr), cos(0.87)); V3f y(0,0,1); V3f yr(rot_y(y, 0.23)); same("y rotation", y.dot(yr), cos(0.23)); V3f z(1,0,0); V3f zr(rot_z(z, 0.19)); same("z rotation", z.dot(zr), cos(0.19)); V3f nx(3,2,5); V3f ny(-2,3,4); V3f nz(-4,4,3.8); V3f nnx(3,2,5); V3f nny(-2,3,4); V3f nnz(-4,4,3.8); ortoNormalize(nnx, nny, nnz); same("x unit", nnx.length(), 1.0); same("y unit", nny.length(), 1.0); same("z unit", nnz.length(), 1.0); V3f tmp; tmp.cross(nnx, nx); same("x colinear", tmp.length(), 0.0); tmp.cross(nnx, nny); tmp-=nnz; same("x orto", tmp.length(), 0); tmp.cross(nny, nnz); tmp-=nnx; same("y orto", tmp.length(), 0); tmp.cross(nnz, nnx); tmp-=nny; same("z orto", tmp.length(), 0); };
//make basis ortonormal again. void ortoNormalize(V3f & nnx, V3f & nny, V3f & nnz){ V3f newy; newy.cross(nnz, nnx); V3f newz; newz.cross(nnx, newy); newy /= newy.length(); newz /= newz.length(); nnx /= nnx.length(); nny = newy; nnz = newz; };
void PhongBrdf::randVonMisesFisher3(V3f mu, float kappa, int n, V3f* directions) { V3f normal(0,0,1); V3f u = mu.cross(normal); float cost = dot(mu,normal); float sint = u.length(); u = u.normalize(); M33f rot(cost + u.x * u.x * (1 - cost), u.x * u.y * (1 - cost) - u.z * sint, u.x * u.z * (1 - cost) + u.y * sint, u.y * u.x * (1 - cost) + u.z * sint, cost + u.y * u.y * (1 - cost), u.y * u.z * (1 - cost) - u.x * sint, u.z * u.x * (1 - cost) - u.y * sint, u.z * u.y * (1 - cost) + u.x * sint, cost + u.z * u.z * (1 - cost)); float c = 2/kappa*(sinh(kappa)); // normalizing constant float y, w, v; for (int i=0; i < n; i++) { y = randomGenerator.RandomFloat(); w = 1/kappa * log( exp(-kappa) + kappa * c * y ); v = 2*M_PI*randomGenerator.RandomFloat(); directions[i].x = sqrt(1-w*w)*cos(v); directions[i].y = sqrt(1-w*w)*sin(v); directions[i].z = w; directions[i] = directions[i]*rot; } }
//-***************************************************************************** void MeshDrwHelper::updateNormals( V3fArraySamplePtr iN ) { if ( !m_valid || !m_meshP ) { makeInvalid(); return; } //std::cout << "normals - " << m_name << std::endl; // Now see if we need to calculate normals. if ( ( m_meshN && iN == m_meshN ) )//|| // ( !iN && m_customN.size() > 0 ) ) { return; } size_t numPoints = m_meshP->size(); m_meshN = iN; m_customN.clear(); // Right now we only handle "vertex varying" normals, // which have the same cardinality as the points if ( !m_meshN || m_meshN->size() != numPoints ) { // Make some custom normals. m_meshN.reset(); m_customN.resize( numPoints ); std::fill( m_customN.begin(), m_customN.end(), V3f( 0.0f ) ); //std::cout << "Recalcing normals for object: " // << m_host.name() << std::endl; for ( size_t tidx = 0; tidx < m_triangles.size(); ++tidx ) { const Tri &tri = m_triangles[tidx]; const V3f &A = (*m_meshP)[tri[0]]; const V3f &B = (*m_meshP)[tri[1]]; const V3f &C = (*m_meshP)[tri[2]]; V3f AB = B - A; V3f AC = C - A; V3f wN = AB.cross( AC ); m_customN[tri[0]] += wN; m_customN[tri[1]] += wN; m_customN[tri[2]] += wN; } // Normalize normals. for ( size_t nidx = 0; nidx < numPoints; ++nidx ) { m_customN[nidx].normalize(); } } }
//-***************************************************************************** void MeshDrwHelper::draw( const DrawContext & iCtx ) const { // Bail if invalid. if ( !m_valid || m_triangles.size() < 1 || !m_meshP ) { return; } const V3f *points = m_meshP->get(); const V3f *normals = NULL; if ( m_meshN && ( m_meshN->size() == m_meshP->size() ) ) { normals = m_meshN->get(); } else if ( m_customN.size() == m_meshP->size() ) { normals = &(m_customN.front()); } #ifndef SIMPLE_ABC_VIEWER_NO_GL_CLIENT_STATE //#if 0 { GL_NOISY( glEnableClientState( GL_VERTEX_ARRAY ) ); if ( normals ) { GL_NOISY( glEnableClientState( GL_NORMAL_ARRAY ) ); GL_NOISY( glNormalPointer( GL_FLOAT, 0, ( const GLvoid * )normals ) ); } GL_NOISY( glVertexPointer( 3, GL_FLOAT, 0, ( const GLvoid * )points ) ); GL_NOISY( glDrawElements( GL_TRIANGLES, ( GLsizei )m_triangles.size() * 3, GL_UNSIGNED_INT, ( const GLvoid * )&(m_triangles[0]) ) ); if ( normals ) { GL_NOISY( glDisableClientState( GL_NORMAL_ARRAY ) ); } GL_NOISY( glDisableClientState( GL_VERTEX_ARRAY ) ); } #else glBegin( GL_TRIANGLES ); for ( size_t i = 0; i < m_triangles.size(); ++i ) { const Tri &tri = m_triangles[i]; const V3f &vertA = points[tri[0]]; const V3f &vertB = points[tri[1]]; const V3f &vertC = points[tri[2]]; if ( normals ) { const V3f &normA = normals[tri[0]]; glNormal3fv( ( const GLfloat * )&normA ); glVertex3fv( ( const GLfloat * )&vertA ); const V3f &normB = normals[tri[1]]; glNormal3fv( ( const GLfloat * )&normB ); glVertex3fv( ( const GLfloat * )&vertB ); const V3f &normC = normals[tri[2]]; glNormal3fv( ( const GLfloat * )&normC ); glVertex3fv( ( const GLfloat * )&vertC ); } else { V3f AB = vertB - vertA; V3f AC = vertC - vertA; V3f N = AB.cross( AC ); if ( N.length() > 1.0e-4f ) { N.normalize(); glNormal3fv( ( const GLfloat * )&N ); } glVertex3fv( ( const GLfloat * )&vertA ); glVertex3fv( ( const GLfloat * )&vertB ); glVertex3fv( ( const GLfloat * )&vertC ); } } glEnd(); #endif }
//-***************************************************************************** void MeshDrwHelper::draw( const DrawContext & iCtx ) const { // Bail if invalid. if ( !m_valid || m_triangles.size() < 1 || !m_meshP ) { return; } const V3f *points = m_meshP->get(); const V3f *normals = NULL; if ( m_meshN && ( m_meshN->size() == m_meshP->size() ) ) { normals = m_meshN->get(); } else if ( m_customN.size() == m_meshP->size() ) { normals = &(m_customN.front()); } // colors const C4f *colors = NULL; if (m_colors.size() == m_meshP->size() ) { colors = &(m_colors.front()); } static MGLFunctionTable *gGLFT = NULL; if (gGLFT == NULL) gGLFT = MHardwareRenderer::theRenderer()->glFunctionTable(); gGLFT->glBegin( MGL_TRIANGLES ); for ( size_t i = 0; i < m_triangles.size(); ++i ) { const Tri &tri = m_triangles[i]; const V3f &vertA = points[tri[0]]; const V3f &vertB = points[tri[1]]; const V3f &vertC = points[tri[2]]; if ( normals ) { const V3f &normA = normals[tri[0]]; gGLFT->glNormal3fv( ( const GLfloat * )&normA ); gGLFT->glVertex3fv( ( const GLfloat * )&vertA ); const V3f &normB = normals[tri[1]]; gGLFT->glNormal3fv( ( const GLfloat * )&normB ); gGLFT->glVertex3fv( ( const GLfloat * )&vertB ); const V3f &normC = normals[tri[2]]; gGLFT->glNormal3fv( ( const GLfloat * )&normC ); gGLFT->glVertex3fv( ( const GLfloat * )&vertC ); } else { V3f AB = vertB - vertA; V3f AC = vertC - vertA; V3f N = AB.cross( AC ); if ( N.length() > 1.0e-4f ) { N.normalize(); gGLFT->glNormal3fv( ( const GLfloat * )&N ); } gGLFT->glVertex3fv( ( const GLfloat * )&vertA ); gGLFT->glVertex3fv( ( const GLfloat * )&vertB ); gGLFT->glVertex3fv( ( const GLfloat * )&vertC ); } } gGLFT->glEnd(); }