void CCAMERA::Reset() { m_parametersChanged = true; m_projectionMatrix = glm::mat4( 1.0f ); m_projectionMatrixInv = glm::mat4( 1.0f ); m_rotationMatrix = glm::mat4( 1.0f ); m_rotationMatrixAux = glm::mat4( 1.0f ); m_lastPosition = wxPoint( 0, 0 ); m_zoom = 1.0f; m_zoom_t0 = 1.0f; m_zoom_t1 = 1.0f; m_camera_pos = m_camera_pos_init; m_camera_pos_t0 = m_camera_pos_init; m_camera_pos_t1 = m_camera_pos_init; m_lookat_pos = m_board_lookat_pos_init; m_lookat_pos_t0 = m_board_lookat_pos_init; m_lookat_pos_t1 = m_board_lookat_pos_init; m_rotate_aux = SFVEC3F( 0.0f ); m_rotate_aux_t0 = SFVEC3F( 0.0f ); m_rotate_aux_t1 = SFVEC3F( 0.0f ); updateRotationMatrix(); updateViewMatrix(); m_viewMatrixInverse = glm::inverse( m_viewMatrix ); m_scr_nX.clear(); m_scr_nY.clear(); rebuildProjection(); }
SFVEC3F CSOLDERMASKNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const { if( m_copper_normal_generator ) { const SFVEC3F copperNormal = m_copper_normal_generator->Generate( aRay, aHitInfo ); return copperNormal * SFVEC3F(0.10f); } else return SFVEC3F(0.0f); }
CMATERIAL::CMATERIAL() { m_ambientColor = SFVEC3F( 0.2f, 0.2f, 0.2f ); m_emissiveColor = SFVEC3F( 0.0f, 0.0f, 0.0f ); m_specularColor = SFVEC3F( 1.0f, 1.0f, 1.0f ); m_shinness = 50.2f; m_transparency = 0.0f; // completely opaque m_cast_shadows = true; m_reflection = 0.0f; m_normal_perturbator = NULL; }
SFVEC3F CPOSTSHADER_SSAO::giColorCurve( const SFVEC3F &aColor ) const { const SFVEC3F vec1 = SFVEC3F(1.0f); // http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiIxLjAtKDEvKHgqMS4wKzEuMCkpK3gqMC4xIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiLTAuMDYyMTg0NjE1Mzg0NjE1NTA1IiwiMS4xNDI5ODQ2MTUzODQ2MTQ2IiwiLTAuMTI3MDk5OTk5OTk5OTk5NzciLCIxLjEzMjYiXX1d return vec1 - ( vec1 / (aColor + vec1) ) + aColor * SFVEC3F(0.10f); // http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiIxLjAtKDEuMC8oeCoyLjArMS4wKSkreCowLjEiLCJjb2xvciI6IiMwMDAwMDAifSx7InR5cGUiOjEwMDAsIndpbmRvdyI6WyItMC4wNjIxODQ2MTUzODQ2MTU1MDUiLCIxLjE0Mjk4NDYxNTM4NDYxNDYiLCItMC4xMjcwOTk5OTk5OTk5OTk3NyIsIjEuMTMyNiJdfV0- //return vec1 - ( vec1 / (aColor * SFVEC3F(2.0f) + vec1) ) + aColor * SFVEC3F(0.10f); //return aColor; }
CCAMERA::CCAMERA( float aRangeScale ) { wxLogTrace( m_logTrace, wxT( "CCAMERA::CCAMERA" ) ); m_range_scale = aRangeScale; m_camera_pos_init = SFVEC3F( 0.0f, 0.0f, -(aRangeScale * 2.0f ) ); m_board_lookat_pos_init = SFVEC3F( 0.0f ); m_windowSize = SFVEC2I( 0, 0 ); m_projectionType = PROJECTION_PERSPECTIVE; m_interpolation_mode = INTERPOLATION_BEZIER; Reset(); }
void CCAMERA::Reset_T1() { m_camera_pos_t1 = m_camera_pos_init; m_zoom_t1 = 1.0f; m_rotate_aux_t1 = SFVEC3F( 0.0f ); m_lookat_pos_t1 = m_board_lookat_pos_init; }
CVCYLINDER::CVCYLINDER( SFVEC2F aCenterPoint, float aZmin, float aZmax, float aRadius ) : COBJECT( OBJ3D_CYLINDER ) { m_center = aCenterPoint; m_radius_squared = aRadius * aRadius; m_inv_radius = 1.0f / aRadius; m_bbox.Set( SFVEC3F( aCenterPoint.x - aRadius, aCenterPoint.y - aRadius, aZmin ), SFVEC3F( aCenterPoint.x + aRadius, aCenterPoint.y + aRadius, aZmax ) ); m_bbox.ScaleNextUp(); m_centroid = m_bbox.GetCenter(); }
void CCAMERA::updateFrustum() { // Update matrix and vectors m_viewMatrixInverse = glm::inverse( m_viewMatrix ); m_right = glm::normalize( SFVEC3F( m_viewMatrixInverse * glm::vec4( SFVEC3F( 1.0, 0.0, 0.0 ), 0.0 ) ) ); m_up = glm::normalize( SFVEC3F( m_viewMatrixInverse * glm::vec4( SFVEC3F( 0.0, 1.0, 0.0 ), 0.0 ) ) ); m_dir = glm::normalize( SFVEC3F( m_viewMatrixInverse * glm::vec4( SFVEC3F( 0.0, 0.0, 1.0 ), 0.0 ) ) ); m_pos = SFVEC3F( m_viewMatrixInverse * glm::vec4( SFVEC3F( 0.0, 0.0, 0.0 ), 1.0 ) ); /* * Frustum is a implementation based on a tutorial by * http://www.lighthouse3d.com/tutorials/view-frustum-culling/ */ // compute the centers of the near and far planes m_frustum.nc = m_pos - m_dir * m_frustum.nearD; m_frustum.fc = m_pos - m_dir * m_frustum.farD; // compute the 4 corners of the frustum on the near plane m_frustum.ntl = m_frustum.nc + m_up * m_frustum.nh - m_right * m_frustum.nw; m_frustum.ntr = m_frustum.nc + m_up * m_frustum.nh + m_right * m_frustum.nw; m_frustum.nbl = m_frustum.nc - m_up * m_frustum.nh - m_right * m_frustum.nw; m_frustum.nbr = m_frustum.nc - m_up * m_frustum.nh + m_right * m_frustum.nw; // compute the 4 corners of the frustum on the far plane m_frustum.ftl = m_frustum.fc + m_up * m_frustum.fh - m_right * m_frustum.fw; m_frustum.ftr = m_frustum.fc + m_up * m_frustum.fh + m_right * m_frustum.fw; m_frustum.fbl = m_frustum.fc - m_up * m_frustum.fh - m_right * m_frustum.fw; m_frustum.fbr = m_frustum.fc - m_up * m_frustum.fh + m_right * m_frustum.fw; // Reserve size for precalc values m_right_nX.resize( m_windowSize.x ); m_up_nY.resize( m_windowSize.y ); // Precalc X values for camera -> ray generation const SFVEC3F right_nw = m_right * m_frustum.nw; for( unsigned int x = 0; x < (unsigned int)m_windowSize.x; ++x ) m_right_nX[x] = right_nw * m_scr_nX[x]; // Precalc Y values for camera -> ray generation const SFVEC3F up_nh = m_up * m_frustum.nh; for( unsigned int y = 0; y < (unsigned int)m_windowSize.y; ++y ) m_up_nY[y] = up_nh * m_scr_nY[y]; }
void CCAMERA::updateRotationMatrix() { m_rotationMatrixAux = glm::rotate( glm::mat4( 1.0f ), m_rotate_aux.x, SFVEC3F( 1.0f, 0.0f, 0.0f ) ); m_rotationMatrixAux = glm::rotate( m_rotationMatrixAux, m_rotate_aux.y, SFVEC3F( 0.0f, 1.0f, 0.0f ) ); m_rotationMatrixAux = glm::rotate( m_rotationMatrixAux, m_rotate_aux.z, SFVEC3F( 0.0f, 0.0f, 1.0f ) ); m_parametersChanged = true; updateViewMatrix(); updateFrustum(); }
SFVEC3F CINFO3D_VISU::GetColor( EDA_COLOR_T aColor ) const { const StructColors &colordata = g_ColorRefs[ColorGetBase( aColor )]; static const float inv_255 = 1.0f / 255.0f; const float red = colordata.m_Red * inv_255; const float green = colordata.m_Green * inv_255; const float blue = colordata.m_Blue * inv_255; return SFVEC3F( red, green, blue ); }
CROUNDSEG::CROUNDSEG( const CROUNDSEGMENT2D &aSeg2D, float aZmin, float aZmax ) : COBJECT( OBJ3D_ROUNDSEG ), m_segment( aSeg2D.m_segment ) { m_radius = aSeg2D.GetRadius(); m_radius_squared = m_radius * m_radius; m_inv_radius = 1.0f / m_radius; m_plane_dir_left = SFVEC3F( -m_segment.m_Dir.y, m_segment.m_Dir.x, 0.0f ); m_plane_dir_right = SFVEC3F( m_segment.m_Dir.y, -m_segment.m_Dir.x, 0.0f ); m_bbox.Reset(); m_bbox.Set( SFVEC3F( m_segment.m_Start.x, m_segment.m_Start.y, aZmin), SFVEC3F( m_segment.m_End.x, m_segment.m_End.y, aZmax) ); m_bbox.Set( m_bbox.Min() - SFVEC3F( m_radius, m_radius, 0.0f ), m_bbox.Max() + SFVEC3F( m_radius, m_radius, 0.0f ) ); m_bbox.ScaleNextUp(); m_centroid = m_bbox.GetCenter(); m_center_left = m_centroid + m_plane_dir_left * m_radius; m_center_right = m_centroid + m_plane_dir_right * m_radius; m_seglen_over_two_squared = (m_segment.m_Length / 2.0f) * (m_segment.m_Length / 2.0f); }
SFVEC3F CCOPPERNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const { if( m_board_normal_generator ) { const SFVEC3F boardNormal = m_board_normal_generator->Generate( aRay, aHitInfo ); SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale; const float noise = (m_copper_perlin.noise( hitPos.x + Fast_RandFloat() * 0.1f, hitPos.y ) - 0.5f) * 2.0f; float scratchPattern = (m_copper_perlin.noise( hitPos.x / 100.0f, hitPos.y * 20.0f ) - 0.5f); scratchPattern = glm::clamp( scratchPattern * 5.0f, -1.0f, 1.0f ); const float x = glm::clamp( (noise + scratchPattern) * 0.04f, -0.10f, 0.10f ); const float y = glm::clamp( (noise + (noise * scratchPattern)) * 0.04f, -0.10f, 0.10f ); return SFVEC3F( x, y, 0.0f ) + boardNormal * 0.85f; } else return SFVEC3F(0.0f); }
SFVEC3F CPLASTICSHINENORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const { SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale; const float noise1 = (m_perlin.noise( hitPos.x, hitPos.y, hitPos.z ) - 0.5f); const float noise2 = (m_perlin.noise( hitPos.x * 3.0f, hitPos.y * 3.0f, hitPos.z * 3.0f ) - 0.5f); return SFVEC3F( noise1 * 0.09f + noise2 * 0.08f ); }
SFVEC3F CBOARDNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const { const SFVEC3F &hitPos = aHitInfo.m_HitPoint; // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJzaW4oc2luKHNpbih4KSoxLjkpKjEuNSkiLCJjb2xvciI6IiMwMDAwMDAifSx7InR5cGUiOjEwMDAsIndpbmRvdyI6WyItMC45NjIxMDU3MDgwNzg1MjYyIiwiNy45NzE0MjYyNjc2MDE0MyIsIi0yLjUxNzYyMDM1MTQ4MjQ0OSIsIjIuOTc5OTM3Nzg3Mzk3NTMwMyJdLCJzaXplIjpbNjQ2LDM5Nl19XQ-- // Implement a texture as the "measling crazing blistering" method of FR4 const float x = (glm::sin(glm::sin( glm::sin( hitPos.x * m_scale ) * 1.9f ) * 1.5f ) + 0.0f) * 0.10f; const float y = (glm::sin(glm::sin( glm::sin( hitPos.y * m_scale ) * 1.9f ) * 1.5f ) + 0.0f) * 0.10f; const float z = glm::sin( 2.0f * hitPos.z * m_scale + Fast_RandFloat() * 1.0f ) * 0.2f; return SFVEC3F( x, y, z ); }
SFVEC3F CINFO3D_VISU::GetLayerColor( LAYER_ID aLayerId ) const { wxASSERT( aLayerId < LAYER_ID_COUNT ); const EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( aLayerId ); const StructColors &colordata = g_ColorRefs[ColorGetBase( color )]; static const float inv_255 = 1.0f / 255.0f; const float red = colordata.m_Red * inv_255; const float green = colordata.m_Green * inv_255; const float blue = colordata.m_Blue * inv_255; return SFVEC3F( red, green, blue ); }
void C3D_RENDER_OGL_LEGACY::add_triangle_top_bot( CLAYER_TRIANGLES *aDst, const SFVEC2F &v0, const SFVEC2F &v1, const SFVEC2F &v2, float top, float bot ) { aDst->m_layer_bot_triangles->AddTriangle( SFVEC3F( v0.x, v0.y, bot ), SFVEC3F( v1.x, v1.y, bot ), SFVEC3F( v2.x, v2.y, bot ) ); aDst->m_layer_top_triangles->AddTriangle( SFVEC3F( v2.x, v2.y, top ), SFVEC3F( v1.x, v1.y, top ), SFVEC3F( v0.x, v0.y, top ) ); }
SFVEC3F CPLASTICNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const { SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale; const float noise1 = (m_perlin.noise( hitPos.x, hitPos.y, hitPos.z ) - 0.5f); const float noise2 = (m_perlin.noise( hitPos.x * 5.0f, hitPos.y * 5.0f, hitPos.z * 5.0f ) - 0.5f); const float noise3 = (m_perlin.noise( hitPos.x * 10.0f + Fast_RandFloat() * 0.10f, hitPos.y * 10.0f + Fast_RandFloat() * 0.10f, hitPos.z * 10.0f + Fast_RandFloat() * 0.10f ) - 0.5f); return SFVEC3F( noise1 * 0.08f + noise2 * 0.10f + noise3 * 0.30f ); }
SFVEC3F CMETALBRUSHEDNORMAL::Generate( const RAY &aRay, const HITINFO &aHitInfo ) const { SFVEC3F hitPos = aHitInfo.m_HitPoint * m_scale; SFVEC3F hitPosRelative = hitPos - glm::floor( hitPos ); const float noiseX = (m_perlin.noise( hitPos.x * (60.0f), hitPos.y * 1.0f, hitPos.z * 1.0f ) - 0.5f); const float noiseY = (m_perlin.noise( hitPos.x * 1.0f, hitPos.y * (60.0f), hitPos.z * 1.0f ) - 0.5f); const float noise2 = (m_perlin.noise( hitPos.x * 1.0f, hitPos.y * 1.0f, hitPos.z * 1.0f ) - 0.5f); const float noise3X = (m_perlin.noise( hitPos.x * (80.0f + noise2 * 0.5f), hitPos.y * 0.5f + Fast_RandFloat() * 0.05f, hitPos.z * 0.5f ) - 0.5f ); const float noise3Y = (m_perlin.noise( hitPos.x * 0.5f + Fast_RandFloat() * 0.05f, hitPos.y * (80.0f + noise2 * 0.5f), hitPos.z * 0.5f ) - 0.5f ); // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiIoKHgtZmxvb3IoeCkpK3Npbih4KSleMyIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIi02LjcxNDAwMDAxOTAzMDA3NyIsIjcuMjQ0NjQzNjkyOTY5NzM5IiwiLTMuMTU1NTUyNjAxNDUyNTg4IiwiNS40MzQzODE5OTA1NDczMDY1Il0sInNpemUiOls2NDQsMzk0XX1d // ((x - floor(x))+sin(x))^3 float sawX = (hitPosRelative.x + glm::sin(10.0f * hitPos.x + 5.0f * noise2 + Fast_RandFloat() ) ); sawX = sawX * sawX * sawX; float sawY = (hitPosRelative.y + glm::sin(10.0f * hitPos.y + 5.0f * noise2 + Fast_RandFloat() ) ); sawY = sawY * sawY * sawY; float xOut = sawX * noise3X * 0.07f + noiseX * 0.25f + noise3X * 0.07f; float yOut = sawY * noise3Y * 0.07f + noiseY * 0.25f + noise3Y * 0.07f; const float outLowFreqNoise = noise2 * 0.005f; return SFVEC3F( xOut + outLowFreqNoise, yOut + outLowFreqNoise, 0.0f + outLowFreqNoise ); }
void C3D_RENDER_OGL_LEGACY::generate_cylinder( const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, float aZtop, float aZbot, unsigned int aNr_sides_per_circle, CLAYER_TRIANGLES *aDstLayer ) { std::vector< SFVEC2F > innerContour; std::vector< SFVEC2F > outerContour; generate_ring_contour( aCenter, aInnerRadius, aOuterRadius, aNr_sides_per_circle, innerContour, outerContour, false ); for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i ) { const SFVEC2F &vi0 = innerContour[i + 0]; const SFVEC2F &vi1 = innerContour[i + 1]; const SFVEC2F &vo0 = outerContour[i + 0]; const SFVEC2F &vo1 = outerContour[i + 1]; aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ), SFVEC3F( vi0.x, vi0.y, aZtop ), SFVEC3F( vo0.x, vo0.y, aZtop ), SFVEC3F( vo1.x, vo1.y, aZtop ) ); aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ), SFVEC3F( vo1.x, vo1.y, aZbot ), SFVEC3F( vo0.x, vo0.y, aZbot ), SFVEC3F( vi0.x, vi0.y, aZbot ) ); } aDstLayer->AddToMiddleContourns( outerContour, aZbot, aZtop, true ); aDstLayer->AddToMiddleContourns( innerContour, aZbot, aZtop, false ); }
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CRING2D * aRing, CLAYER_TRIANGLES *aDstLayer, float aZtop, float aZbot ) { const SFVEC2F ¢er = aRing->GetCenter(); const float inner = aRing->GetInnerRadius(); const float outer = aRing->GetOuterRadius(); std::vector< SFVEC2F > innerContour; std::vector< SFVEC2F > outerContour; generate_ring_contour( center, inner, outer, m_settings.GetNrSegmentsCircle( outer * 2.0f ), innerContour, outerContour, false ); // This will add the top and bot quads that will form the approximated ring for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i ) { const SFVEC2F &vi0 = innerContour[i + 0]; const SFVEC2F &vi1 = innerContour[i + 1]; const SFVEC2F &vo0 = outerContour[i + 0]; const SFVEC2F &vo1 = outerContour[i + 1]; aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ), SFVEC3F( vi0.x, vi0.y, aZtop ), SFVEC3F( vo0.x, vo0.y, aZtop ), SFVEC3F( vo1.x, vo1.y, aZtop ) ); aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ), SFVEC3F( vo1.x, vo1.y, aZbot ), SFVEC3F( vo0.x, vo0.y, aZbot ), SFVEC3F( vi0.x, vi0.y, aZbot ) ); } }
bool CVCYLINDER::Intersect( const RAY &aRay, HITINFO &aHitInfo ) const { // Based on: // http://www.cs.utah.edu/~lha/Code%206620%20/Ray4/Cylinder.cpp // Ray-sphere intersection: geometric // ///////////////////////////////////////////////////////////////////////// const double OCx_Start = aRay.m_Origin.x - m_center.x; const double OCy_Start = aRay.m_Origin.y - m_center.y; const double p_dot_p = OCx_Start * OCx_Start + OCy_Start * OCy_Start; const double a = (double)aRay.m_Dir.x * (double)aRay.m_Dir.x + (double)aRay.m_Dir.y * (double)aRay.m_Dir.y; const double b = (double)aRay.m_Dir.x * (double)OCx_Start + (double)aRay.m_Dir.y * (double)OCy_Start; const double c = p_dot_p - m_radius_squared; const float delta = (float)(b * b - a * c); bool hitResult = false; if( delta > FLT_EPSILON ) { const float inv_a = 1.0 / a; const float sdelta = sqrtf( delta ); const float t = (-b - sdelta) * inv_a; const float z = aRay.m_Origin.z + t * aRay.m_Dir.z; if( (z >= m_bbox.Min().z) && (z <= m_bbox.Max().z) ) { if( t < aHitInfo.m_tHit ) { hitResult = true; aHitInfo.m_tHit = t; } } if( !hitResult ) { const float t1 = (-b + sdelta) * inv_a; const float z1 = aRay.m_Origin.z + t1 * aRay.m_Dir.z; if( (z1 > m_bbox.Min().z ) && (z1 < m_bbox.Max().z ) ) { if( t1 < aHitInfo.m_tHit ) { hitResult = true; aHitInfo.m_tHit = t1; } } } } if( hitResult ) { aHitInfo.m_HitPoint = aRay.at( aHitInfo.m_tHit ); const SFVEC2F hitPoint2D = SFVEC2F( aHitInfo.m_HitPoint.x, aHitInfo.m_HitPoint.y ); aHitInfo.m_HitNormal = SFVEC3F( -(hitPoint2D.x - m_center.x) * m_inv_radius, -(hitPoint2D.y - m_center.y) * m_inv_radius, 0.0f ); m_material->PerturbeNormal( aHitInfo.m_HitNormal, aRay, aHitInfo ); aHitInfo.pHitObject = this; } return hitResult; }
SFVEC3F CPOSTSHADER_SSAO::Shade( const SFVEC2I &aShaderPos ) const { // Test source code //return SFVEC3F( GetShadowFactorAt( aShaderPos ) ); //return GetColorAt( aShaderPos ); //return SFVEC3F( 1.0f - GetDepthNormalizedAt( aShaderPos ) ); //return SFVEC3F( (1.0f / GetDepthAt( aShaderPos )) * 0.5f ); //return SFVEC3F( 1.0f - GetDepthNormalizedAt( aShaderPos ) + // (1.0f / GetDepthAt( aShaderPos )) * 0.5f ); #if 1 float cdepth = GetDepthAt( aShaderPos ); if( cdepth > FLT_EPSILON ) { float cNormalizedDepth = GetDepthNormalizedAt( aShaderPos ); wxASSERT( cNormalizedDepth <= 1.0f ); wxASSERT( cNormalizedDepth >= 0.0f ); cdepth = ( (1.50f - cNormalizedDepth) + ( 1.0f - (1.0f / (cdepth + 1.0f) ) ) * 2.5f ); // Test source code //cdepth = ( (1.75f - cNormalizedDepth) + (1.0f / cdepth) * 2.0f ); //cdepth = 1.5f - cNormalizedDepth; //cdepth = (1.0f / cdepth) * 2.0f; // read current normal,position and color. const SFVEC3F n = GetNormalAt( aShaderPos ); const SFVEC3F p = GetPositionAt( aShaderPos ); //const SFVEC3F col = GetColorAt( aShaderPos ); const float shadowFactor = GetShadowFactorAt( aShaderPos ); // initialize variables: float ao = 0.0f; SFVEC3F gi = SFVEC3F(0.0f); // This calculated the "window range" of the shader. So it will get // more or less sparsed samples const int incx = 3; const int incy = 3; //3 rounds of 8 samples each. for( unsigned int i = 0; i < 3; ++i ) { static const int mask[3] = { 0x01, 0x03, 0x03 }; const int pw = 1 + (Fast_rand() & mask[i]); const int ph = 1 + (Fast_rand() & mask[i]); const int npw = (int)((pw + incx * i) * cdepth ); const int nph = (int)((ph + incy * i) * cdepth ); const SFVEC3F ddiff = GetPositionAt( aShaderPos + SFVEC2I( npw, nph ) ) - p; const SFVEC3F ddiff2 = GetPositionAt( aShaderPos + SFVEC2I( npw,-nph ) ) - p; const SFVEC3F ddiff3 = GetPositionAt( aShaderPos + SFVEC2I(-npw, nph ) ) - p; const SFVEC3F ddiff4 = GetPositionAt( aShaderPos + SFVEC2I(-npw,-nph ) ) - p; const SFVEC3F ddiff5 = GetPositionAt( aShaderPos + SFVEC2I( 0, nph ) ) - p; const SFVEC3F ddiff6 = GetPositionAt( aShaderPos + SFVEC2I( 0,-nph ) ) - p; const SFVEC3F ddiff7 = GetPositionAt( aShaderPos + SFVEC2I( npw, 0 ) ) - p; const SFVEC3F ddiff8 = GetPositionAt( aShaderPos + SFVEC2I(-npw, 0 ) ) - p; ao+= aoFF( aShaderPos, ddiff , n, npw, nph, shadowFactor ); ao+= aoFF( aShaderPos, ddiff2, n, npw,-nph, shadowFactor ); ao+= aoFF( aShaderPos, ddiff3, n, -npw, nph, shadowFactor ); ao+= aoFF( aShaderPos, ddiff4, n, -npw,-nph, shadowFactor ); ao+= aoFF( aShaderPos, ddiff5, n, 0, nph, shadowFactor ); ao+= aoFF( aShaderPos, ddiff6, n, 0,-nph, shadowFactor ); ao+= aoFF( aShaderPos, ddiff7, n, npw, 0, shadowFactor ); ao+= aoFF( aShaderPos, ddiff8, n, -npw, 0, shadowFactor ); gi+= giFF( aShaderPos, ddiff , n, npw, nph) * giColorCurve( GetColorAt( aShaderPos + SFVEC2I( npw, nph ) ) ); gi+= giFF( aShaderPos, ddiff2, n, npw, -nph) * giColorCurve( GetColorAt( aShaderPos + SFVEC2I( npw,-nph ) ) ); gi+= giFF( aShaderPos, ddiff3, n,-npw, nph) * giColorCurve( GetColorAt( aShaderPos + SFVEC2I( -npw, nph ) ) ); gi+= giFF( aShaderPos, ddiff4, n,-npw, -nph) * giColorCurve( GetColorAt( aShaderPos + SFVEC2I( -npw,-nph ) ) ); gi+= giFF( aShaderPos, ddiff5, n, 0.0f, nph) * giColorCurve( GetColorAt( aShaderPos + SFVEC2I( 0, nph ) ) ); gi+= giFF( aShaderPos, ddiff6, n, 0.0f,-nph) * giColorCurve( GetColorAt( aShaderPos + SFVEC2I( 0,-nph ) ) ); gi+= giFF( aShaderPos, ddiff7, n, npw, 0.0f) * giColorCurve( GetColorAt( aShaderPos + SFVEC2I( npw, 0) ) ); gi+= giFF( aShaderPos, ddiff8, n,-npw, 0.0f) * giColorCurve( GetColorAt( aShaderPos + SFVEC2I( -npw, 0) ) ); } ao = (ao / 24.0f) + 0.0f; // Apply a bias for the ambient oclusion gi = (gi * 5.0f / 24.0f); // Apply a bias for the global illumination //return SFVEC3F(ao); return SFVEC3F( SFVEC3F(ao) - gi); // Test source code //return SFVEC3F( col ); //return SFVEC3F( col - SFVEC3F(ao) + gi * 5.0f ); //return SFVEC3F( SFVEC3F(1.0f) - SFVEC3F(ao) + gi * 5.0f ); //return SFVEC3F(cdepth); //return 1.0f - SFVEC3F(ao); //return SFVEC3F(ao); } else return SFVEC3F(0.0f); #endif }
BVHPrimitiveInfo() { primitiveNumber = 0; bounds.Reset(); centroid = SFVEC3F( 0.0f ); }
BVHBuildNode *CBVH_PBRT::HLBVHBuild( const std::vector<BVHPrimitiveInfo> &primitiveInfo, int *totalNodes, CONST_VECTOR_OBJECT &orderedPrims ) { // Compute bounding box of all primitive centroids CBBOX bounds; bounds.Reset(); for( unsigned int i = 0; i < primitiveInfo.size(); ++i ) bounds.Union( primitiveInfo[i].centroid ); // Compute Morton indices of primitives std::vector<MortonPrimitive> mortonPrims( primitiveInfo.size() ); for( int i = 0; i < (int)primitiveInfo.size(); ++i ) { // Initialize _mortonPrims[i]_ for _i_th primitive const int mortonBits = 10; const int mortonScale = 1 << mortonBits; wxASSERT( primitiveInfo[i].primitiveNumber < (int)primitiveInfo.size() ); mortonPrims[i].primitiveIndex = primitiveInfo[i].primitiveNumber; const SFVEC3F centroidOffset = bounds.Offset( primitiveInfo[i].centroid ); wxASSERT( (centroidOffset.x >= 0.0f) && (centroidOffset.x <= 1.0f) ); wxASSERT( (centroidOffset.y >= 0.0f) && (centroidOffset.y <= 1.0f) ); wxASSERT( (centroidOffset.z >= 0.0f) && (centroidOffset.z <= 1.0f) ); mortonPrims[i].mortonCode = EncodeMorton3( centroidOffset * SFVEC3F( (float)mortonScale ) ); } // Radix sort primitive Morton indices RadixSort( &mortonPrims ); // Create LBVH treelets at bottom of BVH // Find intervals of primitives for each treelet std::vector<LBVHTreelet> treeletsToBuild; for( int start = 0, end = 1; end <= (int)mortonPrims.size(); ++end ) { const uint32_t mask = 0b00111111111111000000000000000000; if( (end == (int)mortonPrims.size()) || ( (mortonPrims[start].mortonCode & mask) != (mortonPrims[end].mortonCode & mask) ) ) { // Add entry to _treeletsToBuild_ for this treelet const int numPrimitives = end - start; const int maxBVHNodes = 2 * numPrimitives; // !TODO: implement a memory arena BVHBuildNode *nodes = static_cast<BVHBuildNode *>( _mm_malloc( maxBVHNodes * sizeof( BVHBuildNode ), L1_CACHE_LINE_SIZE ) ); m_addresses_pointer_to_mm_free.push_back( nodes ); for( int i = 0; i < maxBVHNodes; ++i ) { nodes[i].bounds.Reset(); nodes[i].firstPrimOffset = 0; nodes[i].nPrimitives = 0; nodes[i].splitAxis = 0; nodes[i].children[0] = NULL; nodes[i].children[1] = NULL; } LBVHTreelet tmpTreelet; tmpTreelet.startIndex = start; tmpTreelet.numPrimitives = numPrimitives; tmpTreelet.buildNodes = nodes; treeletsToBuild.push_back( tmpTreelet ); start = end; } } // Create LBVHs for treelets in parallel int atomicTotal = 0; int orderedPrimsOffset = 0; orderedPrims.resize( m_primitives.size() ); for( int index = 0; index < (int)treeletsToBuild.size(); ++index ) { // Generate _index_th LBVH treelet int nodesCreated = 0; const int firstBit = 29 - 12; LBVHTreelet &tr = treeletsToBuild[index]; wxASSERT( tr.startIndex < (int)mortonPrims.size() ); tr.buildNodes = emitLBVH( tr.buildNodes, primitiveInfo, &mortonPrims[tr.startIndex], tr.numPrimitives, &nodesCreated, orderedPrims, &orderedPrimsOffset, firstBit ); atomicTotal += nodesCreated; } *totalNodes = atomicTotal; // Initialize _finishedTreelets_ with treelet root node pointers std::vector<BVHBuildNode *> finishedTreelets; finishedTreelets.reserve( treeletsToBuild.size() ); for( int index = 0; index < (int)treeletsToBuild.size(); ++index ) finishedTreelets.push_back( treeletsToBuild[index].buildNodes ); // Create and return SAH BVH from LBVH treelets return buildUpperSAH( finishedTreelets, 0, finishedTreelets.size(), totalNodes ); }
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CFILLEDCIRCLE2D * aFilledCircle, CLAYER_TRIANGLES *aDstLayer, float aZtop, float aZbot ) { const SFVEC2F ¢er = aFilledCircle->GetCenter(); const float radius = aFilledCircle->GetRadius() * 2.0f; // Double because the render triangle // This is a small adjustment to the circle texture const float texture_factor = (8.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f; const float f = (sqrtf(2.0f) / 2.0f) * radius * texture_factor; // Top and Bot segments ends are just triangle semi-circles, so need to add // it in duplicated aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZtop ), SFVEC3F( center.x - f, center.y, aZtop ), SFVEC3F( center.x, center.y - f, aZtop ) ); aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZtop ), SFVEC3F( center.x + f, center.y, aZtop ), SFVEC3F( center.x, center.y + f, aZtop ) ); aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZbot ), SFVEC3F( center.x + f, center.y, aZbot ), SFVEC3F( center.x, center.y - f, aZbot ) ); aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZbot ), SFVEC3F( center.x - f, center.y, aZbot ), SFVEC3F( center.x, center.y + f, aZbot ) ); }
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CROUNDSEGMENT2D * aSeg, CLAYER_TRIANGLES *aDstLayer, float aZtop, float aZbot ) { const SFVEC2F leftStart = aSeg->GetLeftStar(); const SFVEC2F leftEnd = aSeg->GetLeftEnd(); const SFVEC2F leftDir = aSeg->GetLeftDir(); const SFVEC2F rightStart = aSeg->GetRightStar(); const SFVEC2F rightEnd = aSeg->GetRightEnd(); const SFVEC2F rightDir = aSeg->GetRightDir(); const float radius = aSeg->GetRadius(); const SFVEC2F start = aSeg->GetStart(); const SFVEC2F end = aSeg->GetEnd(); const float texture_factor = (12.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f; const float texture_factorF= ( 6.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f; const float radius_of_the_square = sqrtf( aSeg->GetRadiusSquared() * 2.0f ); const float radius_triangle_factor = (radius_of_the_square - radius) / radius; const SFVEC2F factorS = SFVEC2F( -rightDir.y * radius * radius_triangle_factor, rightDir.x * radius * radius_triangle_factor ); const SFVEC2F factorE = SFVEC2F( -leftDir.y * radius * radius_triangle_factor, leftDir.x * radius * radius_triangle_factor ); // Top end segment triangles (semi-circles) aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( rightEnd.x + texture_factor * factorS.x, rightEnd.y + texture_factor * factorS.y, aZtop ), SFVEC3F( leftStart.x + texture_factor * factorE.x, leftStart.y + texture_factor * factorE.y, aZtop ), SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ), start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ), aZtop ) ); aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( leftEnd.x + texture_factor * factorE.x, leftEnd.y + texture_factor * factorE.y, aZtop ), SFVEC3F( rightStart.x + texture_factor * factorS.x, rightStart.y + texture_factor * factorS.y, aZtop ), SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ), end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ), aZtop ) ); // Bot end segment triangles (semi-circles) aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( leftStart.x + texture_factor * factorE.x, leftStart.y + texture_factor * factorE.y, aZbot ), SFVEC3F( rightEnd.x + texture_factor * factorS.x, rightEnd.y + texture_factor * factorS.y, aZbot ), SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ), start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ), aZbot ) ); aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( rightStart.x + texture_factor * factorS.x, rightStart.y + texture_factor * factorS.y, aZbot ), SFVEC3F( leftEnd.x + texture_factor * factorE.x, leftEnd.y + texture_factor * factorE.y, aZbot ), SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ), end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ), aZbot ) ); // Segment top and bot planes aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( rightEnd.x, rightEnd.y, aZtop ), SFVEC3F( rightStart.x, rightStart.y, aZtop ), SFVEC3F( leftEnd.x, leftEnd.y, aZtop ), SFVEC3F( leftStart.x, leftStart.y, aZtop ) ); aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( rightEnd.x, rightEnd.y, aZbot ), SFVEC3F( leftStart.x, leftStart.y, aZbot ), SFVEC3F( leftEnd.x, leftEnd.y, aZbot ), SFVEC3F( rightStart.x, rightStart.y, aZbot ) ); }
CINFO3D_VISU::CINFO3D_VISU() : m_currentCamera( m_trackBallCamera ), m_trackBallCamera( RANGE_SCALE_3D ) { wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::CINFO3D_VISU" ) ); m_board = NULL; m_3d_model_manager = NULL; m_3D_grid_type = GRID3D_NONE; m_drawFlags.resize( FL_LAST, false ); m_render_engine = RENDER_ENGINE_OPENGL_LEGACY; m_material_mode = MATERIAL_MODE_NORMAL; m_boardPos = wxPoint(); m_boardSize = wxSize(); m_boardCenter = SFVEC3F(); m_boardBoudingBox.Reset(); m_board2dBBox3DU.Reset(); m_layers_container2D.clear(); m_layers_holes2D.clear(); m_through_holes_inner.Clear(); m_through_holes_outer.Clear(); m_copperLayersCount = -1; m_epoxyThickness3DU = 0.0f; m_copperThickness3DU = 0.0f; m_nonCopperLayerThickness3DU = 0.0f; m_biuTo3Dunits = 1.0; m_stats_nr_tracks = 0; m_stats_nr_vias = 0; m_stats_via_med_hole_diameter = 0.0f; m_stats_nr_holes = 0; m_stats_hole_med_diameter = 0.0f; m_stats_track_med_width = 0.0f; m_calc_seg_min_factor3DU = 0.0f; m_calc_seg_max_factor3DU = 0.0f; memset( m_layerZcoordTop, 0, sizeof( m_layerZcoordTop ) ); memset( m_layerZcoordBottom, 0, sizeof( m_layerZcoordBottom ) ); SetFlag( FL_USE_REALISTIC_MODE, true ); SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, true ); SetFlag( FL_SHOW_BOARD_BODY, true ); SetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS, true ); SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, true ); SetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT, true ); SetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL, true ); SetFlag( FL_ZONE, true ); SetFlag( FL_SILKSCREEN, true ); SetFlag( FL_SOLDERMASK, true ); m_BgColorBot = SFVEC3D( 0.4, 0.4, 0.5 ); m_BgColorTop = SFVEC3D( 0.8, 0.8, 0.9 ); m_BoardBodyColor = SFVEC3D( 0.4, 0.4, 0.5 ); m_SolderMaskColor = SFVEC3D( 0.1, 0.2, 0.1 ); m_SolderPasteColor = SFVEC3D( 0.4, 0.4, 0.4 ); m_SilkScreenColor = SFVEC3D( 0.9, 0.9, 0.9 ); m_CopperColor = SFVEC3D( 0.75, 0.61, 0.23 ); }
void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event ) { wxPaintDC( this ); // SwapBuffer requires the window to be shown before calling if( !IsShownOnScreen() ) { wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint !IsShown" ) ); return; } // "Makes the OpenGL state that is represented by the OpenGL rendering // context context current, i.e. it will be used by all subsequent OpenGL calls. // This function may only be called when the window is shown on screen" GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this ); // Set the OpenGL viewport according to the client size of this canvas. // This is done here rather than in a wxSizeEvent handler because our // OpenGL rendering context (and thus viewport setting) is used with // multiple canvases: If we updated the viewport in the wxSizeEvent // handler, changing the size of one canvas causes a viewport setting that // is wrong when next another canvas is repainted. wxSize clientSize = GetClientSize(); if( !m_ogl_initialized ) { m_ogl_initialized = true; ogl_initialize(); } if( m_reload_is_needed ) { wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint m_reload_is_needed" ) ); m_reload_is_needed = false; m_ogl_3dmodel = new C_OGL_3DMODEL( *m_3d_model ); // It convert a model as it was a board, so get the max size dimension of the board // and compute the conversion scale m_BiuTo3Dunits = (double)RANGE_SCALE_3D / ((double)m_ogl_3dmodel->GetBBox().GetMaxDimension() * UNITS3D_TO_UNITSPCB); } glViewport( 0, 0, clientSize.x, clientSize.y ); m_trackBallCamera.SetCurWindowSize( clientSize ); // clear color and depth buffers // ///////////////////////////////////////////////////////////////////////// glEnable( GL_DEPTH_TEST ); glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); glClearDepth( 1.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Set projection and modelview matrixes // ///////////////////////////////////////////////////////////////////////// glMatrixMode( GL_PROJECTION ); glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetProjectionMatrix() ) ); glMatrixMode( GL_MODELVIEW ); glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetViewMatrix() ) ); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); // Render Model if( m_ogl_3dmodel ) { glPushMatrix(); double modelunit_to_3d_units_factor = m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB; glScaled( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor, modelunit_to_3d_units_factor); // Center model in the render viewport const SFVEC3F model_center = m_ogl_3dmodel->GetBBox().GetCenter(); glTranslatef( -model_center.x, -model_center.y, -model_center.z ); // !TODO: draw transparent models m_ogl_3dmodel->Draw_opaque(); m_ogl_3dmodel->Draw_transparent(); //m_ogl_3dmodel->Draw_bboxes(); glPopMatrix(); } glViewport( 0, 0, clientSize.y / 8 , clientSize.y / 8 ); // YxY squared view port glClear( GL_DEPTH_BUFFER_BIT ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 45.0f, 1.0f, 0.01f, RANGE_SCALE_3D * 2.0f ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); const glm::mat4 TranslationMatrix = glm::translate( glm::mat4(1.0f), SFVEC3F( 0.0f, 0.0f, -RANGE_SCALE_3D ) ); const glm::mat4 ViewMatrix = TranslationMatrix * m_trackBallCamera.GetRotationMatrix(); glLoadMatrixf( glm::value_ptr( ViewMatrix ) ); ogl_set_arrow_material(); glColor3f( 0.9f, 0.0f, 0.0f ); OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ), SFVEC3F( RANGE_SCALE_3D / 2.65f, 0.0f, 0.0f ), 0.275f ); glColor3f( 0.0f, 0.9f, 0.0f ); OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ), SFVEC3F( 0.0f, RANGE_SCALE_3D / 2.65f, 0.0f ), 0.275f ); glColor3f( 0.0f, 0.0f, 0.9f ); OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ), SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 2.65f ), 0.275f ); // "Swaps the double-buffer of this window, making the back-buffer the // front-buffer and vice versa, so that the output of the previous OpenGL // commands is displayed on the window." SwapBuffers(); GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC ); event.Skip(); }
void CLAYER_TRIANGLES::AddToMiddleContourns( const std::vector< SFVEC2F > &aContournPoints, float zBot, float zTop, bool aInvertFaceDirection ) { if( aContournPoints.size() > 4 ) { // Calculate normals of each segment of the contourn std::vector< SFVEC2F > contournNormals; contournNormals.clear(); contournNormals.resize( aContournPoints.size() - 1 ); if( aInvertFaceDirection ) { for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i ) { const SFVEC2F &v0 = aContournPoints[i + 0]; const SFVEC2F &v1 = aContournPoints[i + 1]; const SFVEC2F n = glm::normalize( v1 - v0 ); contournNormals[i] = SFVEC2F( n.y,-n.x ); } } else { for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i ) { const SFVEC2F &v0 = aContournPoints[i + 0]; const SFVEC2F &v1 = aContournPoints[i + 1]; const SFVEC2F n = glm::normalize( v1 - v0 ); contournNormals[i] = SFVEC2F( -n.y, n.x ); } } if( aInvertFaceDirection ) std::swap( zBot, zTop ); const unsigned int nContournsToProcess = ( aContournPoints.size() - 1 ); for( unsigned int i = 0; i < nContournsToProcess; ++i ) { SFVEC2F lastNormal; if( i > 0 ) lastNormal = contournNormals[i - 1]; else lastNormal = contournNormals[nContournsToProcess - 1]; SFVEC2F n0 = contournNormals[i]; // Only interpolate the normal if the angle is closer if( glm::dot( n0, lastNormal ) > 0.5f ) n0 = glm::normalize( n0 + lastNormal ); SFVEC2F nextNormal; if( i < (nContournsToProcess - 1) ) nextNormal = contournNormals[i + 1]; else nextNormal = contournNormals[0]; SFVEC2F n1 = contournNormals[i]; if( glm::dot( n1, nextNormal ) > 0.5f ) n1 = glm::normalize( n1 + nextNormal ); const SFVEC3F n3d0 = SFVEC3F( n0.x, n0.y, 0.0f ); const SFVEC3F n3d1 = SFVEC3F( n1.x, n1.y, 0.0f ); const SFVEC2F &v0 = aContournPoints[i + 0]; const SFVEC2F &v1 = aContournPoints[i + 1]; #pragma omp critical { m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, zTop ), SFVEC3F( v1.x, v1.y, zTop ), SFVEC3F( v1.x, v1.y, zBot ), SFVEC3F( v0.x, v0.y, zBot ) ); m_layer_middle_contourns_quads->AddNormal( n3d0, n3d1, n3d1, n3d0 ); } } } }
bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials, std::vector< SMESH >& meshes ) { SMESH m; S3D::INIT_SMESH( m ); SGAPPEARANCE* pa = m_Appearance; SGFACESET* pf = m_FaceSet; if( NULL == pa ) pa = m_RAppearance; if( NULL == pf ) pf = m_RFaceSet; // no face sets = nothing to render, which is valid though pointless if( NULL == pf ) return true; if( !pf->validate() ) { #ifdef DEBUG std::ostringstream ostr; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << " * [INFO] bad model; inconsistent data"; wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() ); #endif return true; } if( NULL == pa ) { m.m_MaterialIdx = 0; } else { int idx; if( !S3D::GetMatIndex( materials, pa, idx ) ) { m.m_MaterialIdx = 0; } else { m.m_MaterialIdx = idx; } } SGCOLORS* pc = pf->m_Colors; SGCOORDS* pv = pf->m_Coords; SGCOORDINDEX* vidx = pf->m_CoordIndices; SGNORMALS* pn = pf->m_Normals; if( NULL == pc ) pc = pf->m_RColors; if( NULL == pv ) pv = pf->m_RCoords; if( NULL == pn ) pn = pf->m_RNormals; // set the vertex points and indices size_t nCoords = 0; SGPOINT* pCoords = NULL; pv->GetCoordsList( nCoords, pCoords ); size_t nColors = 0; SGCOLOR* pColors = NULL; if( pc ) { // check the vertex colors pc->GetColorList( nColors, pColors ); if( nColors < nCoords ) { #ifdef DEBUG std::ostringstream ostr; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << " * [INFO] bad model; not enough colors per vertex ("; ostr << nColors << " vs " << nCoords << ")"; wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() ); #endif return true; } } // set the vertex indices size_t nvidx = 0; int* lv = NULL; vidx->GetIndices( nvidx, lv ); // note: reduce the vertex set to include only the referenced vertices std::vector< int > vertices; // store the list of temp vertex indices std::map< int, unsigned int > indexmap; // map temp vertex to true vertex std::map< int, unsigned int >::iterator mit; for( unsigned int i = 0; i < nvidx; ++i ) { mit = indexmap.find( lv[i] ); if( mit == indexmap.end() ) { indexmap.insert( std::pair< int, unsigned int >( lv[i], vertices.size() ) ); vertices.push_back( lv[i] ); } } if( vertices.size() < 3 ) { #ifdef DEBUG std::ostringstream ostr; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << " * [INFO] bad model; not enough vertices"; wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() ); #endif return true; } // construct the final vertex/color list SFVEC3F* lColors = NULL; SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ]; int ti; if( pc ) { lColors = new SFVEC3F[vertices.size()]; m.m_Color = lColors; } if( pc ) { for( size_t i = 0; i < vertices.size(); ++i ) { ti = vertices[i]; glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 ); pt = (*aTransform) * pt; pColors[ti].GetColor( lColors[i].x, lColors[i].y, lColors[i].z ); lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z ); } } else { for( size_t i = 0; i < vertices.size(); ++i ) { ti = vertices[i]; glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 ); pt = (*aTransform) * pt; lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z ); } } m.m_VertexSize = (unsigned int) vertices.size(); m.m_Positions = lCoords; unsigned int* lvidx = new unsigned int[ nvidx ]; for( unsigned int i = 0; i < nvidx; ++i ) { mit = indexmap.find( lv[i] ); lvidx[i] = mit->second; } m.m_FaceIdxSize = (unsigned int )nvidx; m.m_FaceIdx = lvidx; // set the per-vertex normals size_t nNorms = 0; SGVECTOR* pNorms = NULL; double x, y, z; pn->GetNormalList( nNorms, pNorms ); SFVEC3F* lNorms = new SFVEC3F[ vertices.size() ]; for( size_t i = 0; i < vertices.size(); ++i ) { ti = vertices[i]; pNorms[ti].GetVector( x, y, z ); glm::dvec4 pt( x, y, z, 0.0 ); pt = (*aTransform) * pt; lNorms[i] = SFVEC3F( pt.x, pt.y, pt.z ); } m.m_Normals = lNorms; meshes.push_back( m ); return true; }