KiCad PCB EDA Suite
RENDER_3D_RAYTRACE Class Reference

#include <render_3d_raytrace.h>

Inheritance diagram for RENDER_3D_RAYTRACE:
RENDER_3D_BASE

Public Member Functions

 RENDER_3D_RAYTRACE (EDA_3D_CANVAS *aCanvas, BOARD_ADAPTER &aAdapter, CAMERA &aCamera)
 
 ~RENDER_3D_RAYTRACE ()
 
void SetCurWindowSize (const wxSize &aSize) override
 Before each render, the canvas will tell the render what is the size of its windows, so render can take actions if it changed. More...
 
bool Redraw (bool aIsMoving, REPORTER *aStatusReporter, REPORTER *aWarningReporter) override
 Redraw the view. More...
 
int GetWaitForEditingTimeOut () override
 Give the interface the time (in ms) that it should wait for editing or movements before (this works for display preview mode). More...
 
void Reload (REPORTER *aStatusReporter, REPORTER *aWarningReporter, bool aOnlyLoadCopperAndShapes)
 
BOARD_ITEMIntersectBoardItem (const RAY &aRay)
 
void ReloadRequest ()
 
bool IsReloadRequestPending () const
 Query if there is a pending reload request. More...
 
void SetBusyIndicatorFactory (BUSY_INDICATOR::FACTORY aNewFactory)
 Set a new busy indicator factory. More...
 

Protected Member Functions

std::unique_ptr< BUSY_INDICATORCreateBusyIndicator () const
 Return a created busy indicator, if a factory has been set, else a null pointer. More...
 

Protected Attributes

EDA_3D_CANVASm_canvas
 Settings reference in use for this render. More...
 
BOARD_ADAPTERm_boardAdapter
 
CAMERAm_camera
 Flag if the opengl specific for this render was already initialized. More...
 
bool m_is_opengl_initialized
 
bool m_reloadRequested
 The window size that this camera is working. More...
 
wxSize m_windowSize
 

Static Protected Attributes

static const wxChar * m_logTrace = wxT( "KI_TRACE_3D_RENDER" )
 Trace mask used to enable or disable the trace output of this class. More...
 

Private Member Functions

bool initializeOpenGL ()
 
void initializeNewWindowSize ()
 
void initPbo ()
 
void deletePbo ()
 
void createItemsFromContainer (const BVH_CONTAINER_2D *aContainer2d, PCB_LAYER_ID aLayer_id, const MATERIAL *aMaterialLayer, const SFVEC3F &aLayerColor, float aLayerZOffset)
 
void restartRenderState ()
 
void renderTracing (GLubyte *ptrPBO, REPORTER *aStatusReporter)
 
void postProcessShading (GLubyte *ptrPBO, REPORTER *aStatusReporter)
 
void postProcessBlurFinish (GLubyte *ptrPBO, REPORTER *aStatusReporter)
 
void renderBlockTracing (GLubyte *ptrPBO, signed int iBlock)
 
void renderFinalColor (GLubyte *ptrPBO, const SFVEC3F &rgbColor, bool applyColorSpaceConversion)
 
void renderRayPackets (const SFVEC3F *bgColorY, const RAY *aRayPkt, HITINFO_PACKET *aHitPacket, bool is_testShadow, SFVEC3F *aOutHitColor)
 
void renderAntiAliasPackets (const SFVEC3F *aBgColorY, const HITINFO_PACKET *aHitPck_X0Y0, const HITINFO_PACKET *aHitPck_AA_X1Y1, const RAY *aRayPck, SFVEC3F *aOutHitColor)
 
void setupMaterials ()
 
SFVEC3F shadeHit (const SFVEC3F &aBgColor, const RAY &aRay, HITINFO &aHitInfo, bool aIsInsideObject, unsigned int aRecursiveLevel, bool is_testShadow) const
 
void createObject (CONTAINER_3D &aDstContainer, const OBJECT_2D *aObject2D, float aZMin, float aZMax, const MATERIAL *aMaterial, const SFVEC3F &aObjColor)
 Create one or more 3D objects form a 2D object and Z positions. More...
 
void addPadsAndVias ()
 
void insertHole (const PCB_VIA *aVia)
 
void insertHole (const PAD *aPad)
 
void load3DModels (CONTAINER_3D &aDstContainer, bool aSkipMaterialInformation)
 
void addModels (CONTAINER_3D &aDstContainer, const S3DMODEL *a3DModel, const glm::mat4 &aModelMatrix, float aFPOpacity, bool aSkipMaterialInformation, BOARD_ITEM *aBoardItem)
 
MODEL_MATERIALSgetModelMaterial (const S3DMODEL *a3DModel)
 
void initializeBlockPositions ()
 
void render (GLubyte *ptrPBO, REPORTER *aStatusReporter)
 
void renderPreview (GLubyte *ptrPBO)
 

Private Attributes

struct {
   BLINN_PHONG_MATERIAL   m_Paste
 
   BLINN_PHONG_MATERIAL   m_SilkS
 
   BLINN_PHONG_MATERIAL   m_SolderMask
 
   BLINN_PHONG_MATERIAL   m_EpoxyBoard
 
   BLINN_PHONG_MATERIAL   m_Copper
 
   BLINN_PHONG_MATERIAL   m_NonPlatedCopper
 
   BLINN_PHONG_MATERIAL   m_Floor
 
m_materials
 
BOARD_NORMAL m_boardMaterial
 
COPPER_NORMAL m_copperMaterial
 
PLATED_COPPER_NORMAL m_platedCopperMaterial
 
SOLDER_MASK_NORMAL m_solderMaskMaterial
 
PLASTIC_NORMAL m_plasticMaterial
 
PLASTIC_SHINE_NORMAL m_shinyPlasticMaterial
 
BRUSHED_METAL_NORMAL m_brushedMetalMaterial
 
SILK_SCREEN_NORMAL m_silkScreenMaterial
 
bool m_isPreview
 
RT_RENDER_STATE m_renderState
 State used on quality render. More...
 
unsigned long int m_renderStartTime
 Time that the render starts. More...
 
size_t m_blockRenderProgressCount
 Save the number of blocks progress of the render. More...
 
POST_SHADER_SSAO m_postShaderSsao
 
std::list< LIGHT * > m_lights
 
DIRECTIONAL_LIGHTm_cameraLight
 
bool m_openglSupportsVertexBufferObjects
 
GLuint m_pboId
 
GLuint m_pboDataSize
 
CONTAINER_3D m_objectContainer
 Store the list of created objects special for RT that will be clear in the end. More...
 
CONTAINER_2D m_containerWithObjectsToDelete
 
CONTAINER_2Dm_outlineBoard2dObjects
 
BVH_CONTAINER_2Dm_antioutlineBoard2dObjects
 
ACCELERATOR_3Dm_accelerator
 
SFVEC3F m_backgroundColorTop
 
SFVEC3F m_backgroundColorBottom
 Used to see if the windows size changed. More...
 
wxSize m_oldWindowsSize
 Encode Morton code positions. More...
 
std::vector< SFVEC2UIm_blockPositions
 Flag if a position was already processed (cleared each new render). More...
 
std::vector< int > m_blockPositionsWasProcessed
 Encode the Morton code positions (on fast preview mode). More...
 
std::vector< SFVEC2UIm_blockPositionsFast
 
SFVEC2UI m_realBufferSize
 
SFVEC2UI m_fastPreviewModeSize
 
HITINFO_PACKETm_firstHitinfo
 
SFVEC3Fm_shaderBuffer
 
unsigned int m_xoffset
 
unsigned int m_yoffset
 
MAP_MODEL_MATERIALS m_modelMaterialMap
 Stores materials of the 3D models. More...
 
unsigned int m_convertedDummyBlockCount
 
unsigned int m_converted2dRoundSegmentCount
 

Detailed Description

Definition at line 55 of file render_3d_raytrace.h.

Constructor & Destructor Documentation

◆ RENDER_3D_RAYTRACE()

RENDER_3D_RAYTRACE::RENDER_3D_RAYTRACE ( EDA_3D_CANVAS aCanvas,
BOARD_ADAPTER aAdapter,
CAMERA aCamera 
)
explicit

Definition at line 43 of file render_3d_raytrace.cpp.

43  :
44  RENDER_3D_BASE( aCanvas, aAdapter, aCamera ),
45  m_postShaderSsao( aCamera )
46 {
47  wxLogTrace( m_logTrace, wxT( "RENDER_3D_RAYTRACE::RENDER_3D_RAYTRACE" ) );
48 
50  m_pboId = GL_NONE;
51  m_pboDataSize = 0;
52  m_accelerator = nullptr;
55  m_oldWindowsSize.x = 0;
56  m_oldWindowsSize.y = 0;
57  m_outlineBoard2dObjects = nullptr;
59  m_firstHitinfo = nullptr;
60  m_shaderBuffer = nullptr;
61  m_cameraLight = nullptr;
62 
63  m_xoffset = 0;
64  m_yoffset = 0;
65 
66  m_isPreview = false;
67  m_renderState = RT_RENDER_STATE_MAX; // Set to an initial invalid state
70 }
unsigned int m_convertedDummyBlockCount
unsigned long int m_renderStartTime
Time that the render starts.
RT_RENDER_STATE m_renderState
State used on quality render.
size_t m_blockRenderProgressCount
Save the number of blocks progress of the render.
unsigned int m_converted2dRoundSegmentCount
RENDER_3D_BASE(EDA_3D_CANVAS *aCanvas, BOARD_ADAPTER &aBoardAdapter, CAMERA &aCamera)
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
POST_SHADER_SSAO m_postShaderSsao
DIRECTIONAL_LIGHT * m_cameraLight
ACCELERATOR_3D * m_accelerator
CONTAINER_2D * m_outlineBoard2dObjects
HITINFO_PACKET * m_firstHitinfo
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects
wxSize m_oldWindowsSize
Encode Morton code positions.

References m_accelerator, m_antioutlineBoard2dObjects, m_blockRenderProgressCount, m_cameraLight, m_converted2dRoundSegmentCount, m_convertedDummyBlockCount, m_firstHitinfo, m_isPreview, RENDER_3D_BASE::m_logTrace, m_oldWindowsSize, m_openglSupportsVertexBufferObjects, m_outlineBoard2dObjects, m_pboDataSize, m_pboId, m_renderStartTime, m_renderState, m_shaderBuffer, m_xoffset, m_yoffset, and RT_RENDER_STATE_MAX.

◆ ~RENDER_3D_RAYTRACE()

RENDER_3D_RAYTRACE::~RENDER_3D_RAYTRACE ( )

Definition at line 73 of file render_3d_raytrace.cpp.

74 {
75  wxLogTrace( m_logTrace, wxT( "RENDER_3D_RAYTRACE::~RENDER_3D_RAYTRACE" ) );
76 
77  delete m_accelerator;
78  m_accelerator = nullptr;
79 
81  m_outlineBoard2dObjects = nullptr;
82 
85 
86  delete[] m_shaderBuffer;
87  m_shaderBuffer = nullptr;
88 
89  deletePbo();
90 }
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
ACCELERATOR_3D * m_accelerator
CONTAINER_2D * m_outlineBoard2dObjects
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects

References deletePbo(), m_accelerator, m_antioutlineBoard2dObjects, RENDER_3D_BASE::m_logTrace, m_outlineBoard2dObjects, and m_shaderBuffer.

Member Function Documentation

◆ addModels()

void RENDER_3D_RAYTRACE::addModels ( CONTAINER_3D aDstContainer,
const S3DMODEL a3DModel,
const glm::mat4 &  aModelMatrix,
float  aFPOpacity,
bool  aSkipMaterialInformation,
BOARD_ITEM aBoardItem 
)
private

Definition at line 1383 of file raytracing/create_scene.cpp.

1386 {
1387  // Validate a3DModel pointers
1388  wxASSERT( a3DModel != nullptr );
1389 
1390  if( a3DModel == nullptr )
1391  return;
1392 
1393  wxASSERT( a3DModel->m_Materials != nullptr );
1394  wxASSERT( a3DModel->m_Meshes != nullptr );
1395  wxASSERT( a3DModel->m_MaterialsSize > 0 );
1396  wxASSERT( a3DModel->m_MeshesSize > 0 );
1397  wxASSERT( aFPOpacity > 0.0f );
1398  wxASSERT( aFPOpacity <= 1.0f );
1399 
1400  if( aFPOpacity > 1.0f )
1401  {
1402  aFPOpacity = 1.0f;
1403  }
1404 
1405  if( ( a3DModel->m_Materials != nullptr ) && ( a3DModel->m_Meshes != nullptr )
1406  && ( a3DModel->m_MaterialsSize > 0 ) && ( a3DModel->m_MeshesSize > 0 ) )
1407  {
1408  MODEL_MATERIALS* materialVector = nullptr;
1409 
1410  if( !aSkipMaterialInformation )
1411  {
1412  materialVector = getModelMaterial( a3DModel );
1413  }
1414 
1415  const glm::mat3 normalMatrix = glm::transpose( glm::inverse( glm::mat3( aModelMatrix ) ) );
1416 
1417  for( unsigned int mesh_i = 0; mesh_i < a3DModel->m_MeshesSize; ++mesh_i )
1418  {
1419  const SMESH& mesh = a3DModel->m_Meshes[mesh_i];
1420 
1421  // Validate the mesh pointers
1422  wxASSERT( mesh.m_Positions != nullptr );
1423  wxASSERT( mesh.m_FaceIdx != nullptr );
1424  wxASSERT( mesh.m_Normals != nullptr );
1425  wxASSERT( mesh.m_FaceIdxSize > 0 );
1426  wxASSERT( ( mesh.m_FaceIdxSize % 3 ) == 0 );
1427 
1428 
1429  if( ( mesh.m_Positions != nullptr ) && ( mesh.m_Normals != nullptr )
1430  && ( mesh.m_FaceIdx != nullptr ) && ( mesh.m_FaceIdxSize > 0 )
1431  && ( mesh.m_VertexSize > 0 ) && ( ( mesh.m_FaceIdxSize % 3 ) == 0 )
1432  && ( mesh.m_MaterialIdx < a3DModel->m_MaterialsSize ) )
1433  {
1434  float fpTransparency;
1435  const BLINN_PHONG_MATERIAL* blinn_material;
1436 
1437  if( !aSkipMaterialInformation )
1438  {
1439  blinn_material = &( *materialVector )[mesh.m_MaterialIdx];
1440 
1441  fpTransparency =
1442  1.0f - ( ( 1.0f - blinn_material->GetTransparency() ) * aFPOpacity );
1443  }
1444 
1445  // Add all face triangles
1446  for( unsigned int faceIdx = 0; faceIdx < mesh.m_FaceIdxSize; faceIdx += 3 )
1447  {
1448  const unsigned int idx0 = mesh.m_FaceIdx[faceIdx + 0];
1449  const unsigned int idx1 = mesh.m_FaceIdx[faceIdx + 1];
1450  const unsigned int idx2 = mesh.m_FaceIdx[faceIdx + 2];
1451 
1452  wxASSERT( idx0 < mesh.m_VertexSize );
1453  wxASSERT( idx1 < mesh.m_VertexSize );
1454  wxASSERT( idx2 < mesh.m_VertexSize );
1455 
1456  if( ( idx0 < mesh.m_VertexSize ) && ( idx1 < mesh.m_VertexSize )
1457  && ( idx2 < mesh.m_VertexSize ) )
1458  {
1459  const SFVEC3F& v0 = mesh.m_Positions[idx0];
1460  const SFVEC3F& v1 = mesh.m_Positions[idx1];
1461  const SFVEC3F& v2 = mesh.m_Positions[idx2];
1462 
1463  const SFVEC3F& n0 = mesh.m_Normals[idx0];
1464  const SFVEC3F& n1 = mesh.m_Normals[idx1];
1465  const SFVEC3F& n2 = mesh.m_Normals[idx2];
1466 
1467  // Transform vertex with the model matrix
1468  const SFVEC3F vt0 = SFVEC3F( aModelMatrix * glm::vec4( v0, 1.0f ) );
1469  const SFVEC3F vt1 = SFVEC3F( aModelMatrix * glm::vec4( v1, 1.0f ) );
1470  const SFVEC3F vt2 = SFVEC3F( aModelMatrix * glm::vec4( v2, 1.0f ) );
1471 
1472  const SFVEC3F nt0 = glm::normalize( SFVEC3F( normalMatrix * n0 ) );
1473  const SFVEC3F nt1 = glm::normalize( SFVEC3F( normalMatrix * n1 ) );
1474  const SFVEC3F nt2 = glm::normalize( SFVEC3F( normalMatrix * n2 ) );
1475 
1476  TRIANGLE* newTriangle = new TRIANGLE( vt0, vt2, vt1, nt0, nt2, nt1 );
1477 
1478  newTriangle->SetBoardItem( aBoardItem );
1479 
1480  aDstContainer.Add( newTriangle );
1481 
1482  if( !aSkipMaterialInformation )
1483  {
1484  newTriangle->SetMaterial( blinn_material );
1485  newTriangle->SetModelTransparency( fpTransparency );
1486 
1487  if( mesh.m_Color == nullptr )
1488  {
1489  const SFVEC3F diffuseColor =
1490  a3DModel->m_Materials[mesh.m_MaterialIdx].m_Diffuse;
1491 
1493  newTriangle->SetColor( ConvertSRGBToLinear(
1494  MaterialDiffuseToColorCAD( diffuseColor ) ) );
1495  else
1496  newTriangle->SetColor( ConvertSRGBToLinear( diffuseColor ) );
1497  }
1498  else
1499  {
1501  newTriangle->SetColor(
1503  mesh.m_Color[idx0] ) ),
1505  mesh.m_Color[idx1] ) ),
1507  mesh.m_Color[idx2] ) ) );
1508  else
1509  newTriangle->SetColor(
1510  ConvertSRGBToLinear( mesh.m_Color[idx0] ),
1511  ConvertSRGBToLinear( mesh.m_Color[idx1] ),
1512  ConvertSRGBToLinear( mesh.m_Color[idx2] ) );
1513  }
1514  }
1515  }
1516  }
1517  }
1518  }
1519  }
1520 }
Use a gray shading based on diffuse material.
SFVEC3F * m_Normals
Vertex normals array.
Definition: c3dmodel.h:80
float GetTransparency() const
Definition: material.h:273
BOARD_ADAPTER & m_boardAdapter
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
void SetModelTransparency(float aModelTransparency)
Definition: object_3d.h:66
MODEL_MATERIALS * getModelMaterial(const S3DMODEL *a3DModel)
std::vector< BLINN_PHONG_MATERIAL > MODEL_MATERIALS
Vector of materials.
Blinn Phong based material https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model.
Definition: material.h:378
SFVEC3F * m_Positions
Vertex position array.
Definition: c3dmodel.h:79
Per-vertex normal/color/texcoors structure.
Definition: c3dmodel.h:76
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:93
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
Definition: c3dmodel.h:83
void SetColor(const SFVEC3F &aColor)
unsigned int m_VertexSize
Number of vertex in the arrays.
Definition: c3dmodel.h:78
void SetMaterial(const MATERIAL *aMaterial)
Definition: object_3d.h:58
const void SetBoardItem(BOARD_ITEM *aBoardItem)
Definition: object_3d.h:55
MATERIAL_MODE GetMaterialMode() const noexcept
SFVEC3F * m_Color
Vertex color array, can be NULL.
Definition: c3dmodel.h:82
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:95
A triangle object.
Definition: triangle_3d.h:42
SFVEC3F MaterialDiffuseToColorCAD(const SFVEC3F &aDiffuseColor)
Definition: 3d_math.h:147
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
Definition: c3dmodel.h:85
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:96
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Definition: c3dmodel.h:40
void Add(OBJECT_3D *aObject)
Definition: container_3d.h:48
unsigned int * m_FaceIdx
Triangle Face Indexes.
Definition: c3dmodel.h:84
unsigned int m_MeshesSize
Number of meshes in the array.
Definition: c3dmodel.h:92
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)

References CONTAINER_3D_BASE::Add(), CAD_MODE, ConvertSRGBToLinear(), BOARD_ADAPTER::GetMaterialMode(), getModelMaterial(), MATERIAL::GetTransparency(), RENDER_3D_BASE::m_boardAdapter, SMESH::m_Color, SMATERIAL::m_Diffuse, SMESH::m_FaceIdx, SMESH::m_FaceIdxSize, SMESH::m_MaterialIdx, S3DMODEL::m_Materials, S3DMODEL::m_MaterialsSize, S3DMODEL::m_Meshes, S3DMODEL::m_MeshesSize, SMESH::m_Normals, SMESH::m_Positions, SMESH::m_VertexSize, MaterialDiffuseToColorCAD(), OBJECT_3D::SetBoardItem(), TRIANGLE::SetColor(), OBJECT_3D::SetMaterial(), OBJECT_3D::SetModelTransparency(), TRIANGLE, and v2.

Referenced by load3DModels().

◆ addPadsAndVias()

void RENDER_3D_RAYTRACE::addPadsAndVias ( )
private

Definition at line 1151 of file raytracing/create_scene.cpp.

