1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2020 Mario Luzeiro <mrluzeiro@ua.pt>
5  * Copyright (C) 2015-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
23  */
24 
25 #ifndef RENDER_3D_RAYTRACE_H
26 #define RENDER_3D_RAYTRACE_H
27 
28 #include "../../common_ogl/openGL_includes.h"
29 #include "accelerators/container_3d.h"
30 #include "accelerators/accelerator_3d.h"
31 #include "../render_3d_base.h"
32 #include "light.h"
33 #include "../post_shader_ssao.h"
34 #include "material.h"
35 #include <plugins/3dapi/c3dmodel.h>
36 
37 #include <map>
38 
39 /// Vector of materials
40 typedef std::vector< BLINN_PHONG_MATERIAL > MODEL_MATERIALS;
41 
42 /// Maps a S3DMODEL pointer with a created BLINN_PHONG_MATERIAL vector
43 typedef std::map< const S3DMODEL* , MODEL_MATERIALS > MAP_MODEL_MATERIALS;
44 
45 typedef enum
46 {
47     RT_RENDER_STATE_TRACING = 0,
48     RT_RENDER_STATE_POST_PROCESS_SHADE,
49     RT_RENDER_STATE_POST_PROCESS_BLUR_AND_FINISH,
50     RT_RENDER_STATE_FINISH,
51     RT_RENDER_STATE_MAX
52 } RT_RENDER_STATE;
53 
54 
55 class RENDER_3D_RAYTRACE : public RENDER_3D_BASE
56 {
57 public:
58     // TODO: Take into account board thickness so that the camera won't move inside of the board
59     // when facing it perpendicularly.
60     static constexpr float MIN_DISTANCE_IU = 4 * PCB_IU_PER_MM;
61 
62     explicit RENDER_3D_RAYTRACE( EDA_3D_CANVAS* aCanvas, BOARD_ADAPTER& aAdapter, CAMERA& aCamera );
63 
64     ~RENDER_3D_RAYTRACE();
65 
66     void SetCurWindowSize( const wxSize& aSize ) override;
67     bool Redraw( bool aIsMoving, REPORTER* aStatusReporter, REPORTER* aWarningReporter ) override;
68 
69     int GetWaitForEditingTimeOut() override;
70 
71     void Reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter,
72                  bool aOnlyLoadCopperAndShapes );
73 
74     BOARD_ITEM *IntersectBoardItem( const RAY& aRay );
75 
76 private:
77     bool initializeOpenGL();
78     void initializeNewWindowSize();
79     void initPbo();
80     void deletePbo();
81     void createItemsFromContainer( const BVH_CONTAINER_2D* aContainer2d, PCB_LAYER_ID aLayer_id,
82                                    const MATERIAL* aMaterialLayer, const SFVEC3F& aLayerColor,
83                                    float aLayerZOffset );
84 
85     void restartRenderState();
86     void renderTracing( GLubyte* ptrPBO, REPORTER* aStatusReporter );
87     void postProcessShading( GLubyte* ptrPBO, REPORTER* aStatusReporter );
88     void postProcessBlurFinish( GLubyte* ptrPBO, REPORTER* aStatusReporter );
89     void renderBlockTracing( GLubyte* ptrPBO , signed int iBlock );
90     void renderFinalColor( GLubyte* ptrPBO, const SFVEC3F& rgbColor,
91                            bool applyColorSpaceConversion );
92 
93     void renderRayPackets( const SFVEC3F* bgColorY, const RAY* aRayPkt, HITINFO_PACKET* aHitPacket,
94                            bool is_testShadow, SFVEC3F* aOutHitColor );
95 
96     void renderAntiAliasPackets( const SFVEC3F* aBgColorY, const HITINFO_PACKET* aHitPck_X0Y0,
97                                  const HITINFO_PACKET* aHitPck_AA_X1Y1, const RAY* aRayPck,
98                                  SFVEC3F* aOutHitColor );
99 
100     // Materials
101     void setupMaterials();
102 
103     SFVEC3F shadeHit( const SFVEC3F& aBgColor, const RAY& aRay, HITINFO& aHitInfo,
104                       bool aIsInsideObject, unsigned int aRecursiveLevel,
105                       bool is_testShadow ) const;
106 
107     /**
108      * Create one or more 3D objects form a 2D object and Z positions.
109      *
110      * It tries to optimize some types of objects that will be faster to trace than the
111      * LAYER_ITEM object.
112      */
113     void createObject( CONTAINER_3D& aDstContainer, const OBJECT_2D* aObject2D, float aZMin,
114                        float aZMax, const MATERIAL* aMaterial, const SFVEC3F& aObjColor );
115 
116     void addPadsAndVias();
117     void insertHole( const PCB_VIA* aVia );
118     void insertHole( const PAD* aPad );
119     void load3DModels( CONTAINER_3D& aDstContainer, bool aSkipMaterialInformation );
120     void addModels( CONTAINER_3D& aDstContainer, const S3DMODEL* a3DModel,
121                     const glm::mat4& aModelMatrix, float aFPOpacity,
122                     bool aSkipMaterialInformation, BOARD_ITEM* aBoardItem );
123 
124     MODEL_MATERIALS* getModelMaterial( const S3DMODEL* a3DModel );
125 
126     void initializeBlockPositions();
127 
128     void render( GLubyte* ptrPBO, REPORTER* aStatusReporter );
129     void renderPreview( GLubyte* ptrPBO );
130 
131     struct
132     {
133         BLINN_PHONG_MATERIAL m_Paste;
134         BLINN_PHONG_MATERIAL m_SilkS;
135         BLINN_PHONG_MATERIAL m_SolderMask;
136         BLINN_PHONG_MATERIAL m_EpoxyBoard;
137         BLINN_PHONG_MATERIAL m_Copper;
138         BLINN_PHONG_MATERIAL m_NonPlatedCopper;
139         BLINN_PHONG_MATERIAL m_Floor;
140     } m_materials;
141 
142     BOARD_NORMAL         m_boardMaterial;
143     COPPER_NORMAL        m_copperMaterial;
144     PLATED_COPPER_NORMAL m_platedCopperMaterial;
145     SOLDER_MASK_NORMAL   m_solderMaskMaterial;
146     PLASTIC_NORMAL       m_plasticMaterial;
147     PLASTIC_SHINE_NORMAL m_shinyPlasticMaterial;
148     BRUSHED_METAL_NORMAL m_brushedMetalMaterial;
149     SILK_SCREEN_NORMAL   m_silkScreenMaterial;
150 
151     bool m_isPreview;
152 
153     /// State used on quality render
154     RT_RENDER_STATE m_renderState;
155 
156     /// Time that the render starts
157     unsigned long int m_renderStartTime;
158 
159     /// Save the number of blocks progress of the render
160     size_t m_blockRenderProgressCount;
161 
162     POST_SHADER_SSAO m_postShaderSsao;
163 
164     std::list<LIGHT*> m_lights;
165 
166     DIRECTIONAL_LIGHT* m_cameraLight;
167 
168     bool m_openglSupportsVertexBufferObjects;
169 
170     GLuint m_pboId;
171     GLuint m_pboDataSize;
172 
173     CONTAINER_3D m_objectContainer;
174 
175     ///< Store the list of created objects special for RT that will be clear in the end.
176     CONTAINER_2D m_containerWithObjectsToDelete;
177 
178     CONTAINER_2D* m_outlineBoard2dObjects;
179     BVH_CONTAINER_2D* m_antioutlineBoard2dObjects;
180 
181     ACCELERATOR_3D* m_accelerator;
182 
183     SFVEC3F m_backgroundColorTop;
184     SFVEC3F m_backgroundColorBottom;
185 
186     ///< Used to see if the windows size changed.
187     wxSize m_oldWindowsSize;
188 
189     ///< Encode Morton code positions.
190     std::vector< SFVEC2UI > m_blockPositions;
191 
192     ///< Flag if a position was already processed (cleared each new render).
193     std::vector< int > m_blockPositionsWasProcessed;
194 
195     ///< Encode the Morton code positions (on fast preview mode).
196     std::vector< SFVEC2UI > m_blockPositionsFast;
197 
198     SFVEC2UI m_realBufferSize;
199     SFVEC2UI m_fastPreviewModeSize;
200 
201     HITINFO_PACKET* m_firstHitinfo;
202 
203     SFVEC3F* m_shaderBuffer;
204 
205     // Display Offset
206     unsigned int m_xoffset;
207     unsigned int m_yoffset;
208 
209     /// Stores materials of the 3D models
210     MAP_MODEL_MATERIALS m_modelMaterialMap;
211 
212     // Statistics
213     unsigned int m_convertedDummyBlockCount;
214     unsigned int m_converted2dRoundSegmentCount;
215 };
216 
217 #define USE_SRGB_SPACE
218 
219 #ifdef USE_SRGB_SPACE
220 extern SFVEC3F ConvertSRGBToLinear( const SFVEC3F& aSRGBcolor );
221 #else
222 #define ConvertSRGBToLinear( v ) ( v )
223 #endif
224 
225 #endif // RENDER_3D_RAYTRACE_H
226