KiCad PCB EDA Suite
sg_appearance.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2017 Cirilo Bernardo <[email protected]>
5 * Copyright (C) 2020 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#include <iostream>
26#include <utility>
27#include <sstream>
28#include <wx/log.h>
29
32
33
35{
37
38 // defaults in accord with VRML2.0 spec
39 ambient.SetColor( 0.05317f, 0.17879f, 0.01804f );
40 shininess = 0.2f;
41 transparency = 0.0f;
42 diffuse.SetColor( 0.8f, 0.8f, 0.8f );
43
44 if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
45 {
46 m_Parent = nullptr;
47
48 wxLogTrace( MASK_3D_SG,
49 wxT( "%s:%s:%d * [BUG] inappropriate parent to SGAPPEARANCE (type %s )" ),
50 __FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
51 }
52 else if( nullptr != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
53 {
54 m_Parent->AddChildNode( this );
55 }
56}
57
58
60{
61}
62
63
64bool SGAPPEARANCE::SetParent( SGNODE* aParent, bool notify )
65{
66 if( nullptr != m_Parent )
67 {
68 if( aParent == m_Parent )
69 return true;
70
71 // handle the change in parents
72 if( notify )
74
75 m_Parent = nullptr;
76
77 if( nullptr == aParent )
78 return true;
79 }
80
81 // only a SGSHAPE may be parent to a SGAPPEARANCE
82 if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
83 return false;
84
85 m_Parent = aParent;
86
87 if( m_Parent )
88 m_Parent->AddChildNode( this );
89
90 return true;
91}
92
93
94bool SGAPPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
95{
96 return emissive.SetColor( aRVal, aGVal, aBVal );
97}
98
99
100bool SGAPPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
101{
102 wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
103
104 return emissive.SetColor( aRGBColor );
105}
106
107
108bool SGAPPEARANCE::SetEmissive( const SGCOLOR& aRGBColor )
109{
110 return emissive.SetColor( aRGBColor );
111}
112
113
114bool SGAPPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
115{
116 return diffuse.SetColor( aRVal, aGVal, aBVal );
117}
118
119
120bool SGAPPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
121{
122 wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
123
124 return diffuse.SetColor( aRGBColor );
125}
126
127
128bool SGAPPEARANCE::SetDiffuse( const SGCOLOR& aRGBColor )
129{
130 return diffuse.SetColor( aRGBColor );
131}
132
133
134bool SGAPPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
135{
136 return specular.SetColor( aRVal, aGVal, aBVal );
137}
138
139
140bool SGAPPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
141{
142 wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
143
144 return specular.SetColor( aRGBColor );
145}
146
147bool SGAPPEARANCE::SetSpecular( const SGCOLOR& aRGBColor )
148{
149 return specular.SetColor( aRGBColor );
150}
151
152
153bool SGAPPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
154{
155 return ambient.SetColor( aRVal, aGVal, aBVal );
156}
157
158
159bool SGAPPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
160{
161 wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
162
163 return ambient.SetColor( aRGBColor );
164}
165
166
167bool SGAPPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
168{
169 return ambient.SetColor( aRGBColor );
170}
171
172
173SGNODE* SGAPPEARANCE::FindNode( const char* aNodeName, const SGNODE* aCaller) noexcept
174{
175 if( nullptr == aNodeName || 0 == aNodeName[0] )
176 return nullptr;
177
178 if( !m_Name.compare( aNodeName ) )
179 return this;
180
181 return nullptr;
182}
183
184
185void SGAPPEARANCE::unlinkChildNode( const SGNODE* aCaller ) noexcept
186{
187 wxCHECK_MSG( aCaller, /* void */,
188 wxT( "unexpected code branch; node should have no children or refs" ) );
189}
190
191
192void SGAPPEARANCE::unlinkRefNode( const SGNODE* aCaller ) noexcept
193{
194 wxCHECK_MSG( aCaller, /* void */,
195 wxT( "unexpected code branch; node should have no children or refs" ) );
196}
197
198
199bool SGAPPEARANCE::AddRefNode( SGNODE* aNode ) noexcept
200{
201 wxCHECK_MSG( aNode, false, wxT( "this node does not accept children or refs" ) );
202
203 // This is redundant but it keeps gcc from generating a warning on debug builds.
204 return false;
205}
206
207
208bool SGAPPEARANCE::AddChildNode( SGNODE* aNode ) noexcept
209{
210 wxCHECK_MSG( aNode, false, wxT( "this node does not accept children or refs" ) );
211
212 // This is redundant but it keeps gcc from generating a warning on debug builds.
213 return false;
214}
215
216
218{
219 m_written = false;
220
221 // rename this node
222 m_Name.clear();
223 GetName();
224}
225
226
227bool SGAPPEARANCE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
228{
229 if( aReuseFlag )
230 {
231 if( !m_written )
232 {
233 aFile << " appearance DEF " << GetName() << " Appearance {\n";
234 m_written = true;
235 }
236 else
237 {
238 aFile << " appearance USE " << GetName() << "\n";
239 return true;
240 }
241 }
242 else
243 {
244 aFile << " appearance Appearance {\n";
245 }
246
247 aFile << " material Material {\n";
248
249 std::string tmp;
250 float ambr, ambg, ambb;
251 ambient.GetColor( ambr, ambg, ambb );
252 float amb = ( 0.212671 * ambr + 0.71516 * ambg + 0.072169 * ambb );
253 diffuse.GetColor( ambr, ambg, ambb );
254 float den = ( 0.212671 * ambr + 0.71516 * ambg + 0.072169 * ambb );
255
256 if( den < 0.004f )
257 den = 0.004f;
258
259 amb /= den;
260
261 if( amb > 1.0f )
262 amb = 1.0f;
263
264 S3D::FormatFloat( tmp, amb );
265 aFile << " ambientIntensity " << tmp << "\n";
266
267 float red, green, blue;
268 diffuse.GetColor( red, green, blue );
269 S3D::FormatFloat( tmp, red );
270 aFile << " diffuseColor " << tmp << " ";
271 S3D::FormatFloat( tmp, green );
272 aFile << tmp << " ";
273 S3D::FormatFloat( tmp, blue);
274 aFile << tmp << "\n";
275
276 emissive.GetColor( red, green, blue );
277 S3D::FormatFloat( tmp, red );
278 aFile << " emissiveColor " << tmp << " ";
279 S3D::FormatFloat( tmp, green );
280 aFile << tmp << " ";
281 S3D::FormatFloat( tmp, blue);
282 aFile << tmp << "\n";
283
285 aFile << " shininess " << tmp << "\n";
286
287 specular.GetColor( red, green, blue );
288 S3D::FormatFloat( tmp, red );
289 aFile << " specularColor " << tmp << " ";
290 S3D::FormatFloat( tmp, green );
291 aFile << tmp << " ";
292 S3D::FormatFloat( tmp, blue);
293 aFile << tmp << "\n";
294
296 aFile << " transparency " << tmp << "\n";
297
298 aFile << "} }\n";
299
300 return true;
301}
302
303
304bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
305{
306 if( nullptr == parentNode )
307 {
308 wxCHECK_MSG( m_Parent, false, wxT( "corrupt data; m_aParent is NULL" ) );
309
310 SGNODE* np = m_Parent;
311
312 while( nullptr != np->GetParent() )
313 np = np->GetParent();
314
315 if( np->WriteCache( aFile, nullptr ) )
316 {
317 m_written = true;
318 return true;
319 }
320
321 return false;
322 }
323
324 wxCHECK_MSG( parentNode == m_Parent, false, wxT( "corrupt data; parentNode != m_aParent" ) );
325
326 if( !aFile.good() )
327 {
328 wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
329 __FILE__, __FUNCTION__, __LINE__ );
330
331 return false;
332 }
333
334 aFile << "[" << GetName() << "]";
335 S3D::WriteColor( aFile, ambient );
336 aFile.write( (char*) &shininess, sizeof( shininess ) );
337 aFile.write( (char*) &transparency, sizeof( transparency ) );
338 S3D::WriteColor( aFile, diffuse );
339 S3D::WriteColor( aFile, emissive );
340 S3D::WriteColor( aFile, specular );
341
342 if( aFile.fail() )
343 return false;
344
345 m_written = true;
346 return true;
347}
348
349
350bool SGAPPEARANCE::ReadCache( std::istream& aFile, SGNODE* parentNode )
351{
352 S3D::ReadColor( aFile, ambient );
353 aFile.read( (char*) &shininess, sizeof( shininess ) );
354 aFile.read( (char*) &transparency, sizeof( transparency ) );
355 S3D::ReadColor( aFile, diffuse );
356 S3D::ReadColor( aFile, emissive );
357 S3D::ReadColor( aFile, specular );
358
359 if( aFile.fail() )
360 return false;
361
362 return true;
363}
SGNODE * FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override
Search the tree of linked nodes and return a reference to the first node found with the given name.
bool AddRefNode(SGNODE *aNode) noexcept override
bool SetSpecular(float aRVal, float aGVal, float aBVal)
void unlinkRefNode(const SGNODE *aNode) noexcept override
Remove pointers to a referenced node.
SGCOLOR diffuse
Definition: sg_appearance.h:77
SGCOLOR ambient
Definition: sg_appearance.h:76
bool AddChildNode(SGNODE *aNode) noexcept override
void unlinkChildNode(const SGNODE *aNode) noexcept override
Remove references to an owned child.
SGAPPEARANCE(SGNODE *aParent)
float transparency
Definition: sg_appearance.h:75
bool SetEmissive(float aRVal, float aGVal, float aBVal)
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Writes this node's data to a VRML file.
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Reads binary format data from a cache file.
SGCOLOR specular
Definition: sg_appearance.h:79
bool SetDiffuse(float aRVal, float aGVal, float aBVal)
bool SetAmbient(float aRVal, float aGVal, float aBVal)
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Write this node's data to a binary cache file.
virtual ~SGAPPEARANCE()
SGCOLOR emissive
Definition: sg_appearance.h:78
void ReNameNodes(void) override
Rename a node and all its child nodes in preparation for write operations.
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Set the parent SGNODE of this object.
bool SetColor(float aRedVal, float aGreenVal, float aBlueVal)
Definition: sg_base.cpp:85
void GetColor(float &aRedVal, float &aGreenVal, float &aBlueVal) const noexcept
Definition: sg_base.cpp:59
The base class of all Scene Graph nodes.
Definition: sg_node.h:75
virtual bool WriteCache(std::ostream &aFile, SGNODE *parentNode)=0
Write this node's data to a binary cache file.
const char * GetName(void)
Definition: sg_node.cpp:146
SGNODE * GetParent(void) const noexcept
Returns a pointer to the parent SGNODE of this object or NULL if the object has no parent (ie.
Definition: sg_node.cpp:110
S3D::SGTYPES GetNodeType(void) const noexcept
Return the type of this node instance.
Definition: sg_node.cpp:104
virtual bool AddChildNode(SGNODE *aNode)=0
SGNODE * m_Parent
Pointer to parent node; may be NULL for top level transform.
Definition: sg_node.h:227
std::string m_Name
name to use for referencing the entity by name.
Definition: sg_node.h:229
virtual void unlinkChildNode(const SGNODE *aNode)=0
Remove references to an owned child.
bool m_written
Set to true when the object has been written after a ReNameNodes().
Definition: sg_node.h:230
S3D::SGTYPES m_SGtype
Type of Scene Graph node.
Definition: sg_node.h:228
bool WriteColor(std::ostream &aFile, const SGCOLOR &aColor)
Definition: sg_helpers.cpp:180
void FormatFloat(std::string &result, double value)
Definition: sg_helpers.cpp:37
@ SGTYPE_SHAPE
Definition: sg_types.h:44
@ SGTYPE_APPEARANCE
Definition: sg_types.h:37
bool ReadColor(std::istream &aFile, SGCOLOR &aColor)
Definition: sg_helpers.cpp:295
Define a number of macros to aid in repetitious code which is probably best expressed as a preprocess...