1152 {
1153  if( !m_boardAdapter.GetBoard() )
1154  return;
1155 
1156  // Insert plated vertical holes inside the board
1157 
1158  // Insert vias holes (vertical cylinders)
1159  for( PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
1160  {
1161  if( track->Type() == PCB_VIA_T )
1162  {
1163  const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
1164  insertHole( via );
1165  }
1166  }
1167 
1168  // Insert pads holes (vertical cylinders)
1169  for( FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
1170  {
1171  for( PAD* pad : footprint->Pads() )
1172  {
1173  if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
1174  insertHole( pad );
1175  }
1176  }
1177 }
BOARD_ADAPTER & m_boardAdapter
like PAD_PTH, but not plated
FOOTPRINTS & Footprints()
Definition: board.h:233
const BOARD * GetBoard() const noexcept
Get current board to be rendered.
void insertHole(const PCB_VIA *aVia)
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
Definition: pad.h:57
TRACKS & Tracks()
Definition: board.h:230

References BOARD::Footprints(), BOARD_ADAPTER::GetBoard(), insertHole(), RENDER_3D_BASE::m_boardAdapter, NPTH, pad, PCB_VIA_T, BOARD::Tracks(), and via.

Referenced by Reload().

◆ CreateBusyIndicator()

std::unique_ptr< BUSY_INDICATOR > RENDER_3D_BASE::CreateBusyIndicator ( ) const
protectedinherited

Return a created busy indicator, if a factory has been set, else a null pointer.

the canvas to disply the scene

Definition at line 70 of file render_3d_base.cpp.

71 {
72  std::unique_ptr<BUSY_INDICATOR> busy;
73 
75  busy = m_busyIndicatorFactory();
76 
77  return busy;
78 }
BUSY_INDICATOR::FACTORY m_busyIndicatorFactory
< Factory that returns a suitable busy indicator for the context.

References RENDER_3D_BASE::m_busyIndicatorFactory.

Referenced by RENDER_3D_OPENGL::Redraw(), and Redraw().

◆ createItemsFromContainer()

void RENDER_3D_RAYTRACE::createItemsFromContainer ( const BVH_CONTAINER_2D aContainer2d,
PCB_LAYER_ID  aLayer_id,
const MATERIAL aMaterialLayer,
const SFVEC3F aLayerColor,
float  aLayerZOffset 
)
private

Definition at line 233 of file raytracing/create_scene.cpp.

238 {
239  if( aContainer2d == nullptr )
240  return;
241 
242  const LIST_OBJECT2D& listObject2d = aContainer2d->GetList();
243 
244  if( listObject2d.size() == 0 )
245  return;
246 
247  for( const OBJECT_2D* object2d_A : listObject2d )
248  {
249  // not yet used / implemented (can be used in future to clip the objects in the
250  // board borders
251  OBJECT_2D* object2d_C = CSGITEM_FULL;
252 
253  std::vector<const OBJECT_2D*>* object2d_B = CSGITEM_EMPTY;
254 
255  object2d_B = new std::vector<const OBJECT_2D*>();
256 
257  // Subtract holes but not in SolderPaste
258  // (can be added as an option in future)
259  if( !( aLayer_id == B_Paste || aLayer_id == F_Paste ) )
260  {
261  // Check if there are any layerhole that intersects this object
262  // Eg: a segment is cut by a via hole or THT hole.
263  const MAP_CONTAINER_2D_BASE& layerHolesMap = m_boardAdapter.GetLayerHoleMap();
264 
265  if( layerHolesMap.find( aLayer_id ) != layerHolesMap.end() )
266  {
267  const BVH_CONTAINER_2D* holes2d = layerHolesMap.at( aLayer_id );
268 
269  CONST_LIST_OBJECT2D intersecting;
270 
271  holes2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
272 
273  for( const OBJECT_2D* hole2d : intersecting )
274  object2d_B->push_back( hole2d );
275  }
276 
277  // Check if there are any THT that intersects this object. If we're processing a silk
278  // layer and the flag is set, then clip the silk at the outer edge of the annular ring,
279  // rather than the at the outer edge of the copper plating.
280  const BVH_CONTAINER_2D& throughHoleOuter =
283  && ( ( aLayer_id == B_SilkS ) || ( aLayer_id == F_SilkS ) ) ) ?
286 
287  if( !throughHoleOuter.GetList().empty() )
288  {
289  CONST_LIST_OBJECT2D intersecting;
290 
291  throughHoleOuter.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
292 
293  for( const OBJECT_2D* hole2d : intersecting )
294  object2d_B->push_back( hole2d );
295  }
296  }
297 
298  if( !m_antioutlineBoard2dObjects->GetList().empty() )
299  {
300  CONST_LIST_OBJECT2D intersecting;
301 
302  m_antioutlineBoard2dObjects->GetIntersectingObjects( object2d_A->GetBBox(),
303  intersecting );
304 
305  for( const OBJECT_2D* obj : intersecting )
306  object2d_B->push_back( obj );
307  }
308 
309  const MAP_CONTAINER_2D_BASE& mapLayers = m_boardAdapter.GetLayerMap();
310 
313  && ( ( aLayer_id == B_SilkS && mapLayers.find( B_Mask ) != mapLayers.end() )
314  || ( aLayer_id == F_SilkS && mapLayers.find( F_Mask ) != mapLayers.end() ) ) )
315  {
316  const PCB_LAYER_ID layerMask_id = ( aLayer_id == B_SilkS ) ? B_Mask : F_Mask;
317 
318  const BVH_CONTAINER_2D* containerMaskLayer2d = mapLayers.at( layerMask_id );
319 
320  CONST_LIST_OBJECT2D intersecting;
321 
322  if( containerMaskLayer2d ) // can be null if B_Mask or F_Mask is not shown
323  containerMaskLayer2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
324 
325  for( const OBJECT_2D* obj2d : intersecting )
326  object2d_B->push_back( obj2d );
327  }
328 
329  if( object2d_B->empty() )
330  {
331  delete object2d_B;
332  object2d_B = CSGITEM_EMPTY;
333  }
334 
335  if( ( object2d_B == CSGITEM_EMPTY ) && ( object2d_C == CSGITEM_FULL ) )
336  {
337  LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A,
338  m_boardAdapter.GetLayerBottomZPos( aLayer_id ) - aLayerZOffset,
339  m_boardAdapter.GetLayerTopZPos( aLayer_id ) + aLayerZOffset );
340  objPtr->SetMaterial( aMaterialLayer );
341  objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) );
342  m_objectContainer.Add( objPtr );
343  }
344  else
345  {
346  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B, object2d_C,
347  object2d_A->GetBoardItem() );
348  m_containerWithObjectsToDelete.Add( itemCSG2d );
349 
350  LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d,
351  m_boardAdapter.GetLayerBottomZPos( aLayer_id ) - aLayerZOffset,
352  m_boardAdapter.GetLayerTopZPos( aLayer_id ) + aLayerZOffset );
353 
354  objPtr->SetMaterial( aMaterialLayer );
355  objPtr->SetColor( ConvertSRGBToLinear( aLayerColor ) );
356 
357  m_objectContainer.Add( objPtr );
358  }
359  }
360 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
std::list< const OBJECT_2D * > CONST_LIST_OBJECT2D
Definition: container_2d.h:39
const BVH_CONTAINER_2D & GetThroughHoleAnnularRings() const noexcept
Get the through hole annular rings container.
const MAP_CONTAINER_2D_BASE & GetLayerMap() const noexcept
Get the map of containers that have the objects per layer.
#define CSGITEM_FULL
Definition: layer_item_2d.h:39
CONTAINER_2D m_containerWithObjectsToDelete
const LIST_OBJECT2D & GetList() const
Definition: container_2d.h:66
void Add(OBJECT_2D *aObject)
Definition: container_2d.h:49
void SetMaterial(const MATERIAL *aMaterial)
Definition: object_3d.h:58
#define CSGITEM_EMPTY
Definition: layer_item_2d.h:38
float GetLayerTopZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the top z position.
float GetLayerBottomZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the bottom z position.
const BVH_CONTAINER_2D & GetThroughHoleOds() const noexcept
Get the inflated through hole outside diameters container.
std::map< PCB_LAYER_ID, BVH_CONTAINER_2D * > MAP_CONTAINER_2D_BASE
A type that stores a container of 2d objects for each layer id.
Definition: board_adapter.h:51
void GetIntersectingObjects(const BBOX_2D &aBBox, CONST_LIST_OBJECT2D &aOutList) const override
Get a list of objects that intersects a bounding box.
Make solid geometry for objects on layers.
Definition: layer_item_2d.h:79
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
void SetColor(SFVEC3F aObjColor)
Definition: layer_item_3d.h:37
std::list< OBJECT_2D * > LIST_OBJECT2D
Definition: container_2d.h:36
void Add(OBJECT_3D *aObject)
Definition: container_3d.h:48
const MAP_CONTAINER_2D_BASE & GetLayerHoleMap() const noexcept
Get the map of container that have the holes per layer.
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects
CONTAINER_3D m_objectContainer
Store the list of created objects special for RT that will be clear in the end.

References CONTAINER_3D_BASE::Add(), CONTAINER_2D_BASE::Add(), B_Mask, B_Paste, B_SilkS, ConvertSRGBToLinear(), CSGITEM_EMPTY, CSGITEM_FULL, F_Mask, F_Paste, F_SilkS, FL_CLIP_SILK_ON_VIA_ANNULUS, FL_SUBTRACT_MASK_FROM_SILK, FL_USE_REALISTIC_MODE, OBJECT_2D::GetBoardItem(), BOARD_ADAPTER::GetFlag(), BVH_CONTAINER_2D::GetIntersectingObjects(), BOARD_ADAPTER::GetLayerBottomZPos(), BOARD_ADAPTER::GetLayerHoleMap(), BOARD_ADAPTER::GetLayerMap(), BOARD_ADAPTER::GetLayerTopZPos(), CONTAINER_2D_BASE::GetList(), BOARD_ADAPTER::GetThroughHoleAnnularRings(), BOARD_ADAPTER::GetThroughHoleOds(), m_antioutlineBoard2dObjects, RENDER_3D_BASE::m_boardAdapter, m_containerWithObjectsToDelete, m_objectContainer, LAYER_ITEM::SetColor(), and OBJECT_3D::SetMaterial().

Referenced by Reload().

◆ createObject()

void RENDER_3D_RAYTRACE::createObject ( CONTAINER_3D aDstContainer,
const OBJECT_2D aObject2D,
float  aZMin,
float  aZMax,
const MATERIAL aMaterial,
const SFVEC3F aObjColor 
)
private

Create one or more 3D objects form a 2D object and Z positions.

It tries to optimize some types of objects that will be faster to trace than the LAYER_ITEM object.

Definition at line 182 of file raytracing/create_scene.cpp.

185 {
186  switch( aObject2D->GetObjectType() )
187  {
189  {
191 
192  XY_PLANE* objPtr;
193  objPtr = new XY_PLANE( BBOX_3D(
194  SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMin ),
195  SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMin ) ) );
196  objPtr->SetMaterial( aMaterial );
197  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
198  aDstContainer.Add( objPtr );
199 
200  objPtr = new XY_PLANE( BBOX_3D(
201  SFVEC3F( aObject2D->GetBBox().Min().x, aObject2D->GetBBox().Min().y, aZMax ),
202  SFVEC3F( aObject2D->GetBBox().Max().x, aObject2D->GetBBox().Max().y, aZMax ) ) );
203  objPtr->SetMaterial( aMaterial );
204  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
205  aDstContainer.Add( objPtr );
206  break;
207  }
208 
210  {
212 
213  const ROUND_SEGMENT_2D* aRoundSeg2D = static_cast<const ROUND_SEGMENT_2D*>( aObject2D );
214  ROUND_SEGMENT* objPtr = new ROUND_SEGMENT( *aRoundSeg2D, aZMin, aZMax );
215  objPtr->SetMaterial( aMaterial );
216  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
217  aDstContainer.Add( objPtr );
218  break;
219  }
220 
221  default:
222  {
223  LAYER_ITEM* objPtr = new LAYER_ITEM( aObject2D, aZMin, aZMax );
224  objPtr->SetMaterial( aMaterial );
225  objPtr->SetColor( ConvertSRGBToLinear( aObjColor ) );
226  aDstContainer.Add( objPtr );
227  break;
228  }
229  }
230 }
void SetColor(SFVEC3F aObjColor)
Definition: plane_3d.h:49
unsigned int m_convertedDummyBlockCount
Manage a bounding box defined by two SFVEC3F min max points.
Definition: bbox_3d.h:41
const SFVEC2F & Max() const
Definition: bbox_2d.h:172
unsigned int m_converted2dRoundSegmentCount
void SetMaterial(const MATERIAL *aMaterial)
Definition: object_3d.h:58
const BBOX_2D & GetBBox() const
Definition: object_2d.h:103
OBJECT_2D_TYPE GetObjectType() const
Definition: object_2d.h:107
const SFVEC2F & Min() const
Definition: bbox_2d.h:167
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
void SetColor(SFVEC3F aObjColor)
Definition: layer_item_3d.h:37
void SetColor(SFVEC3F aObjColor)
A plane that is parallel to XY plane.
Definition: plane_3d.h:37
void Add(OBJECT_3D *aObject)
Definition: container_3d.h:48
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)

References CONTAINER_3D_BASE::Add(), ConvertSRGBToLinear(), DUMMYBLOCK, OBJECT_2D::GetBBox(), OBJECT_2D::GetObjectType(), m_converted2dRoundSegmentCount, m_convertedDummyBlockCount, BBOX_2D::Max(), BBOX_2D::Min(), ROUNDSEG, LAYER_ITEM::SetColor(), ROUND_SEGMENT::SetColor(), XY_PLANE::SetColor(), and OBJECT_3D::SetMaterial().

Referenced by Reload().

◆ deletePbo()

void RENDER_3D_RAYTRACE::deletePbo ( )
private

Definition at line 99 of file render_3d_raytrace.cpp.

100 {
101  // Delete PBO if it was created
103  {
104  if( glIsBufferARB( m_pboId ) )
105  glDeleteBuffers( 1, &m_pboId );
106 
107  m_pboId = GL_NONE;
108  }
109 }

References m_openglSupportsVertexBufferObjects, and m_pboId.

Referenced by initPbo(), and ~RENDER_3D_RAYTRACE().

◆ getModelMaterial()

MODEL_MATERIALS * RENDER_3D_RAYTRACE::getModelMaterial ( const S3DMODEL a3DModel)
private

Definition at line 1280 of file raytracing/create_scene.cpp.

1281 {
1282  MODEL_MATERIALS* materialVector;
1283 
1284  // Try find if the materials already exists in the map list
1285  if( m_modelMaterialMap.find( a3DModel ) != m_modelMaterialMap.end() )
1286  {
1287  // Found it, so get the pointer
1288  materialVector = &m_modelMaterialMap[a3DModel];
1289  }
1290  else
1291  {
1292  // Materials was not found in the map, so it will create a new for
1293  // this model.
1294 
1295  m_modelMaterialMap[a3DModel] = MODEL_MATERIALS();
1296  materialVector = &m_modelMaterialMap[a3DModel];
1297 
1298  materialVector->resize( a3DModel->m_MaterialsSize );
1299 
1300  for( unsigned int imat = 0; imat < a3DModel->m_MaterialsSize; ++imat )
1301  {
1303  {
1304  const SMATERIAL& material = a3DModel->m_Materials[imat];
1305 
1306  // http://www.fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtaW4oc3FydCh4LTAuMzUpKjAuNDAtMC4wNSwxLjApIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMC4wNzA3NzM2NzMyMzY1OTAxMiIsIjEuNTY5NTcxNjI5MjI1NDY5OCIsIi0wLjI3NDYzNTMyMTc1OTkyOTMiLCIwLjY0NzcwMTg4MTkyNTUzNjIiXSwic2l6ZSI6WzY0NCwzOTRdfV0-
1307 
1308  float reflectionFactor = 0.0f;
1309 
1310  if( ( material.m_Shininess - 0.35f ) > FLT_EPSILON )
1311  {
1312  reflectionFactor = glm::clamp(
1313  glm::sqrt( ( material.m_Shininess - 0.35f ) ) * 0.40f - 0.05f, 0.0f,
1314  0.5f );
1315  }
1316 
1317  BLINN_PHONG_MATERIAL& blinnMaterial = ( *materialVector )[imat];
1318 
1319  blinnMaterial = BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( material.m_Ambient ),
1320  ConvertSRGBToLinear( material.m_Emissive ),
1321  ConvertSRGBToLinear( material.m_Specular ), material.m_Shininess * 180.0f,
1322  material.m_Transparency, reflectionFactor );
1323 
1325  {
1326  // Guess material type and apply a normal perturbator
1327  if( ( RGBtoGray( material.m_Diffuse ) < 0.3f )
1328  && ( material.m_Shininess < 0.36f )
1329  && ( material.m_Transparency == 0.0f )
1330  && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) < 0.15f )
1331  && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1332  < 0.15f )
1333  && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1334  < 0.15f ) ) )
1335  {
1336  // This may be a black plastic..
1337  blinnMaterial.SetGenerator( &m_plasticMaterial );
1338  }
1339  else
1340  {
1341  if( ( RGBtoGray( material.m_Diffuse ) > 0.3f )
1342  && ( material.m_Shininess < 0.30f )
1343  && ( material.m_Transparency == 0.0f )
1344  && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g ) > 0.25f )
1345  || ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g ) > 0.25f )
1346  || ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1347  > 0.25f ) ) )
1348  {
1349  // This may be a color plastic ...
1350  blinnMaterial.SetGenerator( &m_shinyPlasticMaterial );
1351  }
1352  else
1353  {
1354  if( ( RGBtoGray( material.m_Diffuse ) > 0.6f )
1355  && ( material.m_Shininess > 0.35f )
1356  && ( material.m_Transparency == 0.0f )
1357  && ( ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.g )
1358  < 0.40f )
1359  && ( glm::abs( material.m_Diffuse.b - material.m_Diffuse.g )
1360  < 0.40f )
1361  && ( glm::abs( material.m_Diffuse.r - material.m_Diffuse.b )
1362  < 0.40f ) ) )
1363  {
1364  // This may be a brushed metal
1365  blinnMaterial.SetGenerator( &m_brushedMetalMaterial );
1366  }
1367  }
1368  }
1369  }
1370  }
1371  else
1372  {
1373  ( *materialVector )[imat] = BLINN_PHONG_MATERIAL(
1374  SFVEC3F( 0.2f ), SFVEC3F( 0.0f ), SFVEC3F( 0.0f ), 0.0f, 0.0f, 0.0f );
1375  }
1376  }
1377  }
1378 
1379  return materialVector;
1380 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
float RGBtoGray(const SFVEC3F &aColor)
Definition: 3d_math.h:140
SFVEC3F m_Ambient
Definition: c3dmodel.h:39
MAP_MODEL_MATERIALS m_modelMaterialMap
Stores materials of the 3D models.
void SetGenerator(const MATERIAL_GENERATOR *aGenerator)
Definition: material.h:328
std::vector< BLINN_PHONG_MATERIAL > MODEL_MATERIALS
Vector of materials.
float m_Transparency
1.0 is completely transparent, 0.0 completely opaque
Definition: c3dmodel.h:44
Blinn Phong based material https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model.
Definition: material.h:378
Use all material properties from model file.
MATERIAL_MODE GetMaterialMode() const noexcept
float m_Shininess
Definition: c3dmodel.h:43
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:95
BRUSHED_METAL_NORMAL m_brushedMetalMaterial
PLASTIC_SHINE_NORMAL m_shinyPlasticMaterial
SFVEC3F m_Emissive
Definition: c3dmodel.h:41
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:96
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Definition: c3dmodel.h:40
PLASTIC_NORMAL m_plasticMaterial
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
SFVEC3F m_Specular
Definition: c3dmodel.h:42

References ConvertSRGBToLinear(), FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES, BOARD_ADAPTER::GetFlag(), BOARD_ADAPTER::GetMaterialMode(), SMATERIAL::m_Ambient, RENDER_3D_BASE::m_boardAdapter, m_brushedMetalMaterial, SMATERIAL::m_Diffuse, SMATERIAL::m_Emissive, S3DMODEL::m_Materials, S3DMODEL::m_MaterialsSize, m_modelMaterialMap, m_plasticMaterial, SMATERIAL::m_Shininess, m_shinyPlasticMaterial, SMATERIAL::m_Specular, SMATERIAL::m_Transparency, NORMAL, RGBtoGray(), and MATERIAL::SetGenerator().

Referenced by addModels().

◆ GetWaitForEditingTimeOut()

int RENDER_3D_RAYTRACE::GetWaitForEditingTimeOut ( )
overridevirtual

Give the interface the time (in ms) that it should wait for editing or movements before (this works for display preview mode).

Returns
a value in milliseconds

Implements RENDER_3D_BASE.

Definition at line 93 of file render_3d_raytrace.cpp.

94 {
95  return 1000; // ms
96 }

◆ initializeBlockPositions()

void RENDER_3D_RAYTRACE::initializeBlockPositions ( )
private

Definition at line 1858 of file render_3d_raytrace.cpp.

1859 {
1860  m_realBufferSize = SFVEC2UI( 0 );
1861 
1862  // Calc block positions for fast preview mode
1863  m_blockPositionsFast.clear();
1864 
1865  unsigned int i = 0;
1866 
1867  while(1)
1868  {
1869  const unsigned int mX = DecodeMorton2X(i);
1870  const unsigned int mY = DecodeMorton2Y(i);
1871 
1872  i++;
1873 
1874  const SFVEC2UI blockPos( mX * 4 * RAYPACKET_DIM - mX * 4,
1875  mY * 4 * RAYPACKET_DIM - mY * 4 );
1876 
1877  if( ( blockPos.x >= ( (unsigned int)m_windowSize.x - ( 4 * RAYPACKET_DIM + 4 ) ) ) &&
1878  ( blockPos.y >= ( (unsigned int)m_windowSize.y - ( 4 * RAYPACKET_DIM + 4 ) ) ) )
1879  break;
1880 
1881  if( ( blockPos.x < ( (unsigned int)m_windowSize.x - ( 4 * RAYPACKET_DIM + 4 ) ) ) &&
1882  ( blockPos.y < ( (unsigned int)m_windowSize.y - ( 4 * RAYPACKET_DIM + 4 ) ) ) )
1883  {
1884  m_blockPositionsFast.push_back( blockPos );
1885 
1886  if( blockPos.x > m_realBufferSize.x )
1887  m_realBufferSize.x = blockPos.x;
1888 
1889  if( blockPos.y > m_realBufferSize.y )
1890  m_realBufferSize.y = blockPos.y;
1891  }
1892  }
1893 
1895 
1898 
1899  m_xoffset = ( m_windowSize.x - m_realBufferSize.x ) / 2;
1900  m_yoffset = ( m_windowSize.y - m_realBufferSize.y ) / 2;
1901 
1903 
1904  // Calc block positions for regular rendering. Choose an 'inside out' style of rendering.
1905  m_blockPositions.clear();
1906  const int blocks_x = m_realBufferSize.x / RAYPACKET_DIM;
1907  const int blocks_y = m_realBufferSize.y / RAYPACKET_DIM;
1908  m_blockPositions.reserve( blocks_x * blocks_y );
1909 
1910  for( int x = 0; x < blocks_x; ++x )
1911  {
1912  for( int y = 0; y < blocks_y; ++y )
1913  m_blockPositions.emplace_back( x * RAYPACKET_DIM, y * RAYPACKET_DIM );
1914  }
1915 
1916  const SFVEC2UI center( m_realBufferSize.x / 2, m_realBufferSize.y / 2 );
1917  std::sort( m_blockPositions.begin(), m_blockPositions.end(),
1918  [&]( const SFVEC2UI& a, const SFVEC2UI& b ) {
1919  // Sort order: inside out.
1920  return distance( a, center ) < distance( b, center );
1921  } );
1922 
1923  // Create m_shader buffer
1924  delete[] m_shaderBuffer;
1926 
1927  initPbo();
1928 }
#define RAYPACKET_DIM
Definition: raypacket.h:32
uint32_t DecodeMorton2X(uint32_t code)
Definition: mortoncodes.cpp:98
#define RAYPACKET_INVMASK
Definition: raypacket.h:34
std::vector< SFVEC2UI > m_blockPositions
Flag if a position was already processed (cleared each new render).
uint32_t DecodeMorton2Y(uint32_t code)
std::vector< SFVEC2UI > m_blockPositionsFast
glm::uvec2 SFVEC2UI
Definition: xv3d_types.h:38
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
POST_SHADER_SSAO m_postShaderSsao
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
void UpdateSize(const SFVEC2UI &aSize)
Definition: post_shader.cpp:73

References DecodeMorton2X(), DecodeMorton2Y(), distance(), initPbo(), m_blockPositions, m_blockPositionsFast, m_fastPreviewModeSize, m_postShaderSsao, m_realBufferSize, m_shaderBuffer, RENDER_3D_BASE::m_windowSize, m_xoffset, m_yoffset, RAYPACKET_DIM, RAYPACKET_INVMASK, and POST_SHADER::UpdateSize().

Referenced by Redraw().

◆ initializeNewWindowSize()

void RENDER_3D_RAYTRACE::initializeNewWindowSize ( )
private

Definition at line 1807 of file render_3d_raytrace.cpp.

1808 {
1809  initPbo();
1810 }

References initPbo().

Referenced by SetCurWindowSize().

◆ initializeOpenGL()

bool RENDER_3D_RAYTRACE::initializeOpenGL ( )
private

Definition at line 1842 of file render_3d_raytrace.cpp.

1843 {
1844  m_is_opengl_initialized = true;
1845 
1846  return true;
1847 }
bool m_is_opengl_initialized

References RENDER_3D_BASE::m_is_opengl_initialized.

Referenced by Redraw().

◆ initPbo()

void RENDER_3D_RAYTRACE::initPbo ( )
private

Definition at line 1813 of file render_3d_raytrace.cpp.

1814 {
1815  if( GLEW_ARB_pixel_buffer_object )
1816  {
1818 
1819  // Try to delete vbo if it was already initialized
1820  deletePbo();
1821 
1822  // Learn about Pixel buffer objects at:
1823  // http://www.songho.ca/opengl/gl_pbo.html
1824  // http://web.eecs.umich.edu/~sugih/courses/eecs487/lectures/25-PBO+Mipmapping.pdf
1825  // "create 2 pixel buffer objects, you need to delete them when program exits.
1826  // glBufferDataARB with NULL pointer reserves only memory space."
1827 
1828  // This sets the number of RGBA pixels
1830 
1831  glGenBuffersARB( 1, &m_pboId );
1832  glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, m_pboId );
1833  glBufferDataARB( GL_PIXEL_UNPACK_BUFFER_ARB, m_pboDataSize, 0, GL_STREAM_DRAW_ARB );
1834  glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, 0 );
1835 
1836  wxLogTrace( m_logTrace,
1837  wxT( "RENDER_3D_RAYTRACE:: GLEW_ARB_pixel_buffer_object is supported" ) );
1838  }
1839 }
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.

