Cleanup: manually remove header text not handled by automation
[blender.git] / source / blender / collada / Materials.cpp
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 #include "Materials.h"
18
19 MaterialNode::MaterialNode(bContext *C, Material *ma, KeyImageMap &key_image_map) :
20         mContext(C),
21         material(ma),
22         effect(nullptr),
23         key_image_map(&key_image_map)
24 {
25         ntree = prepare_material_nodetree();
26         setShaderType();
27 }
28
29 MaterialNode::MaterialNode(bContext *C, COLLADAFW::EffectCommon *ef, Material *ma, UidImageMap &uid_image_map) :
30         mContext(C),
31         material(ma),
32         effect(ef),
33         uid_image_map(&uid_image_map)
34 {
35         ntree = prepare_material_nodetree();
36         setShaderType();
37
38         std::map<std::string, bNode *> nmap;
39 #if 0
40         nmap["main"] = add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300);
41         nmap["emission"] = add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission");
42         nmap["add"] = add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400);
43         nmap["transparent"] = add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200);
44         nmap["mix"] = add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency");
45         nmap["out"] = add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300);
46         nmap["out"]->flag &= ~NODE_SELECT;
47
48         add_link(ntree, nmap["emission"], 0, nmap["add"], 0);
49         add_link(ntree, nmap["main"], 0, nmap["add"], 1);
50         add_link(ntree, nmap["add"], 0, nmap["mix"], 1);
51         add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2);
52
53         add_link(ntree, nmap["mix"], 0, nmap["out"], 0);
54         // experimental, probably not used.
55         make_group(C, ntree, nmap);
56 #else
57         shader_node = add_node(SH_NODE_BSDF_PRINCIPLED, 0, 300, "");
58         output_node = add_node(SH_NODE_OUTPUT_MATERIAL, 300, 300, "");
59         add_link(shader_node, 0, output_node, 0);
60 #endif
61 }
62
63 void MaterialNode::setShaderType()
64 {
65 #if 0
66         COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
67         // Currently we only support PBR based shaders
68         // TODO: simulate the effects with PBR
69
70         // blinn
71         if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
72                 ma->spec_shader = MA_SPEC_BLINN;
73                 ma->spec = ef->getShininess().getFloatValue();
74         }
75         // phong
76         else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
77                 ma->spec_shader = MA_SPEC_PHONG;
78                 ma->har = ef->getShininess().getFloatValue();
79         }
80         // lambert
81         else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
82                 ma->diff_shader = MA_DIFF_LAMBERT;
83         }
84         // default - lambert
85         else {
86                 ma->diff_shader = MA_DIFF_LAMBERT;
87                 fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
88         }
89 #endif
90 }
91
92 bNodeTree *MaterialNode::prepare_material_nodetree()
93 {
94         if (material->nodetree == NULL) {
95                 material->nodetree = ntreeAddTree(NULL, "Shader Nodetree", "ShaderNodeTree");
96                 material->use_nodes = true;
97         }
98         return material->nodetree;
99 }
100
101 bNode *MaterialNode::add_node(int node_type, int locx, int locy, std::string label)
102 {
103         bNode *node = nodeAddStaticNode(mContext, ntree, node_type);
104         if (node) {
105                 if (label.length() > 0) {
106                         strcpy(node->label, label.c_str());
107                 }
108                 node->locx = locx;
109                 node->locy = locy;
110                 node->flag |= NODE_SELECT;
111         }
112         node_map[label] = node;
113         return node;
114 }
115
116 void MaterialNode::add_link(bNode *from_node, int from_index, bNode *to_node, int to_index)
117 {
118         bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
119         bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
120
121         nodeAddLink(ntree, from_node, from_socket, to_node, to_socket);
122 }
123
124 void MaterialNode::set_reflectivity(float val)
125 {
126         material->metallic = val;
127         bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_METALLIC);
128         *(float *)socket->default_value = val;
129 }
130
131 void MaterialNode::set_ior(float val)
132 {
133         bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_IOR);
134         *(float *)socket->default_value = val;
135 }
136
137 void MaterialNode::set_diffuse(COLLADAFW::ColorOrTexture &cot, std::string label)
138 {
139         int locy = -300 * (node_map.size()-2);
140         if (cot.isColor()) {
141                 COLLADAFW::Color col = cot.getColor();
142                 material->r = col.getRed();
143                 material->g = col.getGreen();
144                 material->b = col.getBlue();
145
146                 bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&shader_node->inputs, BC_PBR_DIFFUSE);
147                 float *fcol = (float *)socket->default_value;
148                 fcol[0] = col.getRed();
149                 fcol[1] = col.getGreen();
150                 fcol[2] = col.getBlue();
151         }
152         else if (cot.isTexture()) {
153                 bNode *texture_node = add_texture_node(cot, -300, locy, label);
154                 if (texture_node != NULL) {
155                         add_link(texture_node, 0, shader_node, 0);
156                 }
157         }
158 }
159
160 Image *MaterialNode::get_diffuse_image()
161 {
162         bNode *shader = ntreeFindType(ntree, SH_NODE_BSDF_PRINCIPLED);
163         if (shader == nullptr) {
164                 return nullptr;
165         }
166
167         bNodeSocket *in_socket = (bNodeSocket *)BLI_findlink(&shader->inputs, BC_PBR_DIFFUSE);
168         if (in_socket == nullptr) {
169                 return nullptr;
170         }
171
172         bNodeLink *link = in_socket->link;
173         if (link == nullptr) {
174                 return nullptr;
175         }
176
177         bNode *texture = link->fromnode;
178         if (texture == nullptr) {
179                 return nullptr;
180         }
181
182         if (texture->type != SH_NODE_TEX_IMAGE) {
183                 return nullptr;
184         }
185
186         Image *image = (Image *)texture->id;
187         return image;
188
189 }
190
191 static bNodeSocket *set_color(bNode *node, COLLADAFW::Color col)
192 {
193                 bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->outputs, 0);
194                 float *fcol = (float *)socket->default_value;
195                 fcol[0] = col.getRed();
196                 fcol[1] = col.getGreen();
197                 fcol[2] = col.getBlue();
198
199                 return socket;
200 }
201
202 void MaterialNode::set_ambient(COLLADAFW::ColorOrTexture &cot, std::string label)
203 {
204         int locy = -300 * (node_map.size() - 2);
205         if (cot.isColor()) {
206                 COLLADAFW::Color col = cot.getColor();
207                 bNode *node = add_node(SH_NODE_RGB, -300, locy, label);
208                 set_color(node, col);
209                 // TODO: Connect node
210         }
211         // texture
212         else if (cot.isTexture()) {
213                 add_texture_node(cot, -300, locy, label);
214                 // TODO: Connect node
215         }
216 }
217 void MaterialNode::set_reflective(COLLADAFW::ColorOrTexture &cot, std::string label)
218 {
219         int locy = -300 * (node_map.size() - 2);
220         if (cot.isColor()) {
221                 COLLADAFW::Color col = cot.getColor();
222                 bNode *node = add_node(SH_NODE_RGB, -300, locy, label);
223                 set_color(node, col);
224                 // TODO: Connect node
225         }
226         // texture
227         else if (cot.isTexture()) {
228                 add_texture_node(cot, -300, locy, label);
229                 // TODO: Connect node
230         }
231 }
232
233 void MaterialNode::set_emission(COLLADAFW::ColorOrTexture &cot, std::string label)
234 {
235         int locy = -300 * (node_map.size() - 2);
236         if (cot.isColor()) {
237                 COLLADAFW::Color col = cot.getColor();
238                 bNode *node = add_node(SH_NODE_RGB, -300, locy, label);
239                 set_color(node, col);
240                 // TODO: Connect node
241         }
242         // texture
243         else if (cot.isTexture()) {
244                 add_texture_node(cot, -300, locy, label);
245                 // TODO: Connect node
246         }
247 }
248
249 void MaterialNode::set_opacity(COLLADAFW::ColorOrTexture &cot, std::string label)
250 {
251         if (effect == nullptr) {
252                 return;
253         }
254
255         int locy = -300 * (node_map.size() - 2);
256         if (cot.isColor()) {
257                 COLLADAFW::Color col = effect->getTransparent().getColor();
258                 float alpha = effect->getTransparency().getFloatValue();
259
260                 if (col.isValid()) {
261                         alpha *= col.getAlpha(); // Assuming A_ONE opaque mode
262                 }
263                 if (col.isValid() || alpha < 1.0) {
264                         // not sure what to do here
265                 }
266
267                 bNode *node = add_node(SH_NODE_RGB, -300, locy, label);
268                 set_color(node, col);
269                 // TODO: Connect node
270         }
271         // texture
272         else if (cot.isTexture()) {
273                 add_texture_node(cot, -300, locy, label);
274                 // TODO: Connect node
275         }
276 }
277
278 void MaterialNode::set_specular(COLLADAFW::ColorOrTexture &cot, std::string label)
279 {
280         int locy = -300 * (node_map.size() - 2);
281         if (cot.isColor()) {
282                 COLLADAFW::Color col = cot.getColor();
283                 material->specr = col.getRed();
284                 material->specg = col.getGreen();
285                 material->specb = col.getBlue();
286
287                 bNode *node = add_node(SH_NODE_RGB, -300, locy, label);
288                 set_color(node, col);
289                 // TODO: Connect node
290         }
291         // texture
292         else if (cot.isTexture()) {
293                 add_texture_node(cot, -300, locy, label);
294                 // TODO: Connect node
295         }
296 }
297
298 bNode *MaterialNode::add_texture_node(COLLADAFW::ColorOrTexture &cot, int locx, int locy, std::string label)
299 {
300         if (effect == nullptr) {
301                 return nullptr;
302         }
303
304         UidImageMap &image_map = *uid_image_map;
305
306         COLLADAFW::Texture ctex = cot.getTexture();
307
308         COLLADAFW::SamplerPointerArray& samp_array = effect->getSamplerPointerArray();
309         COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
310
311         const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
312
313         if (image_map.find(ima_uid) == image_map.end()) {
314                 fprintf(stderr, "Couldn't find an image by UID.\n");
315                 return NULL;
316         }
317
318         Image *ima = image_map[ima_uid];
319         bNode *texture_node = add_node(SH_NODE_TEX_IMAGE, locx, locy, label);
320         texture_node->id = &ima->id;
321         return texture_node;
322
323 }