References deletePbo(), RENDER_3D_BASE::m_logTrace, m_openglSupportsVertexBufferObjects, m_pboDataSize, m_pboId, and m_realBufferSize.

Referenced by initializeBlockPositions(), and initializeNewWindowSize().

◆ insertHole() [1/2]

void RENDER_3D_RAYTRACE::insertHole ( const PCB_VIA aVia)
private

Definition at line 934 of file raytracing/create_scene.cpp.

935 {
936  PCB_LAYER_ID top_layer, bottom_layer;
937  int radiusBUI = ( aVia->GetDrillValue() / 2 );
938 
939  aVia->LayerPair( &top_layer, &bottom_layer );
940 
941  float topZ = m_boardAdapter.GetLayerBottomZPos( top_layer )
943 
944  float botZ = m_boardAdapter.GetLayerBottomZPos( bottom_layer )
946 
947  const SFVEC2F center = SFVEC2F( aVia->GetStart().x * m_boardAdapter.BiuTo3dUnits(),
948  -aVia->GetStart().y * m_boardAdapter.BiuTo3dUnits() );
949 
950  RING_2D* ring = new RING_2D( center, radiusBUI * m_boardAdapter.BiuTo3dUnits(),
951  ( radiusBUI + m_boardAdapter.GetHolePlatingThickness() )
952  * m_boardAdapter.BiuTo3dUnits(), *aVia );
953 
955 
956  LAYER_ITEM* objPtr = new LAYER_ITEM( ring, topZ, botZ );
957 
958  objPtr->SetMaterial( &m_materials.m_Copper );
959 
962  else if( aVia->GetViaType() == VIATYPE::MICROVIA )
964  else if( aVia->GetViaType() == VIATYPE::BLIND_BURIED )
966  else
968 
969  m_objectContainer.Add( objPtr );
970 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
to draw micro vias
Definition: layer_ids.h:190
VIATYPE GetViaType() const
Definition: pcb_track.h:354
CONTAINER_2D m_containerWithObjectsToDelete
void Add(OBJECT_2D *aObject)
Definition: container_2d.h:49
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
void SetMaterial(const MATERIAL *aMaterial)
Definition: object_3d.h:58
Meta control for all vias opacity/visibility.
Definition: layer_ids.h:189
float GetLayerBottomZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the bottom z position.
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
Definition: pcb_track.cpp:461
SFVEC4F GetItemColor(int aItemId) const
Get the technical color of a layer.
to draw blind/buried vias
Definition: layer_ids.h:191
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
void SetColor(SFVEC3F aObjColor)
Definition: layer_item_3d.h:37
SFVEC4F m_CopperColor
in realistic mode: copper color
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: pcb_track.cpp:193
float GetCopperThickness() const noexcept
Get the current copper layer thickness.
void Add(OBJECT_3D *aObject)
Definition: container_3d.h:48
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
struct RENDER_3D_RAYTRACE::@5 m_materials
const wxPoint & GetStart() const
Definition: pcb_track.h:108
CONTAINER_3D m_objectContainer
Store the list of created objects special for RT that will be clear in the end.
int GetHolePlatingThickness() const noexcept
Get the current copper layer thickness.

References CONTAINER_3D_BASE::Add(), CONTAINER_2D_BASE::Add(), BOARD_ADAPTER::BiuTo3dUnits(), BLIND_BURIED, ConvertSRGBToLinear(), FL_USE_REALISTIC_MODE, BOARD_ADAPTER::GetCopperThickness(), PCB_VIA::GetDrillValue(), BOARD_ADAPTER::GetFlag(), BOARD_ADAPTER::GetHolePlatingThickness(), BOARD_ADAPTER::GetItemColor(), BOARD_ADAPTER::GetLayerBottomZPos(), PCB_TRACK::GetStart(), PCB_VIA::GetViaType(), LAYER_VIA_BBLIND, LAYER_VIA_MICROVIA, LAYER_VIAS, PCB_VIA::LayerPair(), RENDER_3D_BASE::m_boardAdapter, m_containerWithObjectsToDelete, BOARD_ADAPTER::m_CopperColor, m_materials, m_objectContainer, MICROVIA, LAYER_ITEM::SetColor(), and OBJECT_3D::SetMaterial().

Referenced by addPadsAndVias().

◆ insertHole() [2/2]

void RENDER_3D_RAYTRACE::insertHole ( const PAD aPad)
private

Definition at line 973 of file raytracing/create_scene.cpp.

974 {
975  const OBJECT_2D* object2d_A = nullptr;
976 
977  SFVEC3F objColor;
978 
980  objColor = m_boardAdapter.m_CopperColor;
981  else
983 
984  const wxSize drillsize = aPad->GetDrillSize();
985  const bool hasHole = drillsize.x && drillsize.y;
986 
987  if( !hasHole )
988  return;
989 
990  CONST_LIST_OBJECT2D antiOutlineIntersectionList;
991 
992  const float topZ = m_boardAdapter.GetLayerBottomZPos( F_Cu )
994 
995  const float botZ = m_boardAdapter.GetLayerBottomZPos( B_Cu )
997 
998  if( drillsize.x == drillsize.y ) // usual round hole
999  {
1000  SFVEC2F center = SFVEC2F( aPad->GetPosition().x * m_boardAdapter.BiuTo3dUnits(),
1001  -aPad->GetPosition().y * m_boardAdapter.BiuTo3dUnits() );
1002 
1003  int innerRadius = drillsize.x / 2;
1004  int outerRadius = innerRadius + m_boardAdapter.GetHolePlatingThickness();
1005 
1006  RING_2D* ring = new RING_2D( center, innerRadius * m_boardAdapter.BiuTo3dUnits(),
1007  outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1008 
1010 
1011  object2d_A = ring;
1012 
1013  // If the object (ring) is intersected by an antioutline board,
1014  // it will use instead a CSG of two circles.
1015  if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1016  {
1018  antiOutlineIntersectionList );
1019  }
1020 
1021  if( !antiOutlineIntersectionList.empty() )
1022  {
1023  FILLED_CIRCLE_2D* innerCircle = new FILLED_CIRCLE_2D(
1024  center, innerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1025 
1026  FILLED_CIRCLE_2D* outterCircle = new FILLED_CIRCLE_2D(
1027  center, outerRadius * m_boardAdapter.BiuTo3dUnits(), *aPad );
1028  std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1029  object2d_B->push_back( innerCircle );
1030 
1031  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outterCircle, object2d_B, CSGITEM_FULL,
1032  *aPad );
1033 
1034  m_containerWithObjectsToDelete.Add( itemCSG2d );
1035  m_containerWithObjectsToDelete.Add( innerCircle );
1036  m_containerWithObjectsToDelete.Add( outterCircle );
1037 
1038  object2d_A = itemCSG2d;
1039  }
1040  }
1041  else // Oblong hole
1042  {
1043  wxPoint ends_offset;
1044  int width;
1045 
1046  if( drillsize.x > drillsize.y ) // Horizontal oval
1047  {
1048  ends_offset.x = ( drillsize.x - drillsize.y ) / 2;
1049  width = drillsize.y;
1050  }
1051  else // Vertical oval
1052  {
1053  ends_offset.y = ( drillsize.y - drillsize.x ) / 2;
1054  width = drillsize.x;
1055  }
1056 
1057  RotatePoint( &ends_offset, aPad->GetOrientation() );
1058 
1059  wxPoint start = aPad->GetPosition() + ends_offset;
1060  wxPoint end = aPad->GetPosition() - ends_offset;
1061 
1062  ROUND_SEGMENT_2D* innerSeg =
1064  -start.y * m_boardAdapter.BiuTo3dUnits() ),
1065  SFVEC2F( end.x * m_boardAdapter.BiuTo3dUnits(),
1066  -end.y * m_boardAdapter.BiuTo3dUnits() ),
1067  width * m_boardAdapter.BiuTo3dUnits(), *aPad );
1068 
1069  ROUND_SEGMENT_2D* outerSeg =
1071  -start.y * m_boardAdapter.BiuTo3dUnits() ),
1072  SFVEC2F( end.x * m_boardAdapter.BiuTo3dUnits(),
1073  -end.y * m_boardAdapter.BiuTo3dUnits() ),
1074  ( width + m_boardAdapter.GetHolePlatingThickness() * 2 )
1075  * m_boardAdapter.BiuTo3dUnits(), *aPad );
1076 
1077  // NOTE: the round segment width is the "diameter", so we double the thickness
1078  std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1079  object2d_B->push_back( innerSeg );
1080 
1081  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( outerSeg, object2d_B, CSGITEM_FULL, *aPad );
1082 
1083  m_containerWithObjectsToDelete.Add( itemCSG2d );
1084  m_containerWithObjectsToDelete.Add( innerSeg );
1085  m_containerWithObjectsToDelete.Add( outerSeg );
1086 
1087  object2d_A = itemCSG2d;
1088 
1089  if( object2d_A && !m_antioutlineBoard2dObjects->GetList().empty() )
1090  {
1092  antiOutlineIntersectionList );
1093  }
1094  }
1095 
1096  if( object2d_A )
1097  {
1098  std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
1099 
1100  // Check if there are any other THT that intersects this hole
1101  // It will use the non inflated holes
1102  if( !m_boardAdapter.GetThroughHoleIds().GetList().empty() )
1103  {
1104  CONST_LIST_OBJECT2D intersecting;
1105 
1107  intersecting );
1108 
1109  for( const OBJECT_2D* hole2d : intersecting )
1110  {
1111  if( object2d_A->Intersects( hole2d->GetBBox() ) )
1112  object2d_B->push_back( hole2d );
1113  }
1114  }
1115 
1116  for( const OBJECT_2D* obj : antiOutlineIntersectionList )
1117  object2d_B->push_back( obj );
1118 
1119  if( object2d_B->empty() )
1120  {
1121  delete object2d_B;
1122  object2d_B = CSGITEM_EMPTY;
1123  }
1124 
1125  if( object2d_B == CSGITEM_EMPTY )
1126  {
1127  LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, topZ, botZ );
1128 
1129  objPtr->SetMaterial( &m_materials.m_Copper );
1130  objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1131  m_objectContainer.Add( objPtr );
1132  }
1133  else
1134  {
1135  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B, CSGITEM_FULL,
1136  *aPad );
1137 
1138  m_containerWithObjectsToDelete.Add( itemCSG2d );
1139 
1140  LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, topZ, botZ );
1141 
1142  objPtr->SetMaterial( &m_materials.m_Copper );
1143  objPtr->SetColor( ConvertSRGBToLinear( objColor ) );
1144 
1145  m_objectContainer.Add( objPtr );
1146  }
1147  }
1148 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
std::list< const OBJECT_2D * > CONST_LIST_OBJECT2D
Definition: container_2d.h:39
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
#define CSGITEM_FULL
Definition: layer_item_2d.h:39
CONTAINER_2D m_containerWithObjectsToDelete
const LIST_OBJECT2D & GetList() const
Definition: container_2d.h:66
const BVH_CONTAINER_2D & GetThroughHoleIds() const noexcept
Get the through hole inner diameter container.
void Add(OBJECT_2D *aObject)
Definition: container_2d.h:49
const wxSize & GetDrillSize() const
Definition: pad.h:243
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
double GetOrientation() const
Return the rotation angle of the pad in a variety of units (the basic call returns tenths of degrees)...
Definition: pad.h:349
void SetMaterial(const MATERIAL *aMaterial)
Definition: object_3d.h:58
#define CSGITEM_EMPTY
Definition: layer_item_2d.h:38
const BBOX_2D & GetBBox() const
Definition: object_2d.h:103
float GetLayerBottomZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the bottom z position.
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
SFVEC4F GetItemColor(int aItemId) const
Get the technical color of a layer.
void GetIntersectingObjects(const BBOX_2D &aBBox, CONST_LIST_OBJECT2D &aOutList) const override
Get a list of objects that intersects a bounding box.
multilayer pads, usually with holes
Definition: layer_ids.h:209
Make solid geometry for objects on layers.
Definition: layer_item_2d.h:79
wxPoint GetPosition() const override
Definition: pad.h:178
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
void SetColor(SFVEC3F aObjColor)
Definition: layer_item_3d.h:37
SFVEC4F m_CopperColor
in realistic mode: copper color
Definition: layer_ids.h:71
float GetCopperThickness() const noexcept
Get the current copper layer thickness.
void Add(OBJECT_3D *aObject)
Definition: container_3d.h:48
virtual bool Intersects(const BBOX_2D &aBBox) const =0
a.Intersects(b) ⇔ !a.Disjoint(b) ⇔ !(a ∩ b = ∅)
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
struct RENDER_3D_RAYTRACE::@5 m_materials
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects
CONTAINER_3D m_objectContainer
Store the list of created objects special for RT that will be clear in the end.
int GetHolePlatingThickness() const noexcept
Get the current copper layer thickness.

References CONTAINER_3D_BASE::Add(), CONTAINER_2D_BASE::Add(), B_Cu, BOARD_ADAPTER::BiuTo3dUnits(), ConvertSRGBToLinear(), CSGITEM_EMPTY, CSGITEM_FULL, F_Cu, FL_USE_REALISTIC_MODE, OBJECT_2D::GetBBox(), BOARD_ADAPTER::GetCopperThickness(), PAD::GetDrillSize(), BOARD_ADAPTER::GetFlag(), BOARD_ADAPTER::GetHolePlatingThickness(), BVH_CONTAINER_2D::GetIntersectingObjects(), BOARD_ADAPTER::GetItemColor(), BOARD_ADAPTER::GetLayerBottomZPos(), CONTAINER_2D_BASE::GetList(), PAD::GetOrientation(), PAD::GetPosition(), BOARD_ADAPTER::GetThroughHoleIds(), OBJECT_2D::Intersects(), LAYER_PADS_TH, m_antioutlineBoard2dObjects, RENDER_3D_BASE::m_boardAdapter, m_containerWithObjectsToDelete, BOARD_ADAPTER::m_CopperColor, m_materials, m_objectContainer, RotatePoint(), LAYER_ITEM::SetColor(), and OBJECT_3D::SetMaterial().

◆ IntersectBoardItem()

BOARD_ITEM * RENDER_3D_RAYTRACE::IntersectBoardItem ( const RAY aRay)

Definition at line 1931 of file render_3d_raytrace.cpp.

1932 {
1933  HITINFO hitInfo;
1934  hitInfo.m_tHit = std::numeric_limits<float>::infinity();
1935 
1936  if( m_accelerator )
1937  {
1938  if( m_accelerator->Intersect( aRay, hitInfo ) )
1939  {
1940  if( hitInfo.pHitObject )
1941  return hitInfo.pHitObject->GetBoardItem();
1942  }
1943  }
1944 
1945  return nullptr;
1946 }
BOARD_ITEM * GetBoardItem() const
Definition: object_3d.h:56
float m_tHit
( 4) distance
Definition: hitinfo.h:38
const OBJECT_3D * pHitObject
( 4) Object that was hitted
Definition: hitinfo.h:40
Stores the hit information of a ray with a point on the surface of a object.
Definition: hitinfo.h:35
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
ACCELERATOR_3D * m_accelerator

References OBJECT_3D::GetBoardItem(), ACCELERATOR_3D::Intersect(), m_accelerator, HITINFO::m_tHit, and HITINFO::pHitObject.

Referenced by EDA_3D_CANVAS::OnLeftDown(), and EDA_3D_CANVAS::OnMouseMove().

◆ IsReloadRequestPending()

bool RENDER_3D_BASE::IsReloadRequestPending ( ) const
inlineinherited

Query if there is a pending reload request.

Returns
true if it wants to reload, false if there is no reload pending

Definition at line 77 of file render_3d_base.h.

77 { return m_reloadRequested; }
bool m_reloadRequested
The window size that this camera is working.

References RENDER_3D_BASE::m_reloadRequested.

Referenced by EDA_3D_CANVAS::DoRePaint(), and EDA_3D_CANVAS::IsReloadRequestPending().

◆ load3DModels()

void RENDER_3D_RAYTRACE::load3DModels ( CONTAINER_3D aDstContainer,
bool  aSkipMaterialInformation 
)
private

Definition at line 1180 of file raytracing/create_scene.cpp.

1181 {
1182  if( !m_boardAdapter.GetBoard() )
1183  return;
1184 
1188  {
1189  return;
1190  }
1191 
1192  // Go for all footprints
1193  for( FOOTPRINT* fp : m_boardAdapter.GetBoard()->Footprints() )
1194  {
1195  if( !fp->Models().empty()
1196  && m_boardAdapter.IsFootprintShown( (FOOTPRINT_ATTR_T) fp->GetAttributes() ) )
1197  {
1198  double zpos = m_boardAdapter.GetFootprintZPos( fp->IsFlipped() );
1199 
1200  wxPoint pos = fp->GetPosition();
1201 
1202  glm::mat4 fpMatrix = glm::mat4( 1.0f );
1203 
1204  fpMatrix = glm::translate( fpMatrix,
1205  SFVEC3F( pos.x * m_boardAdapter.BiuTo3dUnits(),
1206  -pos.y * m_boardAdapter.BiuTo3dUnits(),
1207  zpos ) );
1208 
1209  if( fp->GetOrientation() )
1210  {
1211  fpMatrix = glm::rotate( fpMatrix,
1212  ( (float) ( fp->GetOrientation() / 10.0f ) / 180.0f ) * glm::pi<float>(),
1213  SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1214  }
1215 
1216  if( fp->IsFlipped() )
1217  {
1218  fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1219 
1220  fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1221  }
1222 
1223  const double modelunit_to_3d_units_factor =
1225 
1226  fpMatrix = glm::scale(
1227  fpMatrix, SFVEC3F( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
1228  modelunit_to_3d_units_factor ) );
1229 
1230  BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( fp );
1231 
1232  // Get the list of model files for this model
1234  auto sM = fp->Models().begin();
1235  auto eM = fp->Models().end();
1236 
1237  while( sM != eM )
1238  {
1239  if( ( static_cast<float>( sM->m_Opacity ) > FLT_EPSILON )
1240  && ( sM->m_Show && !sM->m_Filename.empty() ) )
1241  {
1242  // get it from cache
1243  const S3DMODEL* modelPtr = cacheMgr->GetModel( sM->m_Filename );
1244 
1245  // only add it if the return is not NULL.
1246  if( modelPtr )
1247  {
1248  glm::mat4 modelMatrix = fpMatrix;
1249 
1250  modelMatrix = glm::translate( modelMatrix,
1251  SFVEC3F( sM->m_Offset.x, sM->m_Offset.y, sM->m_Offset.z ) );
1252 
1253  modelMatrix = glm::rotate( modelMatrix,
1254  (float) -( sM->m_Rotation.z / 180.0f ) * glm::pi<float>(),
1255  SFVEC3F( 0.0f, 0.0f, 1.0f ) );
1256 
1257  modelMatrix = glm::rotate( modelMatrix,
1258  (float) -( sM->m_Rotation.y / 180.0f ) * glm::pi<float>(),
1259  SFVEC3F( 0.0f, 1.0f, 0.0f ) );
1260 
1261  modelMatrix = glm::rotate( modelMatrix,
1262  (float) -( sM->m_Rotation.x / 180.0f ) * glm::pi<float>(),
1263  SFVEC3F( 1.0f, 0.0f, 0.0f ) );
1264 
1265  modelMatrix = glm::scale( modelMatrix,
1266  SFVEC3F( sM->m_Scale.x, sM->m_Scale.y, sM->m_Scale.z ) );
1267 
1268  addModels( aDstContainer, modelPtr, modelMatrix, (float) sM->m_Opacity,
1269  aSkipMaterialInformation, boardItem );
1270  }
1271  }
1272 
1273  ++sM;
1274  }
1275  }
1276  }
1277 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
bool IsFootprintShown(FOOTPRINT_ATTR_T aFPAttributes) const
Test if footprint should be displayed in relation to attributes and the flags.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
#define UNITS3D_TO_UNITSPCB
Scale conversion from 3d model units to pcb units.
Cache for storing the 3D shapes.
Definition: 3d_cache.h:52
FOOTPRINT_ATTR_T
The set of attributes allowed within a FOOTPRINT, using FOOTPRINT::SetAttributes() and FOOTPRINT::Get...
Definition: footprint.h:66
S3DMODEL * GetModel(const wxString &aModelFileName)
Attempt to load the scene data for a model and to translate it into an S3D_MODEL structure for displa...
Definition: 3d_cache.cpp:643
void addModels(CONTAINER_3D &aDstContainer, const S3DMODEL *a3DModel, const glm::mat4 &aModelMatrix, float aFPOpacity, bool aSkipMaterialInformation, BOARD_ITEM *aBoardItem)
S3D_CACHE * Get3dCacheManager() const noexcept
Return the 3D cache manager pointer.
Definition: board_adapter.h:88
FOOTPRINTS & Footprints()
Definition: board.h:233
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
const BOARD * GetBoard() const noexcept
Get current board to be rendered.
float GetFootprintZPos(bool aIsFlipped) const
Get the position of the footprint in 3d integer units considering if it is flipped or not.
const int scale
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
Store the a model based on meshes and materials.
Definition: c3dmodel.h:90

References addModels(), BOARD_ADAPTER::BiuTo3dUnits(), FL_FP_ATTRIBUTES_NORMAL, FL_FP_ATTRIBUTES_NORMAL_INSERT, FL_FP_ATTRIBUTES_VIRTUAL, BOARD::Footprints(), BOARD_ADAPTER::Get3dCacheManager(), BOARD_ADAPTER::GetBoard(), BOARD_ADAPTER::GetFlag(), BOARD_ADAPTER::GetFootprintZPos(), S3D_CACHE::GetModel(), BOARD_ADAPTER::IsFootprintShown(), RENDER_3D_BASE::m_boardAdapter, scale, and UNITS3D_TO_UNITSPCB.

Referenced by Reload().

◆ postProcessBlurFinish()

void RENDER_3D_RAYTRACE::postProcessBlurFinish ( GLubyte *  ptrPBO,
REPORTER aStatusReporter 
)
private

Definition at line 891 of file render_3d_raytrace.cpp.

892 {
894  {
895  // Now blurs the shader result and compute the final color
896  std::atomic<size_t> nextBlock( 0 );
897  std::atomic<size_t> threadsFinished( 0 );
898 
899  size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
900 
901  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
902  {
903  std::thread t = std::thread( [&]()
904  {
905  for( size_t y = nextBlock.fetch_add( 1 ); y < m_realBufferSize.y;
906  y = nextBlock.fetch_add( 1 ) )
907  {
908  GLubyte* ptr = &ptrPBO[ y * m_realBufferSize.x * 4 ];
909 
910  for( signed int x = 0; x < (int)m_realBufferSize.x; ++x )
911  {
912  const SFVEC3F bluredShadeColor = m_postShaderSsao.Blur( SFVEC2I( x, y ) );
913 
914 #ifdef USE_SRGB_SPACE
915  const SFVEC3F originColor = convertLinearToSRGB(
917 #else
918  const SFVEC3F originColor =
920 #endif
921  const SFVEC3F shadedColor = m_postShaderSsao.ApplyShadeColor(
922  SFVEC2I( x, y ), originColor, bluredShadeColor );
923 
924  renderFinalColor( ptr, shadedColor, false );
925 
926  ptr += 4;
927  }
928  }
929 
930  threadsFinished++;
931  } );
932 
933  t.detach();
934  }
935 
936  while( threadsFinished < parallelThreadCount )
937  std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
938 
939  // Debug code
940  //m_postShaderSsao.DebugBuffersOutputAsImages();
941  }
942 
943  // End rendering
945 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
SFVEC3F ApplyShadeColor(const SFVEC2I &aShaderPos, const SFVEC3F &aInputColor, const SFVEC3F &aShadeColor) const override
Apply the final color process using a previous stage color.
RT_RENDER_STATE m_renderState
State used on quality render.
glm::ivec2 SFVEC2I
Definition: xv3d_types.h:39
const SFVEC3F & GetColorAtNotProtected(const SFVEC2I &aPos) const
void renderFinalColor(GLubyte *ptrPBO, const SFVEC3F &rgbColor, bool applyColorSpaceConversion)
POST_SHADER_SSAO m_postShaderSsao
static SFVEC3F convertLinearToSRGB(const SFVEC3F &aRGBcolor)
SFVEC3F Blur(const SFVEC2I &aShaderPos) const
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44

References POST_SHADER_SSAO::ApplyShadeColor(), POST_SHADER_SSAO::Blur(), convertLinearToSRGB(), FL_RENDER_RAYTRACING_POST_PROCESSING, POST_SHADER::GetColorAtNotProtected(), BOARD_ADAPTER::GetFlag(), RENDER_3D_BASE::m_boardAdapter, m_postShaderSsao, m_realBufferSize, m_renderState, renderFinalColor(), and RT_RENDER_STATE_FINISH.

Referenced by render().

◆ postProcessShading()

void RENDER_3D_RAYTRACE::postProcessShading ( GLubyte *  ptrPBO,
REPORTER aStatusReporter 
)
private

Definition at line 838 of file render_3d_raytrace.cpp.

839 {
841  {
842  if( aStatusReporter )
843  aStatusReporter->Report( _( "Rendering: Post processing shader" ) );
844 
847 
848  std::atomic<size_t> nextBlock( 0 );
849  std::atomic<size_t> threadsFinished( 0 );
850 
851  size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
852 
853  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
854  {
855  std::thread t = std::thread( [&]()
856  {
857  for( size_t y = nextBlock.fetch_add( 1 ); y < m_realBufferSize.y;
858  y = nextBlock.fetch_add( 1 ) )
859  {
860  SFVEC3F* ptr = &m_shaderBuffer[ y * m_realBufferSize.x ];
861 
862  for( signed int x = 0; x < (int)m_realBufferSize.x; ++x )
863  {
864  *ptr = m_postShaderSsao.Shade( SFVEC2I( x, y ) );
865  ptr++;
866  }
867  }
868 
869  threadsFinished++;
870  } );
871 
872  t.detach();
873  }
874 
875  while( threadsFinished < parallelThreadCount )
876  std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
877 
879 
880  // Set next state
882  }
883  else
884  {
885  // As this was an invalid state, set to finish
887  }
888 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
void SetShadowsEnabled(bool aIsShadowsEnabled)
void SetShadedBuffer(SFVEC3F *aShadedBuffer)
RT_RENDER_STATE m_renderState
State used on quality render.
glm::ivec2 SFVEC2I
Definition: xv3d_types.h:39
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
SFVEC3F Shade(const SFVEC2I &aShaderPos) const override
#define _(s)
POST_SHADER_SSAO m_postShaderSsao
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44

References _, FL_RENDER_RAYTRACING_POST_PROCESSING, FL_RENDER_RAYTRACING_SHADOWS, BOARD_ADAPTER::GetFlag(), RENDER_3D_BASE::m_boardAdapter, m_postShaderSsao, m_realBufferSize, m_renderState, m_shaderBuffer, REPORTER::Report(), RT_RENDER_STATE_FINISH, RT_RENDER_STATE_POST_PROCESS_BLUR_AND_FINISH, POST_SHADER_SSAO::SetShadedBuffer(), POST_SHADER_SSAO::SetShadowsEnabled(), and POST_SHADER_SSAO::Shade().

Referenced by render().

◆ Redraw()

bool RENDER_3D_RAYTRACE::Redraw ( bool  aIsMoving,
REPORTER aStatusReporter,
REPORTER aWarningReporter 
)
overridevirtual

Redraw the view.

Parameters
aIsMovingif the user is moving the scene, it should be render in preview mode.
aStatusReportera pointer to the status progress reporter.
Returns
true if the render would like to redraw again.

Implements RENDER_3D_BASE.

Definition at line 149 of file render_3d_raytrace.cpp.

151 {
152  bool requestRedraw = false;
153 
154  // Initialize openGL if need
156  {
157  if( !initializeOpenGL() )
158  return false;
159 
160  //aIsMoving = true;
161  requestRedraw = true;
162 
163  // It will assign the first time the windows size, so it will now
164  // revert to preview mode the first time the Redraw is called
167  }
168 
169  std::unique_ptr<BUSY_INDICATOR> busy = CreateBusyIndicator();
170 
171  // Reload board if it was requested
172  if( m_reloadRequested )
173  {
174  if( aStatusReporter )
175  aStatusReporter->Report( _( "Loading..." ) );
176 
177  //aIsMoving = true;
178  requestRedraw = true;
179  Reload( aStatusReporter, aWarningReporter, false );
180  }
181 
182 
183  // Recalculate constants if windows size was changed
185  {
187  aIsMoving = true;
188  requestRedraw = true;
189 
191  }
192 
193 
194  // Clear buffers
195  glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
196  glClearDepth( 1.0f );
197  glClearStencil( 0x00 );
198  glClear( GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
199 
200  // 4-byte pixel alignment
201  glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
202 
203  glDisable( GL_STENCIL_TEST );
204  glDisable( GL_LIGHTING );
205  glDisable( GL_COLOR_MATERIAL );
206  glDisable( GL_DEPTH_TEST );
207  glDisable( GL_TEXTURE_2D );
208  glDisable( GL_BLEND );
209  glDisable( GL_MULTISAMPLE );
210 
211  const bool was_camera_changed = m_camera.ParametersChanged();
212 
213  if( requestRedraw || aIsMoving || was_camera_changed )
214  m_renderState = RT_RENDER_STATE_MAX; // Set to an invalid state,
215  // so it will restart again latter
216 
217  // This will only render if need, otherwise it will redraw the PBO on the screen again
218  if( aIsMoving || was_camera_changed )
219  {
220  // Set head light (camera view light) with the opposite direction of the camera
221  if( m_cameraLight )
223 
226 
227  // Bind PBO
228  glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, m_pboId );
229 
230  // Get the PBO pixel pointer to write the data
231  GLubyte* ptrPBO = (GLubyte *)glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB,
232  GL_WRITE_ONLY_ARB );
233 
234  if( ptrPBO )
235  {
236  renderPreview( ptrPBO );
237 
238  // release pointer to mapping buffer, this initialize the coping to PBO
239  glUnmapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB );
240  }
241 
242  glWindowPos2i( m_xoffset, m_yoffset );
243  }
244  else
245  {
246  // Bind PBO
247  glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, m_pboId );
248 
250  {
251  // Get the PBO pixel pointer to write the data
252  GLubyte* ptrPBO = (GLubyte *)glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB,
253  GL_WRITE_ONLY_ARB );
254 
255  if( ptrPBO )
256  {
257  render( ptrPBO, aStatusReporter );
258 
260  requestRedraw = true;
261 
262  // release pointer to mapping buffer, this initialize the coping to PBO
263  glUnmapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB );
264  }
265  }
266 
268  {
269  glClear( GL_COLOR_BUFFER_BIT );
270  }
271 
272  glWindowPos2i( m_xoffset, m_yoffset );
273  }
274 
275  // This way it will blend the progress rendering with the last buffer. eg:
276  // if it was called after a openGL.
277  glEnable( GL_BLEND );
278  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
279  glEnable( GL_ALPHA_TEST );
280  glDrawPixels( m_realBufferSize.x, m_realBufferSize.y, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
281  glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, 0 );
282 
283  return requestRedraw;
284 }
BOARD_ADAPTER & m_boardAdapter
RT_RENDER_STATE m_renderState
State used on quality render.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
void renderPreview(GLubyte *ptrPBO)
SFVEC4F m_BgColorTop
background top color
void Reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter, bool aOnlyLoadCopperAndShapes)
#define _(s)
SFVEC4F m_BgColorBot
background bottom color
bool m_is_opengl_initialized
std::unique_ptr< BUSY_INDICATOR > CreateBusyIndicator() const
Return a created busy indicator, if a factory has been set, else a null pointer.
bool m_reloadRequested
The window size that this camera is working.
DIRECTIONAL_LIGHT * m_cameraLight
const SFVEC3F & GetDir() const
Definition: camera.h:108
void OglDrawBackground(const SFVEC3F &aTopColor, const SFVEC3F &aBotColor)
Definition: ogl_utils.cpp:160
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
CAMERA & m_camera
Flag if the opengl specific for this render was already initialized.
void SetDirection(const SFVEC3F &aDir)
Set directional light orientation.
Definition: light.h:131
bool ParametersChanged()
Definition: camera.cpp:582
void render(GLubyte *ptrPBO, REPORTER *aStatusReporter)
wxSize m_oldWindowsSize
Encode Morton code positions.

References _, RENDER_3D_BASE::CreateBusyIndicator(), CAMERA::GetDir(), initializeBlockPositions(), initializeOpenGL(), BOARD_ADAPTER::m_BgColorBot, BOARD_ADAPTER::m_BgColorTop, RENDER_3D_BASE::m_boardAdapter, RENDER_3D_BASE::m_camera, m_cameraLight, RENDER_3D_BASE::m_is_opengl_initialized, m_oldWindowsSize, m_pboId, m_realBufferSize, RENDER_3D_BASE::m_reloadRequested, m_renderState, RENDER_3D_BASE::m_windowSize, m_xoffset, m_yoffset, OglDrawBackground(), CAMERA::ParametersChanged(), Reload(), render(), renderPreview(), REPORTER::Report(), RT_RENDER_STATE_FINISH, RT_RENDER_STATE_MAX, and DIRECTIONAL_LIGHT::SetDirection().

◆ Reload()

void RENDER_3D_RAYTRACE::Reload ( REPORTER aStatusReporter,
REPORTER aWarningReporter,
bool  aOnlyLoadCopperAndShapes 
)

Definition at line 366 of file raytracing/create_scene.cpp.

368 {
369  m_reloadRequested = false;
370 
371  m_modelMaterialMap.clear();
372 
375 
376  unsigned stats_startReloadTime = GetRunningMicroSecs();
377 
378  if( !aOnlyLoadCopperAndShapes )
379  {
380  m_boardAdapter.InitSettings( aStatusReporter, aWarningReporter );
381 
382  SFVEC3F camera_pos = m_boardAdapter.GetBoardCenter();
383  m_camera.SetBoardLookAtPos( camera_pos );
384  }
385 
388 
389  setupMaterials();
390 
391  if( aStatusReporter )
392  aStatusReporter->Report( _( "Load Raytracing: board" ) );
393 
394  // Create and add the outline board
397 
400 
401  if( !aOnlyLoadCopperAndShapes )
402  {
403  const int outlineCount = m_boardAdapter.GetBoardPoly().OutlineCount();
404 
405  if( outlineCount > 0 )
406  {
407  float divFactor = 0.0f;
408 
410  divFactor = m_boardAdapter.GetAverageViaHoleDiameter() * 18.0f;
411  else if( m_boardAdapter.GetHoleCount() )
412  divFactor = m_boardAdapter.GetAverageHoleDiameter() * 8.0f;
413 
414  SHAPE_POLY_SET boardPolyCopy = m_boardAdapter.GetBoardPoly();
415 
416  // Calculate an antiboard outline
417  SHAPE_POLY_SET antiboardPoly;
418 
420 
421  antiboardPoly.BooleanSubtract( boardPolyCopy, SHAPE_POLY_SET::PM_FAST );
422  antiboardPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
423 
424  for( int ii = 0; ii < antiboardPoly.OutlineCount(); ii++ )
425  {
427  m_boardAdapter.BiuTo3dUnits(), -1.0f,
428  *m_boardAdapter.GetBoard(), ii );
429  }
430 
432 
433  boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
434 
435  for( int ii = 0; ii < outlineCount; ii++ )
436  {
438  m_boardAdapter.BiuTo3dUnits(), divFactor,
439  *m_boardAdapter.GetBoard(), ii );
440  }
441 
443  {
444  const LIST_OBJECT2D& listObjects = m_outlineBoard2dObjects->GetList();
445 
446  for( const OBJECT_2D* object2d_A : listObjects )
447  {
448  std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
449 
450  // Check if there are any THT that intersects this outline object part
451  if( !m_boardAdapter.GetThroughHoleOds().GetList().empty() )
452  {
453  const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetThroughHoleOds();
454  CONST_LIST_OBJECT2D intersecting;
455 
456  throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
457 
458  for( const OBJECT_2D* hole : intersecting )
459  {
460  if( object2d_A->Intersects( hole->GetBBox() ) )
461  object2d_B->push_back( hole );
462  }
463  }
464 
465  if( !m_antioutlineBoard2dObjects->GetList().empty() )
466  {
467  CONST_LIST_OBJECT2D intersecting;
468 
469  m_antioutlineBoard2dObjects->GetIntersectingObjects( object2d_A->GetBBox(),
470  intersecting );
471 
472  for( const OBJECT_2D* obj : intersecting )
473  object2d_B->push_back( obj );
474  }
475 
476  if( object2d_B->empty() )
477  {
478  delete object2d_B;
479  object2d_B = CSGITEM_EMPTY;
480  }
481 
482  if( object2d_B == CSGITEM_EMPTY )
483  {
484  LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A,
487 
488  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
490  m_objectContainer.Add( objPtr );
491  }
492  else
493  {
494 
495  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
496  CSGITEM_FULL,
498 
499  m_containerWithObjectsToDelete.Add( itemCSG2d );
500 
501  LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d,
504 
505  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
507  m_objectContainer.Add( objPtr );
508  }
509  }
510 
511  // Add cylinders of the board body to container
512  // Note: This is actually a workaround for the holes in the board.
513  // The issue is because if a hole is in a border of a divided polygon ( ex
514  // a polygon or dummy block) it will cut also the render of the hole.
515  // So this will add a full hole.
516  // In fact, that is not need if the hole have copper.
517  if( !m_boardAdapter.GetThroughHoleOds().GetList().empty() )
518  {
520 
521  for( const OBJECT_2D* hole2d : holeList )
522  {
523  if( !m_antioutlineBoard2dObjects->GetList().empty() )
524  {
525  CONST_LIST_OBJECT2D intersecting;
526 
528  intersecting );
529 
530  // Do not add cylinder if it intersects the edge of the board
531  if( !intersecting.empty() )
532  continue;
533  }
534 
535  switch( hole2d->GetObjectType() )
536  {
538  {
539  const float radius = hole2d->GetBBox().GetExtent().x * 0.5f * 0.999f;
540 
541  CYLINDER* objPtr = new CYLINDER( hole2d->GetCentroid(),
544  radius );
545 
546  objPtr->SetMaterial( &m_materials.m_EpoxyBoard );
548 
549  m_objectContainer.Add( objPtr );
550  }
551  break;
552 
553  default:
554  break;
555  }
556  }
557  }
558  }
559  }
560  }
561 
562  if( aStatusReporter )
563  aStatusReporter->Report( _( "Load Raytracing: layers" ) );
564 
565  // Add layers maps (except B_Mask and F_Mask)
566  for( auto entry : m_boardAdapter.GetLayerMap() )
567  {
568  PCB_LAYER_ID layer_id = entry.first;
569  const BVH_CONTAINER_2D* container2d = entry.second;
570 
571  // Only process layers that exist
572  if( !container2d )
573  continue;
574 
575  if( aOnlyLoadCopperAndShapes && !IsCopperLayer( layer_id ) )
576  continue;
577 
578  // Mask layers are not processed here because they are a special case
579  if( layer_id == B_Mask || layer_id == F_Mask )
580  continue;
581 
582  MATERIAL* materialLayer = &m_materials.m_SilkS;
583  SFVEC3F layerColor = SFVEC3F( 0.0f, 0.0f, 0.0f );
584 
585  switch( layer_id )
586  {
587  case B_Adhes:
588  case F_Adhes:
589  break;
590 
591  case B_Paste:
592  case F_Paste:
593  materialLayer = &m_materials.m_Paste;
594 
596  layerColor = m_boardAdapter.m_SolderPasteColor;
597  else
598  layerColor = m_boardAdapter.GetLayerColor( layer_id );
599 
600  break;
601 
602  case B_SilkS:
603  materialLayer = &m_materials.m_SilkS;
604 
607  else
608  layerColor = m_boardAdapter.GetLayerColor( layer_id );
609 
610  break;
611 
612  case F_SilkS:
613  materialLayer = &m_materials.m_SilkS;
614 
617  else
618  layerColor = m_boardAdapter.GetLayerColor( layer_id );
619 
620  break;
621 
622  case Dwgs_User:
623  case Cmts_User:
624  case Eco1_User:
625  case Eco2_User:
626  case Edge_Cuts:
627  case Margin:
628  break;
629 
630  case B_CrtYd:
631  case F_CrtYd:
632  break;
633 
634  case B_Fab:
635  case F_Fab:
636  break;
637 
638  default:
640  {
642  layerColor = SFVEC3F( 184.0f / 255.0f, 115.0f / 255.0f, 50.0f / 255.0f );
643  else
644  layerColor = m_boardAdapter.m_CopperColor;
645  }
646  else
647  {
648  layerColor = m_boardAdapter.GetLayerColor( layer_id );
649  }
650 
651  materialLayer = &m_materials.m_NonPlatedCopper;
652  break;
653  }
654 
655  createItemsFromContainer( container2d, layer_id, materialLayer, layerColor, 0.0f );
656  } // for each layer on map
657 
658  // Create plated copper
661  {
665 
669  }
670 
671  if( !aOnlyLoadCopperAndShapes )
672  {
673  // Add Mask layer
674  // Solder mask layers are "negative" layers so the elements that we have in the container
675  // should remove the board outline. We will check for all objects in the outline if it
676  // intersects any object in the layer container and also any hole.
678  {
679  const MATERIAL* materialLayer = &m_materials.m_SolderMask;
680 
681  for( auto entry : m_boardAdapter.GetLayerMap() )
682  {
683  PCB_LAYER_ID layer_id = entry.first;
684  const BVH_CONTAINER_2D* container2d = entry.second;
685 
686  // Only process layers that exist
687  if( !container2d )
688  continue;
689 
690  // Only get the Solder mask layers (and only if the board has them)
691  if( !( layer_id == B_Mask || layer_id == F_Mask ) )
692  continue;
693 
694  SFVEC3F layerColor;
695 
697  {
698  if( layer_id == B_Mask )
700  else
702  }
703  else
704  {
705  layerColor = m_boardAdapter.GetLayerColor( layer_id );
706  }
707 
708  const float zLayerMin = m_boardAdapter.GetLayerBottomZPos( layer_id );
709  const float zLayerMax = m_boardAdapter.GetLayerTopZPos( layer_id );
710 
711  // Get the outline board objects
712  for( const OBJECT_2D* object2d_A : m_outlineBoard2dObjects->GetList() )
713  {
714  std::vector<const OBJECT_2D*>* object2d_B = new std::vector<const OBJECT_2D*>();
715 
716  // Check if there are any THT that intersects this outline object part
717  if( !m_boardAdapter.GetThroughHoleOds().GetList().empty() )
718  {
719  const BVH_CONTAINER_2D& throughHoles = m_boardAdapter.GetThroughHoleOds();
720  CONST_LIST_OBJECT2D intersecting;
721 
722  throughHoles.GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
723 
724  for( const OBJECT_2D* hole : intersecting )
725  {
726  if( object2d_A->Intersects( hole->GetBBox() ) )
727  object2d_B->push_back( hole );
728  }
729  }
730 
731  // Check if there are any objects in the layer to subtract with the current
732  // object
733  if( !container2d->GetList().empty() )
734  {
735  CONST_LIST_OBJECT2D intersecting;
736 
737  container2d->GetIntersectingObjects( object2d_A->GetBBox(), intersecting );
738 
739  for( const OBJECT_2D* obj : intersecting )
740  object2d_B->push_back( obj );
741  }
742 
743  if( object2d_B->empty() )
744  {
745  delete object2d_B;
746  object2d_B = CSGITEM_EMPTY;
747  }
748 
749  if( object2d_B == CSGITEM_EMPTY )
750  {
751 #if 0
752  createObject( m_objectContainer, object2d_A, zLayerMin, zLayerMax,
753  materialLayer, layerColor );
754 #else
755  LAYER_ITEM* objPtr = new LAYER_ITEM( object2d_A, zLayerMin, zLayerMax );
756 
757  objPtr->SetMaterial( materialLayer );
758  objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
759 
760  m_objectContainer.Add( objPtr );
761 #endif
762  }
763  else
764  {
765  LAYER_ITEM_2D* itemCSG2d = new LAYER_ITEM_2D( object2d_A, object2d_B,
766  CSGITEM_FULL,
767  object2d_A->GetBoardItem() );
768 
769  m_containerWithObjectsToDelete.Add( itemCSG2d );
770 
771  LAYER_ITEM* objPtr = new LAYER_ITEM( itemCSG2d, zLayerMin, zLayerMax );
772  objPtr->SetMaterial( materialLayer );
773  objPtr->SetColor( ConvertSRGBToLinear( layerColor ) );
774 
775  m_objectContainer.Add( objPtr );
776  }
777  }
778  }
779  }
780 
781  addPadsAndVias();
782  }
783 
784 #ifdef PRINT_STATISTICS_3D_VIEWER
785  unsigned stats_endConvertTime = GetRunningMicroSecs();
786  unsigned stats_startLoad3DmodelsTime = stats_endConvertTime;
787 #endif
788 
789  if( aStatusReporter )
790  aStatusReporter->Report( _( "Loading 3D models..." ) );
791 
792  load3DModels( m_objectContainer, aOnlyLoadCopperAndShapes );
793 
794 #ifdef PRINT_STATISTICS_3D_VIEWER
795  unsigned stats_endLoad3DmodelsTime = GetRunningMicroSecs();
796 #endif
797 
798  if( !aOnlyLoadCopperAndShapes )
799  {
800  // Add floor
802  {
803  BBOX_3D boardBBox = m_boardAdapter.GetBBox();
804 
805  if( boardBBox.IsInitialized() )
806  {
807  boardBBox.Scale( 3.0f );
808 
809  if( m_objectContainer.GetList().size() > 0 )
810  {
811  BBOX_3D containerBBox = m_objectContainer.GetBBox();
812 
813  containerBBox.Scale( 1.3f );
814 
815  const SFVEC3F centerBBox = containerBBox.GetCenter();
816 
817  // Floor triangles
818  const float minZ = glm::min( containerBBox.Min().z, boardBBox.Min().z );
819 
820  const SFVEC3F v1 =
821  SFVEC3F( -RANGE_SCALE_3D * 4.0f, -RANGE_SCALE_3D * 4.0f, minZ )
822  + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
823 
824  const SFVEC3F v3 =
825  SFVEC3F( +RANGE_SCALE_3D * 4.0f, +RANGE_SCALE_3D * 4.0f, minZ )
826  + SFVEC3F( centerBBox.x, centerBBox.y, 0.0f );
827 
828  const SFVEC3F v2 = SFVEC3F( v1.x, v3.y, v1.z );
829  const SFVEC3F v4 = SFVEC3F( v3.x, v1.y, v1.z );
830 
832 
833  TRIANGLE* newTriangle1 = new TRIANGLE( v1, v2, v3 );
834  TRIANGLE* newTriangle2 = new TRIANGLE( v3, v4, v1 );
835 
836  m_objectContainer.Add( newTriangle1 );
837  m_objectContainer.Add( newTriangle2 );
838 
839  newTriangle1->SetMaterial( &m_materials.m_Floor );
840  newTriangle2->SetMaterial( &m_materials.m_Floor );
841 
842  newTriangle1->SetColor( backgroundColor );
843  newTriangle2->SetColor( backgroundColor );
844 
845  // Ceiling triangles
846  const float maxZ = glm::max( containerBBox.Max().z, boardBBox.Max().z );
847 
848  const SFVEC3F v5 = SFVEC3F( v1.x, v1.y, maxZ );
849  const SFVEC3F v6 = SFVEC3F( v2.x, v2.y, maxZ );
850  const SFVEC3F v7 = SFVEC3F( v3.x, v3.y, maxZ );
851  const SFVEC3F v8 = SFVEC3F( v4.x, v4.y, maxZ );
852 
853  TRIANGLE* newTriangle3 = new TRIANGLE( v7, v6, v5 );
854  TRIANGLE* newTriangle4 = new TRIANGLE( v5, v8, v7 );
855 
856  m_objectContainer.Add( newTriangle3 );
857  m_objectContainer.Add( newTriangle4 );
858 
859  newTriangle3->SetMaterial( &m_materials.m_Floor );
860  newTriangle4->SetMaterial( &m_materials.m_Floor );
861 
862  newTriangle3->SetColor( backgroundColor );
863  newTriangle4->SetColor( backgroundColor );
864  }
865  }
866  }
867 
868  // Init initial lights
869  for( LIGHT* light : m_lights )
870  delete light;
871 
872  m_lights.clear();
873 
874  auto IsColorZero =
875  []( const SFVEC3F& aSource )
876  {
877  return ( ( aSource.r < ( 1.0f / 255.0f ) ) && ( aSource.g < ( 1.0f / 255.0f ) )
878  && ( aSource.b < ( 1.0f / 255.0f ) ) );
879  };
880 
881  m_cameraLight = new DIRECTIONAL_LIGHT( SFVEC3F( 0.0f, 0.0f, 0.0f ),
883  m_cameraLight->SetCastShadows( false );
884 
885  if( !IsColorZero( m_boardAdapter.m_RtCameraLightColor ) )
886  m_lights.push_back( m_cameraLight );
887 
888  const SFVEC3F& boardCenter = m_boardAdapter.GetBBox().GetCenter();
889 
890  if( !IsColorZero( m_boardAdapter.m_RtLightColorTop ) )
891  {
892  m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
893  +RANGE_SCALE_3D * 2.0f ),
895  }
896 
897  if( !IsColorZero( m_boardAdapter.m_RtLightColorBottom ) )
898  {
899  m_lights.push_back( new POINT_LIGHT( SFVEC3F( boardCenter.x, boardCenter.y,
900  -RANGE_SCALE_3D * 2.0f ),
902  }
903 
904  wxASSERT( m_boardAdapter.m_RtLightColor.size()
906 
907  for( size_t i = 0; i < m_boardAdapter.m_RtLightColor.size(); ++i )
908  {
909  if( !IsColorZero( m_boardAdapter.m_RtLightColor[i] ) )
910  {
912 
913  m_lights.push_back( new DIRECTIONAL_LIGHT(
914  SphericalToCartesian( glm::pi<float>() * sc.x, glm::pi<float>() * sc.y ),
916  }
917  }
918  }
919 
920  // Create an accelerator
921  delete m_accelerator;
923 
924  if( aStatusReporter )
925  {
926  // Calculation time in seconds
927  double calculation_time = (double) GetRunningMicroSecs() - stats_startReloadTime / 1e6;
928 
929  aStatusReporter->Report( wxString::Format( _( "Reload time %.3f s" ), calculation_time ) );
930  }
931 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
void SetBoardLookAtPos(const SFVEC3F &aBoardPos)
Definition: camera.h:114
BOARD_ADAPTER & m_boardAdapter
std::list< const OBJECT_2D * > CONST_LIST_OBJECT2D
Definition: container_2d.h:39
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
int OutlineCount() const
Return the number of vertices in a given outline/hole.
A base light class to derive to implement other light classes.
Definition: light.h:40
SFVEC4F m_SilkScreenColorBot
in realistic mode: SilkScreen color ( bot )
MAP_MODEL_MATERIALS m_modelMaterialMap
Stores materials of the 3D models.
void SetColor(SFVEC3F aObjColor)
Definition: cylinder_3d.h:48
const SFVEC3F & Max() const
Return the maximum vertex pointer.
Definition: bbox_3d.h:198
Manage a bounding box defined by two SFVEC3F min max points.
Definition: bbox_3d.h:41
SFVEC4F m_SolderMaskColorTop
in realistic mode: solder mask color ( top )
const MAP_CONTAINER_2D_BASE & GetLayerMap() const noexcept
Get the map of containers that have the objects per layer.
float GetAverageHoleDiameter() const noexcept
Average diameter of through holes.
void InitSettings(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
Function to be called by the render when it need to reload the settings for the board.
std::vector< SFVEC2F > m_RtLightSphericalCoords
const LIST_OBJECT & GetList() const
Definition: container_3d.h:59
SFVEC4F m_BoardBodyColor
in realistic mode: FR4 board color
SFVEC4F m_SolderPasteColor
in realistic mode: solder paste color
SFVEC4F m_SolderMaskColorBot
in realistic mode: solder mask color ( bot )
std::list< LIGHT * > m_lights
Point light source based on http://ogldev.atspace.co.uk/www/tutorial20/tutorial20....
Definition: light.h:70
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
SFVEC3F m_RtCameraLightColor
#define CSGITEM_FULL
Definition: layer_item_2d.h:39
const SFVEC3F & Min() const
Return the minimum vertex pointer.
Definition: bbox_3d.h:191
CONTAINER_2D m_containerWithObjectsToDelete
A vertical cylinder.
Definition: cylinder_3d.h:37
const LIST_OBJECT2D & GetList() const
Definition: container_2d.h:66
Base material class that can be used to derive other material implementations.
Definition: material.h:239
void Add(OBJECT_2D *aObject)
Definition: container_2d.h:49
void SetColor(const SFVEC3F &aColor)
SFVEC3F GetCenter() const
Return the center point of the bounding box.
Definition: bbox_3d.cpp:132
void Scale(float aScale)
Scales a bounding box by its center.
Definition: bbox_3d.cpp:191
const BVH_CONTAINER_2D * GetPlatedPadsBack() const noexcept
SFVEC4F m_BgColorTop
background top color
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
void SetMaterial(const MATERIAL *aMaterial)
Definition: object_3d.h:58
float NextFloatDown(float v)
Definition: 3d_fastmath.h:157
#define CSGITEM_EMPTY
Definition: layer_item_2d.h:38
Represent a set of closed polygons.
float GetLayerTopZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the top z position.
float GetLayerBottomZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the bottom z position.
SFVEC3F m_RtLightColorTop
void load3DModels(CONTAINER_3D &aDstContainer, bool aSkipMaterialInformation)
static OBJECT_2D_STATS & Instance()
Definition: object_2d.h:137
void ConvertPolygonToBlocks(const SHAPE_POLY_SET &aMainPath, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, float aDivFactor, const BOARD_ITEM &aBoardItem, int aPolyIndex)
Use a polygon in the format of the ClipperLib::Path and process it and create multiple 2d objects (PO...
Definition: polygon_2d.cpp:378
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
static OBJECT_3D_STATS & Instance()
Definition: object_3d.h:132
const BOARD * GetBoard() const noexcept
Get current board to be rendered.
#define _(s)
const BVH_CONTAINER_2D & GetThroughHoleOds() const noexcept
Get the inflated through hole outside diameters container.
std::vector< SFVEC3F > m_RtLightColor
const SHAPE_POLY_SET & GetBoardPoly() const noexcept
Get the current polygon of the epoxy board.
bool IsInitialized() const
Check if this bounding box is already initialized.
Definition: bbox_3d.cpp:88
void createObject(CONTAINER_3D &aDstContainer, const OBJECT_2D *aObject2D, float aZMin, float aZMax, const MATERIAL *aMaterial, const SFVEC3F &aObjColor)
Create one or more 3D objects form a 2D object and Z positions.
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:796
void GetIntersectingObjects(const BBOX_2D &aBBox, CONST_LIST_OBJECT2D &aOutList) const override
Get a list of objects that intersects a bounding box.
void SetCastShadows(bool aCastShadow)
Definition: light.h:59
void buildBoardBoundingBoxPoly(const BOARD *aBoard, SHAPE_POLY_SET &aOutline)
Get the complete bounding box of the board (including all items).
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void ResetStats()
Definition: object_3d.h:115
bool m_reloadRequested
The window size that this camera is working.
const BBOX_3D & GetBBox() const noexcept
Get the board outling bounding box.
unsigned int GetViaCount() const noexcept
Get number of vias in this board.
A triangle object.
Definition: triangle_3d.h:42
DIRECTIONAL_LIGHT * m_cameraLight
const BBOX_3D & GetBBox() const
Definition: container_3d.h:63
A light source based only on a directional vector.
Definition: light.h:115
unsigned int GetHoleCount() const noexcept
Get number of holes in this board.
SFVEC4F GetLayerColor(PCB_LAYER_ID aLayerId) const
Get the technical color of a layer.
const BVH_CONTAINER_2D * GetPlatedPadsFront() const noexcept
Make solid geometry for objects on layers.
Definition: layer_item_2d.h:79
unsigned GetRunningMicroSecs()
An alternate way to calculate an elapset time (in microsecondes) to class PROF_COUNTER.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
void SetColor(SFVEC3F aObjColor)
Definition: layer_item_3d.h:37
void createItemsFromContainer(const BVH_CONTAINER_2D *aContainer2d, PCB_LAYER_ID aLayer_id, const MATERIAL *aMaterialLayer, const SFVEC3F &aLayerColor, float aLayerZOffset)
SFVEC4F m_CopperColor
in realistic mode: copper color
Definition: layer_ids.h:71
float NextFloatUp(float v)
Definition: 3d_fastmath.h:136
const SFVEC3F & GetBoardCenter() const noexcept
The board center position in 3D units.
SFVEC3F SphericalToCartesian(float aInclination, float aAzimuth)
https://en.wikipedia.org/wiki/Spherical_coordinate_system
Definition: 3d_math.h:43
float GetAverageViaHoleDiameter() const noexcept
Thee average diameter of the via holes.
CAMERA & m_camera
Flag if the opengl specific for this render was already initialized.
std::list< OBJECT_2D * > LIST_OBJECT2D
Definition: container_2d.h:36
SFVEC4F m_SilkScreenColorTop
in realistic mode: SilkScreen color ( top )
float GetCopperThickness() const noexcept
Get the current copper layer thickness.
void Add(OBJECT_3D *aObject)
Definition: container_3d.h:48
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
void ResetStats()
Definition: object_2d.h:122
SFVEC3F m_RtLightColorBottom
ACCELERATOR_3D * m_accelerator
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
CONTAINER_2D * m_outlineBoard2dObjects
#define RANGE_SCALE_3D
This defines the range that all coord will have to be rendered.
Definition: board_adapter.h:62
struct RENDER_3D_RAYTRACE::@5 m_materials
BVH_CONTAINER_2D * m_antioutlineBoard2dObjects
virtual void Clear()
CONTAINER_3D m_objectContainer
Store the list of created objects special for RT that will be clear in the end.

References _, CONTAINER_3D_BASE::Add(), CONTAINER_2D_BASE::Add(), addPadsAndVias(), B_Adhes, B_CrtYd, B_Cu, B_Fab, B_Mask, B_Paste, B_SilkS, BOARD_ADAPTER::BiuTo3dUnits(), SHAPE_POLY_SET::BooleanSubtract(), buildBoardBoundingBoxPoly(), BVH_CONTAINER_2D::BuildBVH(), CONTAINER_3D_BASE::Clear(), CONTAINER_2D_BASE::Clear(), Cmts_User, ConvertPolygonToBlocks(), ConvertSRGBToLinear(), createItemsFromContainer(), createObject(), CSGITEM_EMPTY, CSGITEM_FULL, CYLINDER, Dwgs_User, Eco1_User, Eco2_User, Edge_Cuts, F_Adhes, F_CrtYd, F_Cu, F_Fab, F_Mask, F_Paste, F_SilkS, FILLED_CIRCLE, FL_RENDER_PLATED_PADS_AS_PLATED, FL_RENDER_RAYTRACING_BACKFLOOR, FL_SHOW_BOARD_BODY, FL_SOLDERMASK, FL_USE_REALISTIC_MODE, Format(), SHAPE_POLY_SET::Fracture(), BOARD_ADAPTER::GetAverageHoleDiameter(), BOARD_ADAPTER::GetAverageViaHoleDiameter(), CONTAINER_3D_BASE::GetBBox(), BOARD_ADAPTER::GetBBox(), BOARD_ADAPTER::GetBoard(), BOARD_ADAPTER::GetBoardCenter(), BOARD_ADAPTER::GetBoardPoly(), BBOX_3D::GetCenter(), BOARD_ADAPTER::GetCopperThickness(), BOARD_ADAPTER::GetFlag(), BOARD_ADAPTER::GetHoleCount(), BVH_CONTAINER_2D::GetIntersectingObjects(), BOARD_ADAPTER::GetLayerBottomZPos(), BOARD_ADAPTER::GetLayerColor(), BOARD_ADAPTER::GetLayerMap(), BOARD_ADAPTER::GetLayerTopZPos(), CONTAINER_3D_BASE::GetList(), CONTAINER_2D_BASE::GetList(), BOARD_ADAPTER::GetPlatedPadsBack(), BOARD_ADAPTER::GetPlatedPadsFront(), GetRunningMicroSecs(), BOARD_ADAPTER::GetThroughHoleOds(), BOARD_ADAPTER::GetViaCount(), BOARD_ADAPTER::InitSettings(), OBJECT_3D_STATS::Instance(), OBJECT_2D_STATS::Instance(), IsCopperLayer(), BBOX_3D::IsInitialized(), load3DModels(), m_accelerator, m_antioutlineBoard2dObjects, BOARD_ADAPTER::m_BgColorTop, RENDER_3D_BASE::m_boardAdapter, BOARD_ADAPTER::m_BoardBodyColor, RENDER_3D_BASE::m_camera, m_cameraLight, m_containerWithObjectsToDelete, BOARD_ADAPTER::m_CopperColor, m_lights, m_materials, m_modelMaterialMap, m_objectContainer, m_outlineBoard2dObjects, RENDER_3D_BASE::m_reloadRequested, BOARD_ADAPTER::m_RtCameraLightColor, BOARD_ADAPTER::m_RtLightColor, BOARD_ADAPTER::m_RtLightColorBottom, BOARD_ADAPTER::m_RtLightColorTop, BOARD_ADAPTER::m_RtLightSphericalCoords, BOARD_ADAPTER::m_SilkScreenColorBot, BOARD_ADAPTER::m_SilkScreenColorTop, BOARD_ADAPTER::m_SolderMaskColorBot, BOARD_ADAPTER::m_SolderMaskColorTop, BOARD_ADAPTER::m_SolderPasteColor, Margin, BBOX_3D::Max(), MIDDLE, BBOX_3D::Min(), NextFloatDown(), NextFloatUp(), SHAPE_POLY_SET::OutlineCount(), SHAPE_POLY_SET::PM_FAST, RANGE_SCALE_3D, REPORTER::Report(), OBJECT_3D_STATS::ResetStats(), OBJECT_2D_STATS::ResetStats(), BBOX_3D::Scale(), CAMERA::SetBoardLookAtPos(), LIGHT::SetCastShadows(), LAYER_ITEM::SetColor(), CYLINDER::SetColor(), TRIANGLE::SetColor(), OBJECT_3D::SetMaterial(), setupMaterials(), SphericalToCartesian(), TRIANGLE, v2, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by EDA_3D_CANVAS::DoRePaint(), and Redraw().

◆ ReloadRequest()

void RENDER_3D_BASE::ReloadRequest ( )
inlineinherited
Todo:
This must be reviewed to add flags to improve specific render.

Definition at line 70 of file render_3d_base.h.

70 { m_reloadRequested = true; }
bool m_reloadRequested
The window size that this camera is working.

References RENDER_3D_BASE::m_reloadRequested.

Referenced by EDA_3D_CANVAS::ReloadRequest(), EDA_3D_CANVAS::RenderEngineChanged(), and EDA_3D_CANVAS::RenderRaytracingRequest().

◆ render()

void RENDER_3D_RAYTRACE::render ( GLubyte *  ptrPBO,
REPORTER aStatusReporter 
)
private

Definition at line 287 of file render_3d_raytrace.cpp.

288 {
290  {
292 
293  if( m_cameraLight )
295 
297  {
298  // Set all pixels of PBO transparent (Alpha to 0)
299  // This way it will draw the full buffer but only shows the updated (
300  // already calculated) squares
301  unsigned int nPixels = m_realBufferSize.x * m_realBufferSize.y;
302  GLubyte* tmp_ptrPBO = ptrPBO + 3; // PBO is RGBA
303 
304  for( unsigned int i = 0; i < nPixels; ++i )
305  {
306  *tmp_ptrPBO = 0;
307  tmp_ptrPBO += 4; // PBO is RGBA
308  }
309  }
310 
313  }
314 
315  switch( m_renderState )
316  {
318  renderTracing( ptrPBO, aStatusReporter );
319  break;
320 
322  postProcessShading( ptrPBO, aStatusReporter );
323  break;
324 
326  postProcessBlurFinish( ptrPBO, aStatusReporter );
327  break;
328 
329  default:
330  wxASSERT_MSG( false, "Invalid state on m_renderState");
332  break;
333  }
334 
335  if( aStatusReporter && ( m_renderState == RT_RENDER_STATE_FINISH ) )
336  {
337  // Calculation time in seconds
338  const double elapsed_time = (double)( GetRunningMicroSecs() - m_renderStartTime ) / 1e6;
339 
340  aStatusReporter->Report( wxString::Format( _( "Rendering time %.3f s" ), elapsed_time ) );
341  }
342 }
BOARD_ADAPTER & m_boardAdapter
unsigned long int m_renderStartTime
Time that the render starts.
RT_RENDER_STATE m_renderState
State used on quality render.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
RENDER_ENGINE GetRenderEngine() const noexcept
void renderTracing(GLubyte *ptrPBO, REPORTER *aStatusReporter)
SFVEC4F m_BgColorTop
background top color
#define _(s)
SFVEC4F m_BgColorBot
background bottom color
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
SFVEC3F m_backgroundColorBottom
Used to see if the windows size changed.
DIRECTIONAL_LIGHT * m_cameraLight
const SFVEC3F & GetDir() const
Definition: camera.h:108
unsigned GetRunningMicroSecs()
An alternate way to calculate an elapset time (in microsecondes) to class PROF_COUNTER.
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
void postProcessShading(GLubyte *ptrPBO, REPORTER *aStatusReporter)
CAMERA & m_camera
Flag if the opengl specific for this render was already initialized.
void SetDirection(const SFVEC3F &aDir)
Set directional light orientation.
Definition: light.h:131
void postProcessBlurFinish(GLubyte *ptrPBO, REPORTER *aStatusReporter)
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)

References _, ConvertSRGBToLinear(), Format(), CAMERA::GetDir(), BOARD_ADAPTER::GetRenderEngine(), GetRunningMicroSecs(), m_backgroundColorBottom, m_backgroundColorTop, BOARD_ADAPTER::m_BgColorBot, BOARD_ADAPTER::m_BgColorTop, RENDER_3D_BASE::m_boardAdapter, RENDER_3D_BASE::m_camera, m_cameraLight, m_realBufferSize, m_renderStartTime, m_renderState, OPENGL, postProcessBlurFinish(), postProcessShading(), renderTracing(), REPORTER::Report(), restartRenderState(), RT_RENDER_STATE_FINISH, RT_RENDER_STATE_MAX, RT_RENDER_STATE_POST_PROCESS_BLUR_AND_FINISH, RT_RENDER_STATE_POST_PROCESS_SHADE, RT_RENDER_STATE_TRACING, and DIRECTIONAL_LIGHT::SetDirection().

Referenced by Redraw().

◆ renderAntiAliasPackets()

void RENDER_3D_RAYTRACE::renderAntiAliasPackets ( const SFVEC3F aBgColorY,
const HITINFO_PACKET aHitPck_X0Y0,
const HITINFO_PACKET aHitPck_AA_X1Y1,
const RAY aRayPck,
SFVEC3F aOutHitColor 
)
private
Todo:
Either get rid of the if statement above or do something with the commented out code below.

Definition at line 502 of file render_3d_raytrace.cpp.

506 {
507  const bool is_testShadow = m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_SHADOWS );
508 
509  for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
510  {
511  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
512  {
513  const RAY& rayAA = aRayPck[i];
514 
515  HITINFO hitAA;
516  hitAA.m_tHit = std::numeric_limits<float>::infinity();
517  hitAA.m_acc_node_info = 0;
518 
519  bool hitted = false;
520 
521  const unsigned int idx0y1 = ( x + 0 ) + RAYPACKET_DIM * ( y + 1 );
522  const unsigned int idx1y1 = ( x + 1 ) + RAYPACKET_DIM * ( y + 1 );
523 
524  // Gets the node info from the hit.
525  const unsigned int nodex0y0 = aHitPck_X0Y0[ i ].m_HitInfo.m_acc_node_info;
526  const unsigned int node_AA_x0y0 = aHitPck_AA_X1Y1[ i ].m_HitInfo.m_acc_node_info;
527 
528  unsigned int nodex1y0 = 0;
529 
530  if( x < (RAYPACKET_DIM - 1) )
531  nodex1y0 = aHitPck_X0Y0[ i + 1 ].m_HitInfo.m_acc_node_info;
532 
533  unsigned int nodex0y1 = 0;
534 
535  if( y < ( RAYPACKET_DIM - 1 ) && idx0y1 < RAYPACKET_RAYS_PER_PACKET )
536  nodex0y1 = aHitPck_X0Y0[idx0y1].m_HitInfo.m_acc_node_info;
537 
538  unsigned int nodex1y1 = 0;
539 
540  if( ( x < ( RAYPACKET_DIM - 1 ) ) && ( y < ( RAYPACKET_DIM - 1 ) )
541  && idx1y1 < RAYPACKET_RAYS_PER_PACKET )
542  nodex1y1 = aHitPck_X0Y0[idx1y1].m_HitInfo.m_acc_node_info;
543 
544  // If all notes are equal we assume there was no change on the object hits.
545  if( ( ( nodex0y0 == nodex1y0 ) || ( nodex1y0 == 0 ) )
546  && ( ( nodex0y0 == nodex0y1 ) || ( nodex0y1 == 0 ) )
547  && ( ( nodex0y0 == nodex1y1 ) || ( nodex1y1 == 0 ) )
548  && ( nodex0y0 == node_AA_x0y0 ) )
549  {
552  // Option 1
553  // This option will give a very good quality on reflections (slow)
554  /*
555  if( m_accelerator->Intersect( rayAA, hitAA, nodex0y0 ) )
556  {
557  aOutHitColor[i] += shadeHit( aBgColorY[y], rayAA, hitAA, false, 0 );
558  }
559  else
560  {
561  if( m_accelerator->Intersect( rayAA, hitAA ) )
562  aOutHitColor[i] += shadeHit( aBgColorY[y], rayAA, hitAA, false, 0 );
563  else
564  aOutHitColor[i] += hitColor[i];
565  }
566  */
567 
568  // Option 2
569  // Trace again with the same node,
570  // then if miss just give the same color as before
571  //if( m_accelerator->Intersect( rayAA, hitAA, nodex0y0 ) )
572  // aOutHitColor[i] += shadeHit( aBgColorY[y], rayAA, hitAA, false, 0 );
573 
574  // Option 3
575  // Use same color
576  }
577  else
578  {
579  // Try to intersect the different nodes
580  // It tests the possible combination of hitted or not hitted points
581  // This will try to get the best hit for this ray
582 
583  if( nodex0y0 != 0 )
584  hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex0y0 );
585 
586  if( ( nodex1y0 != 0 ) && ( nodex0y0 != nodex1y0 ) )
587  hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex1y0 );
588 
589  if( ( nodex0y1 != 0 ) && ( nodex0y0 != nodex0y1 ) && ( nodex1y0 != nodex0y1 ) )
590  hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex0y1 );
591 
592  if( ( nodex1y1 != 0 ) && ( nodex0y0 != nodex1y1 ) && ( nodex0y1 != nodex1y1 ) &&
593  ( nodex1y0 != nodex1y1 ) )
594  hitted |= m_accelerator->Intersect( rayAA, hitAA, nodex1y1 );
595 
596  if( (node_AA_x0y0 != 0 ) && ( nodex0y0 != node_AA_x0y0 ) &&
597  ( nodex0y1 != node_AA_x0y0 ) && ( nodex1y0 != node_AA_x0y0 ) &&
598  ( nodex1y1 != node_AA_x0y0 ) )
599  hitted |= m_accelerator->Intersect( rayAA, hitAA, node_AA_x0y0 );
600 
601  if( hitted )
602  {
603  // If we got any result, shade it
604  aOutHitColor[i] = shadeHit( aBgColorY[y], rayAA, hitAA, false, 0,
605  is_testShadow );
606  }
607  else
608  {
609  // Note: There are very few cases that will end on this situation
610  // so it is not so expensive to trace a single ray from the beginning
611 
612  // It was missed the 'last nodes' so, trace a ray from the beginning
613  if( m_accelerator->Intersect( rayAA, hitAA ) )
614  aOutHitColor[i] = shadeHit( aBgColorY[y], rayAA, hitAA, false, 0,
615  is_testShadow );
616  }
617  }
618  }
619  }
620 }
#define RAYPACKET_DIM
Definition: raypacket.h:32
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
SFVEC3F shadeHit(const SFVEC3F &aBgColor, const RAY &aRay, HITINFO &aHitInfo, bool aIsInsideObject, unsigned int aRecursiveLevel, bool is_testShadow) const
Definition: ray.h:62
float m_tHit
( 4) distance
Definition: hitinfo.h:38
HITINFO m_HitInfo
Definition: hitinfo.h:58
Stores the hit information of a ray with a point on the surface of a object.
Definition: hitinfo.h:35
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
#define RAYPACKET_RAYS_PER_PACKET
Definition: raypacket.h:35
unsigned int m_acc_node_info
( 4) The acc stores here the node that it hits
Definition: hitinfo.h:42
ACCELERATOR_3D * m_accelerator

References FL_RENDER_RAYTRACING_SHADOWS, BOARD_ADAPTER::GetFlag(), ACCELERATOR_3D::Intersect(), HITINFO::m_acc_node_info, m_accelerator, RENDER_3D_BASE::m_boardAdapter, HITINFO_PACKET::m_HitInfo, HITINFO::m_tHit, RAYPACKET_DIM, RAYPACKET_RAYS_PER_PACKET, and shadeHit().

Referenced by renderBlockTracing().

◆ renderBlockTracing()

void RENDER_3D_RAYTRACE::renderBlockTracing ( GLubyte *  ptrPBO,
signed int  iBlock 
)
private

Definition at line 626 of file render_3d_raytrace.cpp.

627 {
628  // Initialize ray packets
629  const SFVEC2UI& blockPos = m_blockPositions[iBlock];
630  const SFVEC2I blockPosI = SFVEC2I( blockPos.x + m_xoffset, blockPos.y + m_yoffset );
631 
632  RAYPACKET blockPacket( m_camera, (SFVEC2F) blockPosI + SFVEC2F( DISP_FACTOR, DISP_FACTOR ),
633  SFVEC2F( DISP_FACTOR, DISP_FACTOR ) /* Displacement random factor */ );
634 
635 
637 
638  HITINFO_PACKET_init( hitPacket_X0Y0 );
639 
640  // Calculate background gradient color
641  SFVEC3F bgColor[RAYPACKET_DIM];// Store a vertical gradient color
642 
643  for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
644  {
645  const float posYfactor = (float) ( blockPosI.y + y ) / (float) m_windowSize.y;
646 
647  bgColor[y] = m_backgroundColorTop * SFVEC3F(posYfactor) +
648  m_backgroundColorBottom * ( SFVEC3F(1.0f) - SFVEC3F(posYfactor) );
649  }
650 
651  // Intersect ray packets (calculate the intersection with rays and objects)
652  if( !m_accelerator->Intersect( blockPacket, hitPacket_X0Y0 ) )
653  {
654  // If block is empty then set shades and continue
656  {
657  for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
658  {
659  const SFVEC3F& outColor = bgColor[y];
660 
661  const unsigned int yBlockPos = blockPos.y + y;
662 
663  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x )
664  {
665  m_postShaderSsao.SetPixelData( blockPos.x + x, yBlockPos,
666  SFVEC3F( 0.0f ), outColor,
667  SFVEC3F( 0.0f ), 0, 1.0f );
668  }
669  }
670  }
671 
672  // This will set the output color to be displayed
673  // If post processing is enabled, it will not reflect the final result
674  // (as the final color will be computed on post processing)
675  // but it is used for report progress
676  const bool isFinalColor = !m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_POST_PROCESSING );
677 
678  for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
679  {
680  const SFVEC3F& outColor = bgColor[y];
681 
682  const unsigned int yConst = blockPos.x + ( ( y + blockPos.y ) * m_realBufferSize.x );
683 
684  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x )
685  {
686  GLubyte* ptr = &ptrPBO[( yConst + x ) * 4];
687 
688  renderFinalColor( ptr, outColor, isFinalColor );
689  }
690  }
691 
692  // There is nothing more here to do.. there are no hits ..
693  // just background so continue
694  return;
695  }
696 
697  SFVEC3F hitColor_X0Y0[RAYPACKET_RAYS_PER_PACKET];
698 
699  // Shade original (0, 0) hits ("paint" the intersected objects)
700  renderRayPackets( bgColor, blockPacket.m_ray, hitPacket_X0Y0,
702 
704  {
705  SFVEC3F hitColor_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET];
706 
707  // Intersect one blockPosI + (0.5, 0.5) used for anti aliasing calculation
708  HITINFO_PACKET hitPacket_AA_X1Y1[RAYPACKET_RAYS_PER_PACKET];
709  HITINFO_PACKET_init( hitPacket_AA_X1Y1 );
710 
711  RAYPACKET blockPacket_AA_X1Y1( m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f, 0.5f ),
713 
714  if( !m_accelerator->Intersect( blockPacket_AA_X1Y1, hitPacket_AA_X1Y1 ) )
715  {
716  // Missed all the package
717  for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
718  {
719  const SFVEC3F& outColor = bgColor[y];
720 
721  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
722  {
723  hitColor_AA_X1Y1[i] = outColor;
724  }
725  }
726  }
727  else
728  {
729  renderRayPackets( bgColor, blockPacket_AA_X1Y1.m_ray, hitPacket_AA_X1Y1,
731  hitColor_AA_X1Y1 );
732  }
733 
734  SFVEC3F hitColor_AA_X1Y0[RAYPACKET_RAYS_PER_PACKET];
735  SFVEC3F hitColor_AA_X0Y1[RAYPACKET_RAYS_PER_PACKET];
736  SFVEC3F hitColor_AA_X0Y1_half[RAYPACKET_RAYS_PER_PACKET];
737 
738  for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
739  {
740  const SFVEC3F color_average = ( hitColor_X0Y0[i] +
741  hitColor_AA_X1Y1[i] ) * SFVEC3F( 0.5f );
742 
743  hitColor_AA_X1Y0[i] = color_average;
744  hitColor_AA_X0Y1[i] = color_average;
745  hitColor_AA_X0Y1_half[i] = color_average;
746  }
747 
748  RAY blockRayPck_AA_X1Y0[RAYPACKET_RAYS_PER_PACKET];
749  RAY blockRayPck_AA_X0Y1[RAYPACKET_RAYS_PER_PACKET];
750  RAY blockRayPck_AA_X1Y1_half[RAYPACKET_RAYS_PER_PACKET];
751 
753  m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.5f - DISP_FACTOR, DISP_FACTOR ),
754  SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X1Y0 );
755 
757  m_camera, (SFVEC2F) blockPosI + SFVEC2F( DISP_FACTOR, 0.5f - DISP_FACTOR ),
758  SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X0Y1 );
759 
761  m_camera, (SFVEC2F) blockPosI + SFVEC2F( 0.25f - DISP_FACTOR, 0.25f - DISP_FACTOR ),
762  SFVEC2F( DISP_FACTOR, DISP_FACTOR ), blockRayPck_AA_X1Y1_half );
763 
764  renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X1Y0,
765  hitColor_AA_X1Y0 );
766 
767  renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1, blockRayPck_AA_X0Y1,
768  hitColor_AA_X0Y1 );
769 
770  renderAntiAliasPackets( bgColor, hitPacket_X0Y0, hitPacket_AA_X1Y1,
771  blockRayPck_AA_X1Y1_half, hitColor_AA_X0Y1_half );
772 
773  // Average the result
774  for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
775  {
776  hitColor_X0Y0[i] = ( hitColor_X0Y0[i] + hitColor_AA_X1Y1[i] + hitColor_AA_X1Y0[i] +
777  hitColor_AA_X0Y1[i] + hitColor_AA_X0Y1_half[i] ) *
778  SFVEC3F( 1.0f / 5.0f );
779  }
780  }
781 
782  // Copy results to the next stage
783  GLubyte* ptr = &ptrPBO[( blockPos.x + ( blockPos.y * m_realBufferSize.x ) ) * 4];
784 
785  const uint32_t ptrInc = ( m_realBufferSize.x - RAYPACKET_DIM ) * 4;
786 
788  {
789  SFVEC2I bPos;
790  bPos.y = blockPos.y;
791 
792  for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
793  {
794  bPos.x = blockPos.x;
795 
796  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
797  {
798  const SFVEC3F& hColor = hitColor_X0Y0[i];
799 
800  if( hitPacket_X0Y0[i].m_hitresult == true )
801  m_postShaderSsao.SetPixelData( bPos.x, bPos.y,
802  hitPacket_X0Y0[i].m_HitInfo.m_HitNormal,
803  hColor,
804  blockPacket.m_ray[i].at(
805  hitPacket_X0Y0[i].m_HitInfo.m_tHit ),
806  hitPacket_X0Y0[i].m_HitInfo.m_tHit,
807  hitPacket_X0Y0[i].m_HitInfo.m_ShadowFactor );
808  else
809  m_postShaderSsao.SetPixelData( bPos.x, bPos.y, SFVEC3F( 0.0f ), hColor,
810  SFVEC3F( 0.0f ), 0, 1.0f );
811 
812  renderFinalColor( ptr, hColor, false );
813 
814  bPos.x++;
815  ptr += 4;
816  }
817 
818  ptr += ptrInc;
819  bPos.y++;
820  }
821  }
822  else
823  {
824  for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
825  {
826  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
827  {
828  renderFinalColor( ptr, hitColor_X0Y0[i], true );
829  ptr += 4;
830  }
831 
832  ptr += ptrInc;
833  }
834  }
835 }
#define RAYPACKET_DIM
Definition: raypacket.h:32
float m_ShadowFactor
( 4) Shadow attenuation (1.0 no shadow, 0.0f darkness)
Definition: hitinfo.h:45
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
void renderRayPackets(const SFVEC3F *bgColorY, const RAY *aRayPkt, HITINFO_PACKET *aHitPacket, bool is_testShadow, SFVEC3F *aOutHitColor)
static void HITINFO_PACKET_init(HITINFO_PACKET *aHitPacket)
Definition: ray.h:62
glm::ivec2 SFVEC2I
Definition: xv3d_types.h:39
void RAYPACKET_InitRays_with2DDisplacement(const CAMERA &aCamera, const SFVEC2F &aWindowsPosition, const SFVEC2F &a2DWindowsPosDisplacementFactor, RAY *aRayPck)
Definition: raypacket.cpp:162
float m_tHit
( 4) distance
Definition: hitinfo.h:38
std::vector< SFVEC2UI > m_blockPositions
Flag if a position was already processed (cleared each new render).
void SetPixelData(unsigned int x, unsigned int y, const SFVEC3F &aNormal, const SFVEC3F &aColor, const SFVEC3F &aHitPosition, float aDepth, float aShadowAttFactor)
Definition: post_shader.cpp:79
glm::uvec2 SFVEC2UI
Definition: xv3d_types.h:38
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
void renderFinalColor(GLubyte *ptrPBO, const SFVEC3F &rgbColor, bool applyColorSpaceConversion)
HITINFO m_HitInfo
Definition: hitinfo.h:58
POST_SHADER_SSAO m_postShaderSsao
SFVEC3F m_backgroundColorBottom
Used to see if the windows size changed.
void renderAntiAliasPackets(const SFVEC3F *aBgColorY, const HITINFO_PACKET *aHitPck_X0Y0, const HITINFO_PACKET *aHitPck_AA_X1Y1, const RAY *aRayPck, SFVEC3F *aOutHitColor)
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
#define RAYPACKET_RAYS_PER_PACKET
Definition: raypacket.h:35
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
CAMERA & m_camera
Flag if the opengl specific for this render was already initialized.
#define DISP_FACTOR
ACCELERATOR_3D * m_accelerator

References RAY::at(), DISP_FACTOR, FL_RENDER_RAYTRACING_ANTI_ALIASING, FL_RENDER_RAYTRACING_POST_PROCESSING, FL_RENDER_RAYTRACING_SHADOWS, BOARD_ADAPTER::GetFlag(), HITINFO_PACKET_init(), ACCELERATOR_3D::Intersect(), m_accelerator, m_backgroundColorBottom, m_backgroundColorTop, m_blockPositions, RENDER_3D_BASE::m_boardAdapter, RENDER_3D_BASE::m_camera, HITINFO_PACKET::m_HitInfo, HITINFO::m_HitNormal, m_postShaderSsao, RAYPACKET::m_ray, m_realBufferSize, HITINFO::m_ShadowFactor, HITINFO::m_tHit, RENDER_3D_BASE::m_windowSize, m_xoffset, m_yoffset, RAYPACKET_DIM, RAYPACKET_InitRays_with2DDisplacement(), RAYPACKET_RAYS_PER_PACKET, renderAntiAliasPackets(), renderFinalColor(), renderRayPackets(), and POST_SHADER::SetPixelData().

Referenced by renderTracing().

◆ renderFinalColor()

void RENDER_3D_RAYTRACE::renderFinalColor ( GLubyte *  ptrPBO,
const SFVEC3F rgbColor,
bool  applyColorSpaceConversion 
)
private
Note
This should be used in future when the KiCad support a greater version of glm lib.

Definition at line 445 of file render_3d_raytrace.cpp.

447 {
448  SFVEC3F color = rgbColor;
449 
450 #ifdef USE_SRGB_SPACE
451  // if( applyColorSpaceConversion )
453  // rgbColor = glm::convertLinearToSRGB( rgbColor );
454 
455  if( applyColorSpaceConversion )
456  color = convertLinearToSRGB( rgbColor );
457 #endif
458 
459  ptrPBO[0] = (unsigned int) glm::clamp( (int) ( color.r * 255 ), 0, 255 );
460  ptrPBO[1] = (unsigned int) glm::clamp( (int) ( color.g * 255 ), 0, 255 );
461  ptrPBO[2] = (unsigned int) glm::clamp( (int) ( color.b * 255 ), 0, 255 );
462  ptrPBO[3] = 255;
463 }
int color
Definition: DXF_plotter.cpp:57
static SFVEC3F convertLinearToSRGB(const SFVEC3F &aRGBcolor)
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44

References color, and convertLinearToSRGB().

Referenced by postProcessBlurFinish(), and renderBlockTracing().

◆ renderPreview()

void RENDER_3D_RAYTRACE::renderPreview ( GLubyte *  ptrPBO)
private

Definition at line 948 of file render_3d_raytrace.cpp.

949 {
950  m_isPreview = true;
951 
952  std::atomic<size_t> nextBlock( 0 );
953  std::atomic<size_t> threadsFinished( 0 );
954 
955  size_t parallelThreadCount = std::min<size_t>(
956  std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
957  m_blockPositions.size() );
958 
959  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
960  {
961  std::thread t = std::thread( [&]()
962  {
963  for( size_t iBlock = nextBlock.fetch_add( 1 ); iBlock < m_blockPositionsFast.size();
964  iBlock = nextBlock.fetch_add( 1 ) )
965  {
966  const SFVEC2UI& windowPosUI = m_blockPositionsFast[ iBlock ];
967  const SFVEC2I windowsPos = SFVEC2I( windowPosUI.x + m_xoffset,
968  windowPosUI.y + m_yoffset );
969 
970  RAYPACKET blockPacket( m_camera, windowsPos, 4 );
971 
973 
974  // Initialize hitPacket with a "not hit" information
975  for( HITINFO_PACKET& packet : hitPacket )
976  {
977  packet.m_HitInfo.m_tHit = std::numeric_limits<float>::infinity();
978  packet.m_HitInfo.m_acc_node_info = 0;
979  packet.m_hitresult = false;
980  }
981 
982  // Intersect packet block
983  m_accelerator->Intersect( blockPacket, hitPacket );
984 
985  // Calculate background gradient color
986  SFVEC3F bgColor[RAYPACKET_DIM];
987 
988  for( unsigned int y = 0; y < RAYPACKET_DIM; ++y )
989  {
990  const float posYfactor =
991  (float) ( windowsPos.y + y * 4.0f ) / (float) m_windowSize.y;
992 
993  bgColor[y] = (SFVEC3F) m_boardAdapter.m_BgColorTop * SFVEC3F( posYfactor )
995  * ( SFVEC3F( 1.0f ) - SFVEC3F( posYfactor ) );
996  }
997 
998  COLOR_RGB hitColorShading[RAYPACKET_RAYS_PER_PACKET];
999 
1000  for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
1001  {
1002  const SFVEC3F bhColorY = bgColor[i / RAYPACKET_DIM];
1003 
1004  if( hitPacket[i].m_hitresult == true )
1005  {
1006  const SFVEC3F hitColor = shadeHit( bhColorY, blockPacket.m_ray[i],
1007  hitPacket[i].m_HitInfo, false,
1008  0, false );
1009 
1010  hitColorShading[i] = COLOR_RGB( hitColor );
1011  }
1012  else
1013  hitColorShading[i] = bhColorY;
1014  }
1015 
1016  COLOR_RGB cLRB_old[(RAYPACKET_DIM - 1)];
1017 
1018  for( unsigned int y = 0; y < (RAYPACKET_DIM - 1); ++y )
1019  {
1020  const SFVEC3F bgColorY = bgColor[y];
1021  const COLOR_RGB bgColorYRGB = COLOR_RGB( bgColorY );
1022 
1023  // This stores cRTB from the last block to be reused next time in a cLTB pixel
1024  COLOR_RGB cRTB_old;
1025 
1026  //RAY cRTB_ray;
1027  //HITINFO cRTB_hitInfo;
1028 
1029  for( unsigned int x = 0; x < ( RAYPACKET_DIM - 1 ); ++x )
1030  {
1031  // pxl 0 pxl 1 pxl 2 pxl 3 pxl 4
1032  // x0 x1 ...
1033  // .---------------------------.
1034  // y0 | cLT | cxxx | cLRT | cxxx | cRT |
1035  // | cxxx | cLTC | cxxx | cRTC | cxxx |
1036  // | cLTB | cxxx | cC | cxxx | cRTB |
1037  // | cxxx | cLBC | cxxx | cRBC | cxxx |
1038  // '---------------------------'
1039  // y1 | cLB | cxxx | cLRB | cxxx | cRB |
1040 
1041  const unsigned int iLT = ( ( x + 0 ) + RAYPACKET_DIM * ( y + 0 ) );
1042  const unsigned int iRT = ( ( x + 1 ) + RAYPACKET_DIM * ( y + 0 ) );
1043  const unsigned int iLB = ( ( x + 0 ) + RAYPACKET_DIM * ( y + 1 ) );
1044  const unsigned int iRB = ( ( x + 1 ) + RAYPACKET_DIM * ( y + 1 ) );
1045 
1046  // !TODO: skip when there are no hits
1047  const COLOR_RGB& cLT = hitColorShading[ iLT ];
1048  const COLOR_RGB& cRT = hitColorShading[ iRT ];
1049  const COLOR_RGB& cLB = hitColorShading[ iLB ];
1050  const COLOR_RGB& cRB = hitColorShading[ iRB ];
1051 
1052  // Trace and shade cC
1053  COLOR_RGB cC = bgColorYRGB;
1054 
1055  const SFVEC3F& oriLT = blockPacket.m_ray[ iLT ].m_Origin;
1056  const SFVEC3F& oriRB = blockPacket.m_ray[ iRB ].m_Origin;
1057 
1058  const SFVEC3F& dirLT = blockPacket.m_ray[ iLT ].m_Dir;
1059  const SFVEC3F& dirRB = blockPacket.m_ray[ iRB ].m_Dir;
1060 
1061  SFVEC3F oriC;
1062  SFVEC3F dirC;
1063 
1064  HITINFO centerHitInfo;
1065  centerHitInfo.m_tHit = std::numeric_limits<float>::infinity();
1066 
1067  bool hittedC = false;
1068 
1069  if( ( hitPacket[iLT].m_hitresult == true )
1070  || ( hitPacket[iRT].m_hitresult == true )
1071  || ( hitPacket[iLB].m_hitresult == true )
1072  || ( hitPacket[iRB].m_hitresult == true ) )
1073  {
1074  oriC = ( oriLT + oriRB ) * 0.5f;
1075  dirC = glm::normalize( ( dirLT + dirRB ) * 0.5f );
1076 
1077  // Trace the center ray
1078  RAY centerRay;
1079  centerRay.Init( oriC, dirC );
1080 
1081  const unsigned int nodeLT = hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
1082  const unsigned int nodeRT = hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
1083  const unsigned int nodeLB = hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
1084  const unsigned int nodeRB = hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
1085 
1086  if( nodeLT != 0 )
1087  hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
1088  nodeLT );
1089 
1090  if( ( nodeRT != 0 ) && ( nodeRT != nodeLT ) )
1091  hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
1092  nodeRT );
1093 
1094  if( ( nodeLB != 0 ) && ( nodeLB != nodeLT ) && ( nodeLB != nodeRT ) )
1095  hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
1096  nodeLB );
1097 
1098  if( ( nodeRB != 0 ) && ( nodeRB != nodeLB ) && ( nodeRB != nodeLT )
1099  && ( nodeRB != nodeRT ) )
1100  hittedC |= m_accelerator->Intersect( centerRay, centerHitInfo,
1101  nodeRB );
1102 
1103  if( hittedC )
1104  {
1105  cC = COLOR_RGB( shadeHit( bgColorY, centerRay, centerHitInfo,
1106  false, 0, false ) );
1107  }
1108  else
1109  {
1110  centerHitInfo.m_tHit = std::numeric_limits<float>::infinity();
1111  hittedC = m_accelerator->Intersect( centerRay, centerHitInfo );
1112 
1113  if( hittedC )
1114  cC = COLOR_RGB( shadeHit( bgColorY, centerRay, centerHitInfo,
1115  false, 0, false ) );
1116  }
1117  }
1118 
1119  // Trace and shade cLRT
1120  COLOR_RGB cLRT = bgColorYRGB;
1121 
1122  const SFVEC3F& oriRT = blockPacket.m_ray[ iRT ].m_Origin;
1123  const SFVEC3F& dirRT = blockPacket.m_ray[ iRT ].m_Dir;
1124 
1125  if( y == 0 )
1126  {
1127  // Trace the center ray
1128  RAY rayLRT;
1129  rayLRT.Init( ( oriLT + oriRT ) * 0.5f,
1130  glm::normalize( ( dirLT + dirRT ) * 0.5f ) );
1131 
1132  HITINFO hitInfoLRT;
1133  hitInfoLRT.m_tHit = std::numeric_limits<float>::infinity();
1134 
1135  if( hitPacket[iLT].m_hitresult && hitPacket[iRT].m_hitresult
1136  && ( hitPacket[iLT].m_HitInfo.pHitObject
1137  == hitPacket[iRT].m_HitInfo.pHitObject ) )
1138  {
1139  hitInfoLRT.pHitObject = hitPacket[ iLT ].m_HitInfo.pHitObject;
1140  hitInfoLRT.m_tHit = ( hitPacket[ iLT ].m_HitInfo.m_tHit +
1141  hitPacket[ iRT ].m_HitInfo.m_tHit ) * 0.5f;
1142  hitInfoLRT.m_HitNormal =
1143  glm::normalize( ( hitPacket[ iLT ].m_HitInfo.m_HitNormal +
1144  hitPacket[ iRT ].m_HitInfo.m_HitNormal ) * 0.5f );
1145 
1146  cLRT = COLOR_RGB( shadeHit( bgColorY, rayLRT, hitInfoLRT, false,
1147  0, false ) );
1148  cLRT = BlendColor( cLRT, BlendColor( cLT, cRT ) );
1149  }
1150  else
1151  {
1152  // If any hits
1153  if( hitPacket[ iLT ].m_hitresult || hitPacket[ iRT ].m_hitresult )
1154  {
1155  const unsigned int nodeLT =
1156  hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
1157  const unsigned int nodeRT =
1158  hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
1159 
1160  bool hittedLRT = false;
1161 
1162  if( nodeLT != 0 )
1163  hittedLRT |= m_accelerator->Intersect( rayLRT, hitInfoLRT,
1164  nodeLT );
1165 
1166  if( ( nodeRT != 0 ) && ( nodeRT != nodeLT ) )
1167  hittedLRT |= m_accelerator->Intersect( rayLRT, hitInfoLRT,
1168  nodeRT );
1169 
1170  if( hittedLRT )
1171  cLRT = COLOR_RGB( shadeHit( bgColorY, rayLRT, hitInfoLRT,
1172  false, 0, false ) );
1173  else
1174  {
1175  hitInfoLRT.m_tHit = std::numeric_limits<float>::infinity();
1176 
1177  if( m_accelerator->Intersect( rayLRT,hitInfoLRT ) )
1178  cLRT = COLOR_RGB( shadeHit( bgColorY, rayLRT,
1179  hitInfoLRT, false,
1180  0, false ) );
1181  }
1182  }
1183  }
1184  }
1185  else
1186  {
1187  cLRT = cLRB_old[x];
1188  }
1189 
1190  // Trace and shade cLTB
1191  COLOR_RGB cLTB = bgColorYRGB;
1192 
1193  if( x == 0 )
1194  {
1195  const SFVEC3F &oriLB = blockPacket.m_ray[ iLB ].m_Origin;
1196  const SFVEC3F& dirLB = blockPacket.m_ray[ iLB ].m_Dir;
1197 
1198  // Trace the center ray
1199  RAY rayLTB;
1200  rayLTB.Init( ( oriLT + oriLB ) * 0.5f,
1201  glm::normalize( ( dirLT + dirLB ) * 0.5f ) );
1202 
1203  HITINFO hitInfoLTB;
1204  hitInfoLTB.m_tHit = std::numeric_limits<float>::infinity();
1205 
1206  if( hitPacket[ iLT ].m_hitresult && hitPacket[ iLB ].m_hitresult
1207  && ( hitPacket[ iLT ].m_HitInfo.pHitObject ==
1208  hitPacket[ iLB ].m_HitInfo.pHitObject ) )
1209  {
1210  hitInfoLTB.pHitObject = hitPacket[ iLT ].m_HitInfo.pHitObject;
1211  hitInfoLTB.m_tHit = ( hitPacket[ iLT ].m_HitInfo.m_tHit +
1212  hitPacket[ iLB ].m_HitInfo.m_tHit ) * 0.5f;
1213  hitInfoLTB.m_HitNormal =
1214  glm::normalize( ( hitPacket[ iLT ].m_HitInfo.m_HitNormal +
1215  hitPacket[ iLB ].m_HitInfo.m_HitNormal ) * 0.5f );
1216  cLTB = COLOR_RGB( shadeHit( bgColorY, rayLTB, hitInfoLTB, false,
1217  0, false ) );
1218  cLTB = BlendColor( cLTB, BlendColor( cLT, cLB) );
1219  }
1220  else
1221  {
1222  // If any hits
1223  if( hitPacket[ iLT ].m_hitresult || hitPacket[ iLB ].m_hitresult )
1224  {
1225  const unsigned int nodeLT =
1226  hitPacket[ iLT ].m_HitInfo.m_acc_node_info;
1227  const unsigned int nodeLB =
1228  hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
1229 
1230  bool hittedLTB = false;
1231 
1232  if( nodeLT != 0 )
1233  hittedLTB |= m_accelerator->Intersect( rayLTB, hitInfoLTB,
1234  nodeLT );
1235 
1236  if( ( nodeLB != 0 ) && ( nodeLB != nodeLT ) )
1237  hittedLTB |= m_accelerator->Intersect( rayLTB, hitInfoLTB,
1238  nodeLB );
1239 
1240  if( hittedLTB )
1241  cLTB = COLOR_RGB( shadeHit( bgColorY, rayLTB, hitInfoLTB,
1242  false, 0, false ) );
1243  else
1244  {
1245  hitInfoLTB.m_tHit = std::numeric_limits<float>::infinity();
1246 
1247  if( m_accelerator->Intersect( rayLTB, hitInfoLTB ) )
1248  cLTB = COLOR_RGB( shadeHit( bgColorY, rayLTB,
1249  hitInfoLTB, false,
1250  0, false ) );
1251  }
1252  }
1253  }
1254  }
1255  else
1256  {
1257  cLTB = cRTB_old;
1258  }
1259 
1260  // Trace and shade cRTB
1261  COLOR_RGB cRTB = bgColorYRGB;
1262 
1263  // Trace the center ray
1264  RAY rayRTB;
1265  rayRTB.Init( ( oriRT + oriRB ) * 0.5f,
1266  glm::normalize( ( dirRT + dirRB ) * 0.5f ) );
1267 
1268  HITINFO hitInfoRTB;
1269  hitInfoRTB.m_tHit = std::numeric_limits<float>::infinity();
1270 
1271  if( hitPacket[ iRT ].m_hitresult && hitPacket[ iRB ].m_hitresult
1272  && ( hitPacket[ iRT ].m_HitInfo.pHitObject ==
1273  hitPacket[ iRB ].m_HitInfo.pHitObject ) )
1274  {
1275  hitInfoRTB.pHitObject = hitPacket[ iRT ].m_HitInfo.pHitObject;
1276 
1277  hitInfoRTB.m_tHit = ( hitPacket[ iRT ].m_HitInfo.m_tHit +
1278  hitPacket[ iRB ].m_HitInfo.m_tHit ) * 0.5f;
1279 
1280  hitInfoRTB.m_HitNormal =
1281  glm::normalize( ( hitPacket[ iRT ].m_HitInfo.m_HitNormal +
1282  hitPacket[ iRB ].m_HitInfo.m_HitNormal ) * 0.5f );
1283 
1284  cRTB = COLOR_RGB( shadeHit( bgColorY, rayRTB, hitInfoRTB, false, 0,
1285  false ) );
1286  cRTB = BlendColor( cRTB, BlendColor( cRT, cRB ) );
1287  }
1288  else
1289  {
1290  // If any hits
1291  if( hitPacket[ iRT ].m_hitresult || hitPacket[ iRB ].m_hitresult )
1292  {
1293  const unsigned int nodeRT =
1294  hitPacket[ iRT ].m_HitInfo.m_acc_node_info;
1295  const unsigned int nodeRB =
1296  hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
1297 
1298  bool hittedRTB = false;
1299 
1300  if( nodeRT != 0 )
1301  hittedRTB |= m_accelerator->Intersect( rayRTB, hitInfoRTB,
1302  nodeRT );
1303 
1304  if( ( nodeRB != 0 ) && ( nodeRB != nodeRT ) )
1305  hittedRTB |= m_accelerator->Intersect( rayRTB, hitInfoRTB,
1306  nodeRB );
1307 
1308  if( hittedRTB )
1309  {
1310  cRTB = COLOR_RGB( shadeHit( bgColorY, rayRTB, hitInfoRTB,
1311  false, 0, false) );
1312  }
1313  else
1314  {
1315  hitInfoRTB.m_tHit = std::numeric_limits<float>::infinity();
1316 
1317  if( m_accelerator->Intersect( rayRTB, hitInfoRTB ) )
1318  cRTB = COLOR_RGB( shadeHit( bgColorY, rayRTB, hitInfoRTB,
1319  false, 0, false ) );
1320  }
1321  }
1322  }
1323 
1324  cRTB_old = cRTB;
1325 
1326  // Trace and shade cLRB
1327  COLOR_RGB cLRB = bgColorYRGB;
1328 
1329  const SFVEC3F& oriLB = blockPacket.m_ray[ iLB ].m_Origin;
1330  const SFVEC3F& dirLB = blockPacket.m_ray[ iLB ].m_Dir;
1331 
1332  // Trace the center ray
1333  RAY rayLRB;
1334  rayLRB.Init( ( oriLB + oriRB ) * 0.5f,
1335  glm::normalize( ( dirLB + dirRB ) * 0.5f ) );
1336 
1337  HITINFO hitInfoLRB;
1338  hitInfoLRB.m_tHit = std::numeric_limits<float>::infinity();
1339 
1340  if( hitPacket[iLB].m_hitresult && hitPacket[iRB].m_hitresult
1341  && ( hitPacket[iLB].m_HitInfo.pHitObject ==
1342  hitPacket[iRB].m_HitInfo.pHitObject ) )
1343  {
1344  hitInfoLRB.pHitObject = hitPacket[ iLB ].m_HitInfo.pHitObject;
1345 
1346  hitInfoLRB.m_tHit = ( hitPacket[ iLB ].m_HitInfo.m_tHit +
1347  hitPacket[ iRB ].m_HitInfo.m_tHit ) * 0.5f;
1348 
1349  hitInfoLRB.m_HitNormal =
1350  glm::normalize( ( hitPacket[ iLB ].m_HitInfo.m_HitNormal +
1351  hitPacket[ iRB ].m_HitInfo.m_HitNormal ) * 0.5f );
1352 
1353  cLRB = COLOR_RGB( shadeHit( bgColorY, rayLRB, hitInfoLRB, false, 0,
1354  false ) );
1355  cLRB = BlendColor( cLRB, BlendColor( cLB, cRB ) );
1356  }
1357  else
1358  {
1359  // If any hits
1360  if( hitPacket[ iLB ].m_hitresult || hitPacket[ iRB ].m_hitresult )
1361  {
1362  const unsigned int nodeLB =
1363  hitPacket[ iLB ].m_HitInfo.m_acc_node_info;
1364  const unsigned int nodeRB =
1365  hitPacket[ iRB ].m_HitInfo.m_acc_node_info;
1366 
1367  bool hittedLRB = false;
1368 
1369  if( nodeLB != 0 )
1370  hittedLRB |= m_accelerator->Intersect( rayLRB, hitInfoLRB,
1371  nodeLB );
1372 
1373  if( ( nodeRB != 0 ) && ( nodeRB != nodeLB ) )
1374  hittedLRB |= m_accelerator->Intersect( rayLRB, hitInfoLRB,
1375  nodeRB );
1376 
1377  if( hittedLRB )
1378  {
1379  cLRB = COLOR_RGB( shadeHit( bgColorY, rayLRB, hitInfoLRB,
1380  false, 0, false ) );
1381  }
1382  else
1383  {
1384  hitInfoLRB.m_tHit = std::numeric_limits<float>::infinity();
1385 
1386  if( m_accelerator->Intersect( rayLRB, hitInfoLRB ) )
1387  cLRB = COLOR_RGB( shadeHit( bgColorY, rayLRB, hitInfoLRB,
1388  false, 0, false ) );
1389  }
1390  }
1391  }
1392 
1393  cLRB_old[x] = cLRB;
1394 
1395  // Trace and shade cLTC
1396  COLOR_RGB cLTC = BlendColor( cLT , cC );
1397 
1398  if( hitPacket[ iLT ].m_hitresult || hittedC )
1399  {
1400  // Trace the center ray
1401  RAY rayLTC;
1402  rayLTC.Init( ( oriLT + oriC ) * 0.5f,
1403  glm::normalize( ( dirLT + dirC ) * 0.5f ) );
1404 
1405  HITINFO hitInfoLTC;
1406  hitInfoLTC.m_tHit = std::numeric_limits<float>::infinity();
1407 
1408  bool hitted = false;
1409 
1410  if( hittedC )
1411  hitted = centerHitInfo.pHitObject->Intersect( rayLTC, hitInfoLTC );
1412  else if( hitPacket[ iLT ].m_hitresult )
1413  hitted = hitPacket[ iLT ].m_HitInfo.pHitObject->Intersect(
1414  rayLTC,
1415  hitInfoLTC );
1416 
1417  if( hitted )
1418  cLTC = COLOR_RGB( shadeHit( bgColorY, rayLTC, hitInfoLTC, false,
1419  0, false ) );
1420  }
1421 
1422  // Trace and shade cRTC
1423  COLOR_RGB cRTC = BlendColor( cRT , cC );
1424 
1425  if( hitPacket[ iRT ].m_hitresult || hittedC )
1426  {
1427  // Trace the center ray
1428  RAY rayRTC;
1429  rayRTC.Init( ( oriRT + oriC ) * 0.5f,
1430  glm::normalize( ( dirRT + dirC ) * 0.5f ) );
1431 
1432  HITINFO hitInfoRTC;
1433  hitInfoRTC.m_tHit = std::numeric_limits<float>::infinity();
1434 
1435  bool hitted = false;
1436 
1437  if( hittedC )
1438  hitted = centerHitInfo.pHitObject->Intersect( rayRTC, hitInfoRTC );
1439  else if( hitPacket[ iRT ].m_hitresult )
1440  hitted = hitPacket[ iRT ].m_HitInfo.pHitObject->Intersect( rayRTC,
1441  hitInfoRTC );
1442 
1443  if( hitted )
1444  cRTC = COLOR_RGB( shadeHit( bgColorY, rayRTC, hitInfoRTC, false,
1445  0, false ) );
1446  }
1447 
1448  // Trace and shade cLBC
1449  COLOR_RGB cLBC = BlendColor( cLB , cC );
1450 
1451  if( hitPacket[ iLB ].m_hitresult || hittedC )
1452  {
1453  // Trace the center ray
1454  RAY rayLBC;
1455  rayLBC.Init( ( oriLB + oriC ) * 0.5f,
1456  glm::normalize( ( dirLB + dirC ) * 0.5f ) );
1457 
1458  HITINFO hitInfoLBC;
1459  hitInfoLBC.m_tHit = std::numeric_limits<float>::infinity();
1460 
1461  bool hitted = false;
1462 
1463  if( hittedC )
1464  hitted = centerHitInfo.pHitObject->Intersect( rayLBC, hitInfoLBC );
1465  else if( hitPacket[ iLB ].m_hitresult )
1466  hitted = hitPacket[ iLB ].m_HitInfo.pHitObject->Intersect( rayLBC,
1467  hitInfoLBC );
1468 
1469  if( hitted )
1470  cLBC = COLOR_RGB( shadeHit( bgColorY, rayLBC, hitInfoLBC, false,
1471  0, false ) );
1472  }
1473 
1474  // Trace and shade cRBC
1475  COLOR_RGB cRBC = BlendColor( cRB , cC );
1476 
1477  if( hitPacket[ iRB ].m_hitresult || hittedC )
1478  {
1479  // Trace the center ray
1480  RAY rayRBC;
1481  rayRBC.Init( ( oriRB + oriC ) * 0.5f,
1482  glm::normalize( ( dirRB + dirC ) * 0.5f ) );
1483 
1484  HITINFO hitInfoRBC;
1485  hitInfoRBC.m_tHit = std::numeric_limits<float>::infinity();
1486 
1487  bool hitted = false;
1488 
1489  if( hittedC )
1490  hitted = centerHitInfo.pHitObject->Intersect( rayRBC, hitInfoRBC );
1491  else if( hitPacket[ iRB ].m_hitresult )
1492  hitted = hitPacket[ iRB ].m_HitInfo.pHitObject->Intersect( rayRBC,
1493  hitInfoRBC );
1494 
1495  if( hitted )
1496  cRBC = COLOR_RGB( shadeHit( bgColorY, rayRBC, hitInfoRBC, false,
1497  0, false ) );
1498  }
1499 
1500  // Set pixel colors
1501  GLubyte* ptr =
1502  &ptrPBO[( 4 * x + m_blockPositionsFast[iBlock].x
1503  + m_realBufferSize.x
1504  * ( m_blockPositionsFast[iBlock].y + 4 * y ) ) * 4];
1505  SetPixel( ptr + 0, cLT );
1506  SetPixel( ptr + 4, BlendColor( cLT, cLRT, cLTC ) );
1507  SetPixel( ptr + 8, cLRT );
1508  SetPixel( ptr + 12, BlendColor( cLRT, cRT, cRTC ) );
1509 
1510  ptr += m_realBufferSize.x * 4;
1511  SetPixel( ptr + 0, BlendColor( cLT , cLTB, cLTC ) );
1512  SetPixel( ptr + 4, BlendColor( cLTC, BlendColor( cLT , cC ) ) );
1513  SetPixel( ptr + 8, BlendColor( cC, BlendColor( cLRT, cLTC, cRTC ) ) );
1514  SetPixel( ptr + 12, BlendColor( cRTC, BlendColor( cRT , cC ) ) );
1515 
1516  ptr += m_realBufferSize.x * 4;
1517  SetPixel( ptr + 0, cLTB );
1518  SetPixel( ptr + 4, BlendColor( cC, BlendColor( cLTB, cLTC, cLBC ) ) );
1519  SetPixel( ptr + 8, cC );
1520  SetPixel( ptr + 12, BlendColor( cC, BlendColor( cRTB, cRTC, cRBC ) ) );
1521 
1522  ptr += m_realBufferSize.x * 4;
1523  SetPixel( ptr + 0, BlendColor( cLB , cLTB, cLBC ) );
1524  SetPixel( ptr + 4, BlendColor( cLBC, BlendColor( cLB , cC ) ) );
1525  SetPixel( ptr + 8, BlendColor( cC, BlendColor( cLRB, cLBC, cRBC ) ) );
1526  SetPixel( ptr + 12, BlendColor( cRBC, BlendColor( cRB , cC ) ) );
1527  }
1528  }
1529  }
1530 
1531  threadsFinished++;
1532  } );
1533 
1534  t.detach();
1535  }
1536 
1537  while( threadsFinished < parallelThreadCount )
1538  std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
1539 }
#define RAYPACKET_DIM
Definition: raypacket.h:32
BOARD_ADAPTER & m_boardAdapter
SFVEC3F shadeHit(const SFVEC3F &aBgColor, const RAY &aRay, HITINFO &aHitInfo, bool aIsInsideObject, unsigned int aRecursiveLevel, bool is_testShadow) const
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
void Init(const SFVEC3F &o, const SFVEC3F &d)
Definition: ray.cpp:35
Definition: ray.h:62
glm::ivec2 SFVEC2I
Definition: xv3d_types.h:39
float m_tHit
( 4) distance
Definition: hitinfo.h:38
std::vector< SFVEC2UI > m_blockPositions
Flag if a position was already processed (cleared each new render).
std::vector< SFVEC2UI > m_blockPositionsFast
COLOR_RGB BlendColor(const COLOR_RGB &aC1, const COLOR_RGB &aC2)
Definition: color_rgb.cpp:41
glm::uvec2 SFVEC2UI
Definition: xv3d_types.h:38
SFVEC4F m_BgColorTop
background top color
SFVEC4F m_BgColorBot
background bottom color
HITINFO m_HitInfo
Definition: hitinfo.h:58
const OBJECT_3D * pHitObject
( 4) Object that was hitted
Definition: hitinfo.h:40
static void SetPixel(GLubyte *p, const COLOR_RGB &v)
Stores the hit information of a ray with a point on the surface of a object.
Definition: hitinfo.h:35
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
#define RAYPACKET_RAYS_PER_PACKET
Definition: raypacket.h:35
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
CAMERA & m_camera
Flag if the opengl specific for this render was already initialized.
SFVEC3F m_HitNormal
(12) normal at the hit point
Definition: hitinfo.h:37
ACCELERATOR_3D * m_accelerator

References BlendColor(), RAY::Init(), ACCELERATOR_3D::Intersect(), OBJECT_3D::Intersect(), m_accelerator, BOARD_ADAPTER::m_BgColorBot, BOARD_ADAPTER::m_BgColorTop, m_blockPositions, m_blockPositionsFast, RENDER_3D_BASE::m_boardAdapter, RENDER_3D_BASE::m_camera, RAY::m_Dir, HITINFO_PACKET::m_HitInfo, HITINFO::m_HitNormal, m_isPreview, RAY::m_Origin, RAYPACKET::m_ray, m_realBufferSize, HITINFO::m_tHit, RENDER_3D_BASE::m_windowSize, m_xoffset, m_yoffset, HITINFO::pHitObject, RAYPACKET_DIM, RAYPACKET_RAYS_PER_PACKET, SetPixel(), and shadeHit().

Referenced by Redraw().

◆ renderRayPackets()

void RENDER_3D_RAYTRACE::renderRayPackets ( const SFVEC3F bgColorY,
const RAY aRayPkt,
HITINFO_PACKET aHitPacket,
bool  is_testShadow,
SFVEC3F aOutHitColor 
)
private

Definition at line 480 of file render_3d_raytrace.cpp.

483 {
484  for( unsigned int y = 0, i = 0; y < RAYPACKET_DIM; ++y )
485  {
486  for( unsigned int x = 0; x < RAYPACKET_DIM; ++x, ++i )
487  {
488  if( aHitPacket[i].m_hitresult == true )
489  {
490  aOutHitColor[i] = shadeHit( bgColorY[y], aRayPkt[i], aHitPacket[i].m_HitInfo,
491  false, 0, is_testShadow );
492  }
493  else
494  {
495  aOutHitColor[i] = bgColorY[y];
496  }
497  }
498  }
499 }
#define RAYPACKET_DIM
Definition: raypacket.h:32
SFVEC3F shadeHit(const SFVEC3F &aBgColor, const RAY &aRay, HITINFO &aHitInfo, bool aIsInsideObject, unsigned int aRecursiveLevel, bool is_testShadow) const

References RAYPACKET_DIM, and shadeHit().

Referenced by renderBlockTracing().

◆ renderTracing()

void RENDER_3D_RAYTRACE::renderTracing ( GLubyte *  ptrPBO,
REPORTER aStatusReporter 
)
private

Definition at line 345 of file render_3d_raytrace.cpp.

346 {
347  m_isPreview = false;
348 
349  auto startTime = std::chrono::steady_clock::now();
350  bool breakLoop = false;
351 
352  std::atomic<size_t> numBlocksRendered( 0 );
353  std::atomic<size_t> currentBlock( 0 );
354  std::atomic<size_t> threadsFinished( 0 );
355 
356  size_t parallelThreadCount = std::min<size_t>(
357  std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
358  m_blockPositions.size() );
359 
360  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
361  {
362  std::thread t = std::thread( [&]()
363  {
364  for( size_t iBlock = currentBlock.fetch_add( 1 );
365  iBlock < m_blockPositions.size() && !breakLoop;
366  iBlock = currentBlock.fetch_add( 1 ) )
367  {
368  if( !m_blockPositionsWasProcessed[iBlock] )
369  {
370  renderBlockTracing( ptrPBO, iBlock );
371  numBlocksRendered++;
372  m_blockPositionsWasProcessed[iBlock] = 1;
373 
374  // Check if it spend already some time render and request to exit
375  // to display the progress
376  if( std::chrono::duration_cast<std::chrono::milliseconds>(
377  std::chrono::steady_clock::now() - startTime ).count() > 150 )
378  breakLoop = true;
379  }
380  }
381 
382  threadsFinished++;
383  } );
384 
385  t.detach();
386  }
387 
388  while( threadsFinished < parallelThreadCount )
389  std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
390 
391  m_blockRenderProgressCount += numBlocksRendered;
392 
393  if( aStatusReporter )
394  aStatusReporter->Report( wxString::Format( _( "Rendering: %.0f %%" ),
395  (float) ( m_blockRenderProgressCount * 100 )
396  / (float) m_blockPositions.size() ) );
397 
398  // Check if it finish the rendering and if should continue to a post processing
399  // or mark it as finished
401  {
404  else
406  }
407 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
std::vector< int > m_blockPositionsWasProcessed
Encode the Morton code positions (on fast preview mode).
RT_RENDER_STATE m_renderState
State used on quality render.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
std::vector< SFVEC2UI > m_blockPositions
Flag if a position was already processed (cleared each new render).
void renderBlockTracing(GLubyte *ptrPBO, signed int iBlock)
size_t m_blockRenderProgressCount
Save the number of blocks progress of the render.
#define _(s)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200

References _, FL_RENDER_RAYTRACING_POST_PROCESSING, Format(), BOARD_ADAPTER::GetFlag(), m_blockPositions, m_blockPositionsWasProcessed, m_blockRenderProgressCount, RENDER_3D_BASE::m_boardAdapter, m_isPreview, m_renderState, renderBlockTracing(), REPORTER::Report(), RT_RENDER_STATE_FINISH, and RT_RENDER_STATE_POST_PROCESS_SHADE.

Referenced by render().

◆ restartRenderState()

void RENDER_3D_RAYTRACE::restartRenderState ( )
private

Definition at line 124 of file render_3d_raytrace.cpp.

125 {
127 
130 
132 
134 
135  // Mark the blocks not processed yet
136  std::fill( m_blockPositionsWasProcessed.begin(), m_blockPositionsWasProcessed.end(), 0 );
137 }
std::vector< int > m_blockPositionsWasProcessed
Encode the Morton code positions (on fast preview mode).
unsigned long int m_renderStartTime
Time that the render starts.
RT_RENDER_STATE m_renderState
State used on quality render.
std::vector< SFVEC2UI > m_blockPositions
Flag if a position was already processed (cleared each new render).
size_t m_blockRenderProgressCount
Save the number of blocks progress of the render.
void InitFrame()
Definition: post_shader.h:56
POST_SHADER_SSAO m_postShaderSsao
unsigned GetRunningMicroSecs()
An alternate way to calculate an elapset time (in microsecondes) to class PROF_COUNTER.

References GetRunningMicroSecs(), POST_SHADER::InitFrame(), m_blockPositions, m_blockPositionsWasProcessed, m_blockRenderProgressCount, m_postShaderSsao, m_renderStartTime, m_renderState, and RT_RENDER_STATE_TRACING.

Referenced by render().

◆ SetBusyIndicatorFactory()

void RENDER_3D_BASE::SetBusyIndicatorFactory ( BUSY_INDICATOR::FACTORY  aNewFactory)
inherited

Set a new busy indicator factory.

When set, this factory will be used to generate busy indicators when suitable. If not set, no busy indicator will be used.

Definition at line 64 of file render_3d_base.cpp.

65 {
66  m_busyIndicatorFactory = aNewFactory;
67 }
BUSY_INDICATOR::FACTORY m_busyIndicatorFactory
< Factory that returns a suitable busy indicator for the context.

References RENDER_3D_BASE::m_busyIndicatorFactory.

◆ SetCurWindowSize()

void RENDER_3D_RAYTRACE::SetCurWindowSize ( const wxSize &  aSize)
overridevirtual

Before each render, the canvas will tell the render what is the size of its windows, so render can take actions if it changed.

Parameters
aSizethe current size of the render window

Implements RENDER_3D_BASE.

Definition at line 112 of file render_3d_raytrace.cpp.

113 {
114  if( m_windowSize != aSize )
115  {
116  m_windowSize = aSize;
117  glViewport( 0, 0, m_windowSize.x, m_windowSize.y );
118 
120  }
121 }

References initializeNewWindowSize(), and RENDER_3D_BASE::m_windowSize.

◆ setupMaterials()

void RENDER_3D_RAYTRACE::setupMaterials ( )
private

Definition at line 71 of file raytracing/create_scene.cpp.

72 {
75 
78 
79  double mmTo3Dunits = IU_PER_MM * m_boardAdapter.BiuTo3dUnits();
80 
82  {
83  m_boardMaterial = BOARD_NORMAL( 0.40f * mmTo3Dunits );
84 
85  m_copperMaterial = COPPER_NORMAL( 4.0f * mmTo3Dunits, &m_boardMaterial );
86 
87  m_platedCopperMaterial = PLATED_COPPER_NORMAL( 0.5f * mmTo3Dunits );
88 
90 
91  m_plasticMaterial = PLASTIC_NORMAL( 0.05f * mmTo3Dunits );
92 
93  m_shinyPlasticMaterial = PLASTIC_SHINE_NORMAL( 0.1f * mmTo3Dunits );
94 
95  m_brushedMetalMaterial = BRUSHED_METAL_NORMAL( 0.05f * mmTo3Dunits );
96 
97  m_silkScreenMaterial = SILK_SCREEN_NORMAL( 0.25f * mmTo3Dunits );
98  }
99 
100  // http://devernay.free.fr/cours/opengl/materials.html
101  // Copper
102  const SFVEC3F copperSpecularLinear =
103  ConvertSRGBToLinear( glm::clamp( (SFVEC3F) m_boardAdapter.m_CopperColor * 0.5f + 0.25f,
104  SFVEC3F( 0.0f ), SFVEC3F( 1.0f ) ) );
105 
108  SFVEC3F( 0.0f ), copperSpecularLinear, 0.4f * 128.0f, 0.0f, 0.0f );
109 
111  m_materials.m_Copper.SetGenerator( &m_platedCopperMaterial );
112 
113  m_materials.m_NonPlatedCopper = BLINN_PHONG_MATERIAL(
114  ConvertSRGBToLinear( SFVEC3F( 0.191f, 0.073f, 0.022f ) ), SFVEC3F( 0.0f, 0.0f, 0.0f ),
115  SFVEC3F( 0.256f, 0.137f, 0.086f ), 0.15f * 128.0f, 0.0f, 0.0f );
116 
118  m_materials.m_NonPlatedCopper.SetGenerator( &m_copperMaterial );
119 
123  SFVEC3F( 0.0f, 0.0f, 0.0f ),
127  0.10f * 128.0f, 0.0f, 0.0f );
128 
130  SFVEC3F( 0.0f, 0.0f, 0.0f ),
131  glm::clamp( ( ( SFVEC3F )( 1.0f ) - ConvertSRGBToLinear(
133  SFVEC3F( 0.0f ), SFVEC3F( 0.10f ) ), 0.078125f * 128.0f, 0.0f, 0.0f );
134 
136  m_materials.m_SilkS.SetGenerator( &m_silkScreenMaterial );
137 
138  // Assume that SolderMaskTop == SolderMaskBot
139  const float solderMask_gray =
142  / 3.0f;
143 
144  const float solderMask_transparency = TransparencyControl( solderMask_gray,
146 
147  m_materials.m_SolderMask = BLINN_PHONG_MATERIAL(
149  SFVEC3F( 0.0f, 0.0f, 0.0f ),
150  SFVEC3F( glm::clamp( solderMask_gray * 2.0f, 0.25f, 1.0f ) ), 0.85f * 128.0f,
151  solderMask_transparency, 0.16f );
152 
153  m_materials.m_SolderMask.SetCastShadows( true );
154  m_materials.m_SolderMask.SetRefractionRayCount( 1 );
155 
157  m_materials.m_SolderMask.SetGenerator( &m_solderMaskMaterial );
158 
159  m_materials.m_EpoxyBoard =
160  BLINN_PHONG_MATERIAL( ConvertSRGBToLinear( SFVEC3F( 16.0f / 255.0f, 14.0f / 255.0f,
161  10.0f / 255.0f ) ),
162  SFVEC3F( 0.0f, 0.0f, 0.0f ),
163  ConvertSRGBToLinear( SFVEC3F( 10.0f / 255.0f, 8.0f / 255.0f,
164  10.0f / 255.0f ) ),
165  0.1f * 128.0f, 1.0f - m_boardAdapter.m_BoardBodyColor.a, 0.0f );
166 
167  m_materials.m_EpoxyBoard.SetAbsorvance( 10.0f );
168 
170  m_materials.m_EpoxyBoard.SetGenerator( &m_boardMaterial );
171 
173 
174  m_materials.m_Floor = BLINN_PHONG_MATERIAL( bgTop * 0.125f, SFVEC3F( 0.0f, 0.0f, 0.0f ),
175  ( SFVEC3F( 1.0f ) - bgTop ) / 3.0f,
176  0.10f * 128.0f, 0.0f, 0.50f );
177  m_materials.m_Floor.SetCastShadows( false );
178  m_materials.m_Floor.SetReflectionRecursionCount( 1 );
179 }
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
Procedural generation of the copper normals.
Definition: material.h:75
SOLDER_MASK_NORMAL m_solderMaskMaterial
static void SetDefaultReflectionRecursionCount(unsigned int aCount)
Definition: material.h:257
static void SetDefaultRefractionRecursionCount(unsigned int aCount)
Definition: material.h:252
COPPER_NORMAL m_copperMaterial
static constexpr double IU_PER_MM
Mock up a conversion function.
PLATED_COPPER_NORMAL m_platedCopperMaterial
SFVEC4F m_SolderMaskColorTop
in realistic mode: solder mask color ( top )
SFVEC4F m_BoardBodyColor
in realistic mode: FR4 board color
SFVEC4F m_SolderPasteColor
in realistic mode: solder paste color
Procedural generation of the plastic normals.
Definition: material.h:145
static float TransparencyControl(float aGrayColorValue, float aTransparency)
Perform an interpolation step to easy control the transparency based on the gray color value and tran...
Blinn Phong based material https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model.
Definition: material.h:378
static void SetDefaultReflectionRayCount(unsigned int aCount)
Definition: material.h:247
int m_RtRecursiveReflectionCount
SFVEC4F m_BgColorTop
background top color
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
int m_RtRecursiveRefractionCount
int m_RtRefractionSampleCount
BRUSHED_METAL_NORMAL m_brushedMetalMaterial
PLASTIC_SHINE_NORMAL m_shinyPlasticMaterial
Procedural generation of the shiny brushed metal.
Definition: material.h:194
BOARD_NORMAL m_boardMaterial
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
SFVEC4F m_CopperColor
in realistic mode: copper color
Procedural generation of the shiny plastic normals.
Definition: material.h:169
SFVEC4F m_SilkScreenColorTop
in realistic mode: SilkScreen color ( top )
static void SetDefaultRefractionRayCount(unsigned int aCount)
Definition: material.h:242
Procedural generation of the solder mask.
Definition: material.h:125
PLASTIC_NORMAL m_plasticMaterial
SFVEC3F ConvertSRGBToLinear(const SFVEC3F &aSRGBcolor)
int m_RtReflectionSampleCount
struct RENDER_3D_RAYTRACE::@5 m_materials
SILK_SCREEN_NORMAL m_silkScreenMaterial

References BOARD_ADAPTER::BiuTo3dUnits(), ConvertSRGBToLinear(), FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES, BOARD_ADAPTER::GetFlag(), IU_PER_MM, BOARD_ADAPTER::m_BgColorTop, RENDER_3D_BASE::m_boardAdapter, BOARD_ADAPTER::m_BoardBodyColor, m_boardMaterial, m_brushedMetalMaterial, BOARD_ADAPTER::m_CopperColor, m_copperMaterial, m_materials, m_plasticMaterial, m_platedCopperMaterial, BOARD_ADAPTER::m_RtRecursiveReflectionCount, BOARD_ADAPTER::m_RtRecursiveRefractionCount, BOARD_ADAPTER::m_RtReflectionSampleCount, BOARD_ADAPTER::m_RtRefractionSampleCount, m_shinyPlasticMaterial, BOARD_ADAPTER::m_SilkScreenColorTop, m_silkScreenMaterial, BOARD_ADAPTER::m_SolderMaskColorTop, m_solderMaskMaterial, BOARD_ADAPTER::m_SolderPasteColor, MATERIAL::SetDefaultReflectionRayCount(), MATERIAL::SetDefaultReflectionRecursionCount(), MATERIAL::SetDefaultRefractionRayCount(), MATERIAL::SetDefaultRefractionRecursionCount(), and TransparencyControl().

Referenced by Reload().

◆ shadeHit()

SFVEC3F RENDER_3D_RAYTRACE::shadeHit ( const SFVEC3F aBgColor,
const RAY aRay,
HITINFO aHitInfo,
bool  aIsInsideObject,
unsigned int  aRecursiveLevel,
bool  is_testShadow 
) const
private

Definition at line 1544 of file render_3d_raytrace.cpp.

1547 {
1548  const MATERIAL* objMaterial = aHitInfo.pHitObject->GetMaterial();
1549  wxASSERT( objMaterial != nullptr );
1550 
1551  SFVEC3F outColor = objMaterial->GetEmissiveColor() + objMaterial->GetAmbientColor();
1552 
1553  if( aRecursiveLevel > 7 )
1554  return outColor;
1555 
1556  SFVEC3F hitPoint = aHitInfo.m_HitPoint;
1557 
1558  hitPoint += aHitInfo.m_HitNormal * m_boardAdapter.GetNonCopperLayerThickness() * 0.6f;
1559 
1560  const SFVEC3F diffuseColorObj = aHitInfo.pHitObject->GetDiffuseColor( aHitInfo );
1561 
1562 #if USE_EXPERIMENTAL_SOFT_SHADOWS
1563  const bool is_aa_enabled = m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_ANTI_ALIASING ) &&
1564  (!m_isPreview);
1565 #endif
1566 
1567  float shadow_att_factor_sum = 0.0f;
1568 
1569  unsigned int nr_lights_that_can_cast_shadows = 0;
1570 
1571  for( const LIGHT* light : m_lights )
1572  {
1573  SFVEC3F vectorToLight;
1574  SFVEC3F colorOfLight;
1575  float distToLight;
1576 
1577  light->GetLightParameters( hitPoint, vectorToLight, colorOfLight, distToLight );
1578 
1579  if( m_isPreview )
1580  colorOfLight = SFVEC3F( 1.0f );
1581 
1582  const float NdotL = glm::dot( aHitInfo.m_HitNormal, vectorToLight );
1583 
1584  // Only calc shade if the normal is facing the direction of light,
1585  // otherwise it is in the shadow
1586  if( NdotL >= FLT_EPSILON )
1587  {
1588  float shadow_att_factor_light = 1.0f;
1589 
1590  if( is_testShadow && light->GetCastShadows() )
1591  {
1592  nr_lights_that_can_cast_shadows++;
1593 #if USE_EXPERIMENTAL_SOFT_SHADOWS
1594  // For rays that are recursive, just calculate one hit shadow
1595  if( aRecursiveLevel > 0 )
1596  {
1597 #endif
1598  RAY rayToLight;
1599  rayToLight.Init( hitPoint, vectorToLight );
1600 
1601  // Test if point is not in the shadow.
1602  // Test for any hit from the point in the direction of light
1603  if( m_accelerator->IntersectP( rayToLight, distToLight ) )
1604  shadow_att_factor_light = 0.0f;
1605 
1606 #if USE_EXPERIMENTAL_SOFT_SHADOWS
1607  }
1608  else // Experimental softshadow calculation
1609  {
1610 
1611  const unsigned int shadow_number_of_samples =
1613  const float shadow_inc_factor = 1.0f / (float) ( shadow_number_of_samples );
1614 
1615  for( unsigned int i = 0; i < shadow_number_of_samples; ++i )
1616  {
1617  RAY rayToLight;
1618 
1619  if( i == 0 )
1620  {
1621  rayToLight.Init( hitPoint, vectorToLight );
1622  }
1623  else
1624  {
1625  const SFVEC3F unifVector = UniformRandomHemisphereDirection();
1626  const SFVEC3F disturbed_vector_to_light =
1627  glm::normalize( vectorToLight + unifVector *
1629 
1630  rayToLight.Init( hitPoint, disturbed_vector_to_light );
1631  }
1632 
1633  // !TODO: there are multiple ways that this tests can be
1634  // optimized. Eg: by packing rays or to test against the
1635  // latest hit object.
1636  if( m_accelerator->IntersectP( rayToLight, distToLight ) )
1637  {
1638  shadow_att_factor_light -= shadow_inc_factor;
1639  }
1640  }
1641  }
1642 #endif
1643  shadow_att_factor_sum += shadow_att_factor_light;
1644  }
1645 
1646  outColor += objMaterial->Shade( aRay, aHitInfo, NdotL, diffuseColorObj, vectorToLight,
1647  colorOfLight, shadow_att_factor_light );
1648  }
1649 
1650  // Only use the headlight for preview
1651  if( m_isPreview )
1652  break;
1653  }
1654 
1655  // Improvement: this is not taking in account the lightcolor
1656  if( nr_lights_that_can_cast_shadows > 0 )
1657  {
1658  aHitInfo.m_ShadowFactor = glm::max(
1659  shadow_att_factor_sum / (float) ( nr_lights_that_can_cast_shadows * 1.0f ), 0.0f );
1660  }
1661  else
1662  {
1663  aHitInfo.m_ShadowFactor = 1.0f;
1664  }
1665 
1666  // Clamp color to not be brighter than 1.0f
1667  outColor = glm::min( outColor, SFVEC3F( 1.0f ) );
1668 
1669  if( !m_isPreview )
1670  {
1671  // Reflections
1672  if( ( objMaterial->GetReflection() > 0.0f )
1674  && ( aRecursiveLevel < objMaterial->GetReflectionRecursionCount() ) )
1675  {
1676  const unsigned int reflection_number_of_samples =
1677  objMaterial->GetReflectionRayCount();
1678 
1679  SFVEC3F sum_color = SFVEC3F( 0.0f );
1680 
1681  const SFVEC3F reflectVector = aRay.m_Dir - 2.0f *
1682  glm::dot( aRay.m_Dir, aHitInfo.m_HitNormal ) * aHitInfo.m_HitNormal;
1683 
1684  for( unsigned int i = 0; i < reflection_number_of_samples; ++i )
1685  {
1686  RAY reflectedRay;
1687 
1688  if( i == 0 )
1689  {
1690  reflectedRay.Init( hitPoint, reflectVector );
1691  }
1692  else
1693  {
1694  // Apply some randomize to the reflected vector
1695  const SFVEC3F random_reflectVector =
1696  glm::normalize( reflectVector +
1699 
1700  reflectedRay.Init( hitPoint, random_reflectVector );
1701  }
1702 
1703  HITINFO reflectedHit;
1704  reflectedHit.m_tHit = std::numeric_limits<float>::infinity();
1705 
1706  if( m_accelerator->Intersect( reflectedRay, reflectedHit ) )
1707  {
1708  sum_color += ( diffuseColorObj + objMaterial->GetSpecularColor() ) *
1709  shadeHit( aBgColor, reflectedRay, reflectedHit, false,
1710  aRecursiveLevel + 1, is_testShadow ) *
1711  SFVEC3F( objMaterial->GetReflection() *
1712  // Falloff factor
1713  (1.0f / ( 1.0f + 0.75f * reflectedHit.m_tHit *
1714  reflectedHit.m_tHit) ) );
1715  }
1716  }
1717 
1718  outColor += (sum_color / SFVEC3F( (float)reflection_number_of_samples) );
1719  }
1720 
1721  // Refraction
1722  const float objTransparency = aHitInfo.pHitObject->GetModelTransparency();
1723 
1724  if( ( objTransparency > 0.0f ) && m_boardAdapter.GetFlag( FL_RENDER_RAYTRACING_REFRACTIONS )
1725  && ( aRecursiveLevel < objMaterial->GetRefractionRecursionCount() ) )
1726  {
1727  const float airIndex = 1.000293f;
1728  const float glassIndex = 1.49f;
1729  const float air_over_glass = airIndex / glassIndex;
1730  const float glass_over_air = glassIndex / airIndex;
1731 
1732  const float refractionRatio = aIsInsideObject?glass_over_air:air_over_glass;
1733 
1734  SFVEC3F refractedVector;
1735 
1736  if( Refract( aRay.m_Dir, aHitInfo.m_HitNormal, refractionRatio, refractedVector ) )
1737  {
1738  // This increase the start point by a "fixed" factor so it will work the
1739  // same for all distances
1740  const SFVEC3F startPoint =
1741  aRay.at( aHitInfo.m_tHit + m_boardAdapter.GetNonCopperLayerThickness() *
1742  0.25f );
1743 
1744  const unsigned int refractions_number_of_samples =
1745  objMaterial->GetRefractionRayCount();
1746 
1747  SFVEC3F sum_color = SFVEC3F(0.0f);
1748 
1749  for( unsigned int i = 0; i < refractions_number_of_samples; ++i )
1750  {
1751  RAY refractedRay;
1752 
1753  if( i == 0 )
1754  {
1755  refractedRay.Init( startPoint, refractedVector );
1756  }
1757  else
1758  {
1759  // apply some randomize to the refracted vector
1760  const SFVEC3F randomizeRefractedVector =
1761  glm::normalize( refractedVector +
1764 
1765  refractedRay.Init( startPoint, randomizeRefractedVector );
1766  }
1767 
1768  HITINFO refractedHit;
1769  refractedHit.m_tHit = std::numeric_limits<float>::infinity();
1770 
1771  SFVEC3F refractedColor = aBgColor;
1772 
1773  if( m_accelerator->Intersect( refractedRay, refractedHit ) )
1774  {
1775  refractedColor = shadeHit( aBgColor, refractedRay, refractedHit,
1776  !aIsInsideObject, aRecursiveLevel + 1, false );
1777 
1778  const SFVEC3F absorbance = ( SFVEC3F(1.0f) - diffuseColorObj ) *
1779  (1.0f - objTransparency ) *
1780  objMaterial->GetAbsorvance() *
1781  refractedHit.m_tHit;
1782 
1783  const SFVEC3F transparency = 1.0f / ( absorbance + 1.0f );
1784 
1785  sum_color += refractedColor * transparency;
1786  }
1787  else
1788  {
1789  sum_color += refractedColor;
1790  }
1791  }
1792 
1793  outColor = outColor * ( 1.0f - objTransparency ) + objTransparency * sum_color
1794  / SFVEC3F( (float) refractions_number_of_samples );
1795  }
1796  else
1797  {
1798  outColor = outColor * ( 1.0f - objTransparency ) + objTransparency * aBgColor;
1799  }
1800  }
1801  }
1802 
1803  return outColor;
1804 }
float m_ShadowFactor
( 4) Shadow attenuation (1.0 no shadow, 0.0f darkness)
Definition: hitinfo.h:45
bool GetFlag(DISPLAY3D_FLG aFlag) const
Get a configuration status of a flag.
BOARD_ADAPTER & m_boardAdapter
int m_RtShadowSampleCount
A base light class to derive to implement other light classes.
Definition: light.h:40
SFVEC3F shadeHit(const SFVEC3F &aBgColor, const RAY &aRay, HITINFO &aHitInfo, bool aIsInsideObject, unsigned int aRecursiveLevel, bool is_testShadow) const
const SFVEC3F & GetEmissiveColor() const
Definition: material.h:269
virtual bool IntersectP(const RAY &aRay, float aMaxDistance) const =0
void Init(const SFVEC3F &o, const SFVEC3F &d)
Definition: ray.cpp:35
float GetNonCopperLayerThickness() const noexcept
Get the current non copper layers thickness.
Definition: ray.h:62
float GetModelTransparency() const
Definition: object_3d.h:65
std::list< LIGHT * > m_lights
const SFVEC3F & GetSpecularColor() const
Definition: material.h:270
float m_RtSpreadRefractions
float m_tHit
( 4) distance
Definition: hitinfo.h:38
virtual SFVEC3F Shade(const RAY &aRay, const HITINFO &aHitInfo, float NdotL, const SFVEC3F &aDiffuseObjColor, const SFVEC3F &aDirToLight, const SFVEC3F &aLightColor, float aShadowAttenuationFactor) const =0
Shade an intersection point.
SFVEC3F at(float t) const
Definition: ray.h:84
bool Refract(const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRin_over_Rout, SFVEC3F &aOutVector)
Based on: https://github.com/mmp/pbrt-v3/blob/master/src/core/reflection.h See also: http://www....
Definition: 3d_math.h:112
Base material class that can be used to derive other material implementations.
Definition: material.h:239
SFVEC3F m_HitPoint
(12) hit position
Definition: hitinfo.h:44
float GetReflection() const
Definition: material.h:274
float m_RtSpreadReflections
unsigned int GetRefractionRayCount() const
Definition: material.h:276
const OBJECT_3D * pHitObject
( 4) Object that was hitted
Definition: hitinfo.h:40
SFVEC3F m_Dir
Definition: ray.h:67
SFVEC3F UniformRandomHemisphereDirection()
Definition: 3d_math.h:55
const SFVEC3F & GetAmbientColor() const
Definition: material.h:268
Stores the hit information of a ray with a point on the surface of a object.
Definition: hitinfo.h:35
unsigned int GetReflectionRayCount() const
Definition: material.h:277
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
virtual SFVEC3F GetDiffuseColor(const HITINFO &aHitInfo) const =0
SFVEC3F m_HitNormal
(12) normal at the hit point
Definition: hitinfo.h:37
float m_RtSpreadShadows
Defini