Blender V4.3
EffectExporter.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2010-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <map>
10#include <set>
11
12#include "COLLADAFWColorOrTexture.h"
13#include "COLLADASWEffectProfile.h"
14
15#include "DocumentExporter.h"
16#include "EffectExporter.h"
17#include "MaterialExporter.h"
18
19#include "collada_internal.h"
20#include "collada_utils.h"
21
22#include "DNA_mesh_types.h"
23#include "DNA_world_types.h"
24
25#include "BKE_collection.hh"
26#include "BKE_customdata.hh"
27#include "BKE_material.h"
28#include "BKE_mesh.hh"
29
30static std::string getActiveUVLayerName(Object *ob)
31{
32 Mesh *mesh = (Mesh *)ob->data;
33
34 int num_layers = CustomData_number_of_layers(&mesh->corner_data, CD_PROP_FLOAT2);
35 if (num_layers) {
36 return std::string(bc_CustomData_get_active_layer_name(&mesh->corner_data, CD_PROP_FLOAT2));
37 }
38
39 return "";
40}
41
42EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw,
43 BCExportSettings &export_settings,
44 KeyImageMap &key_image_map)
45 : COLLADASW::LibraryEffects(sw), export_settings(export_settings), key_image_map(key_image_map)
46{
47}
48
49bool EffectsExporter::hasEffects(Scene *sce)
50{
51 bool result = false;
53 int a;
54 for (a = 0; a < ob->totcol; a++) {
55 Material *ma = BKE_object_material_get(ob, a + 1);
56
57 /* no material, but check all of the slots */
58 if (!ma) {
59 continue;
60 }
61
62 result = true;
63 break;
64 }
65 }
67 return result;
68}
69
71{
72 if (hasEffects(sce)) {
73 this->mContext = C;
74 this->scene = sce;
75 openLibrary();
78 sce, *this, this->export_settings.get_export_set());
79
80 closeLibrary();
81 }
82}
83
84void EffectsExporter::set_shader_type(COLLADASW::EffectProfile &ep, Material *ma)
85{
86 /* XXX check if BLINN and PHONG can be supported as well */
87 ep.setShaderType(COLLADASW::EffectProfile::LAMBERT);
88}
89
90void EffectsExporter::set_transparency(COLLADASW::EffectProfile &ep, Material *ma)
91{
92 double alpha = bc_get_alpha(ma);
93 if (alpha < 1) {
94 /* workaround use <transparent> to avoid wrong handling of <transparency> by other tools */
95 COLLADASW::ColorOrTexture cot = bc_get_cot(0, 0, 0, alpha);
96 ep.setTransparent(cot, false, "alpha");
97 ep.setOpaque(COLLADASW::EffectProfile::A_ONE);
98 }
99}
100
101void EffectsExporter::set_diffuse_color(COLLADASW::EffectProfile &ep, Material *ma)
102{
103 COLLADASW::ColorOrTexture cot = bc_get_base_color(ma);
104 ep.setDiffuse(cot, false, "diffuse");
105}
106
107void EffectsExporter::set_ambient(COLLADASW::EffectProfile &ep, Material *ma)
108{
109 COLLADASW::ColorOrTexture cot = bc_get_ambient(ma);
110 ep.setAmbient(cot, false, "ambient");
111}
112void EffectsExporter::set_specular(COLLADASW::EffectProfile &ep, Material *ma)
113{
114 COLLADASW::ColorOrTexture cot = bc_get_specular(ma);
115 ep.setSpecular(cot, false, "specular");
116}
117void EffectsExporter::set_reflective(COLLADASW::EffectProfile &ep, Material *ma)
118{
119 COLLADASW::ColorOrTexture cot = bc_get_reflective(ma);
120 ep.setReflective(cot, false, "reflective");
121}
122
123void EffectsExporter::set_reflectivity(COLLADASW::EffectProfile &ep, Material *ma)
124{
125 double reflectivity = bc_get_reflectivity(ma);
126 if (reflectivity > 0.0) {
127 ep.setReflectivity(reflectivity, false, "specular");
128 }
129}
130
131void EffectsExporter::set_emission(COLLADASW::EffectProfile &ep, Material *ma)
132{
133 COLLADASW::ColorOrTexture cot = bc_get_emission(ma);
134 ep.setEmission(cot, false, "emission");
135}
136
137void EffectsExporter::set_ior(COLLADASW::EffectProfile &ep, Material *ma)
138{
139 double alpha = bc_get_ior(ma);
140 ep.setIndexOfRefraction(alpha, false, "ior");
141}
142
143void EffectsExporter::set_shininess(COLLADASW::EffectProfile &ep, Material *ma)
144{
145 double shininess = bc_get_shininess(ma);
146 ep.setShininess(shininess, false, "shininess");
147}
148
149void EffectsExporter::get_images(Material *ma, KeyImageMap &material_image_map)
150{
151 if (!ma->use_nodes) {
152 return;
153 }
154
155 MaterialNode material = MaterialNode(mContext, ma, key_image_map);
156 Image *image = material.get_diffuse_image();
157 if (image == nullptr) {
158 return;
159 }
160
161 std::string uid(id_name(image));
162 std::string key = translate_id(uid);
163
164 if (material_image_map.find(key) == material_image_map.end()) {
165 material_image_map[key] = image;
166 key_image_map[key] = image;
167 }
168}
169
170void EffectsExporter::create_image_samplers(COLLADASW::EffectProfile &ep,
171 KeyImageMap &material_image_map,
172 std::string &active_uv)
173{
174 KeyImageMap::iterator iter;
175
176 for (iter = material_image_map.begin(); iter != material_image_map.end(); iter++) {
177
178 Image *image = iter->second;
179 std::string uid(id_name(image));
180 std::string key = translate_id(uid);
181
182 COLLADASW::Sampler *sampler = new COLLADASW::Sampler(
183 COLLADASW::Sampler::SAMPLER_TYPE_2D,
184 key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
185 key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
186
187 sampler->setImageId(key);
188
189 ep.setDiffuse(createTexture(image, active_uv, sampler), false, "diffuse");
190 }
191}
192
194{
195 KeyImageMap material_image_map;
196
197 openEffect(get_effect_id(ma));
198
199 COLLADASW::EffectProfile ep(mSW);
200 ep.setProfileType(COLLADASW::EffectProfile::COMMON);
201 ep.openProfile();
202 set_shader_type(ep, ma); /* creates a Lambert Shader for now */
203
204 COLLADASW::ColorOrTexture cot;
205
206 set_diffuse_color(ep, ma);
207 set_emission(ep, ma);
208 set_ior(ep, ma);
209 set_reflectivity(ep, ma);
210 set_transparency(ep, ma);
211
212 /* TODO: */
213#if 0
214 set_shininess(ep, ma); /* Shininess not supported for lambert. */
215 set_ambient(ep, ma);
216 set_specular(ep, ma);
217#endif
218
219 get_images(ma, material_image_map);
220 std::string active_uv(getActiveUVLayerName(ob));
221 create_image_samplers(ep, material_image_map, active_uv);
222
223#if 0
224 uint a, b;
225 for (a = 0, b = 0; a < tex_indices.size(); a++) {
226 MTex *t = ma->mtex[tex_indices[a]];
227 Image *ima = t->tex->ima;
228
229 /* Image not set for texture */
230 if (!ima) {
231 continue;
232 }
233
234 std::string key(id_name(ima));
235 key = translate_id(key);
236
237 /* create only one <sampler>/<surface> pair for each unique image */
238 if (im_samp_map.find(key) == im_samp_map.end()) {
239 /* <newparam> <sampler> <source> */
240 COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
241 key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
242 key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
243 sampler.setImageId(key);
244 /* copy values to arrays since they will live longer */
245 samplers[a] = sampler;
246
247 /* store pointers so they can be used later when we create <texture>s */
248 samp_surf[b] = &samplers[a];
249 // samp_surf[b][1] = &surfaces[a];
250
251 im_samp_map[key] = b;
252 b++;
253 }
254 }
255
256 for (a = 0; a < tex_indices.size(); a++) {
257 MTex *t = ma->mtex[tex_indices[a]];
258 Image *ima = t->tex->ima;
259
260 if (!ima) {
261 continue;
262 }
263
264 std::string key(id_name(ima));
265 key = translate_id(key);
266 int i = im_samp_map[key];
267 std::string uvname = strlen(t->uvname) ? t->uvname : active_uv;
268 COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)
269 samp_surf[i]; /* possibly uninitialized memory ... */
270 writeTextures(ep, key, sampler, t, ima, uvname);
271 }
272#endif
273
274 /* performs the actual writing */
275 ep.addProfileElements();
276 ep.addExtraTechniques(mSW);
277
278 ep.closeProfile();
279 closeEffect();
280}
281
282COLLADASW::ColorOrTexture EffectsExporter::createTexture(Image *ima,
283 std::string &uv_layer_name,
284 COLLADASW::Sampler *sampler
285 /*COLLADASW::Surface *surface*/)
286{
287
288 COLLADASW::Texture texture(translate_id(id_name(ima)));
289 texture.setTexcoord(uv_layer_name);
290 // texture.setSurface(*surface);
291 texture.setSampler(*sampler);
292
293 COLLADASW::ColorOrTexture cot(texture);
294 return cot;
295}
296
297COLLADASW::ColorOrTexture EffectsExporter::getcol(float r, float g, float b, float a)
298{
299 COLLADASW::Color color(r, g, b, a);
300 COLLADASW::ColorOrTexture cot(color);
301 return cot;
302}
#define FOREACH_SCENE_OBJECT_END
#define FOREACH_SCENE_OBJECT_BEGIN(scene, _instance)
CustomData interface, see also DNA_customdata_types.h.
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
unsigned int uint
@ CD_PROP_FLOAT2
static std::string getActiveUVLayerName(Object *ob)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
#define C
Definition RandGen.cpp:29
EffectsExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings, KeyImageMap &key_image_map)
COLLADASW::ColorOrTexture createTexture(Image *ima, std::string &uv_layer_name, COLLADASW::Sampler *sampler)
COLLADASW::ColorOrTexture getcol(float r, float g, float b, float a)
void operator()(Material *ma, Object *ob)
void exportEffects(bContext *C, Scene *sce)
std::string translate_id(const char *idString)
std::string get_effect_id(Material *mat)
std::string id_name(void *id)
COLLADASW::ColorOrTexture bc_get_specular(Material *ma)
COLLADASW::ColorOrTexture bc_get_ambient(Material *ma)
double bc_get_alpha(Material *ma)
COLLADASW::ColorOrTexture bc_get_cot(float r, float g, float b, float a)
COLLADASW::ColorOrTexture bc_get_emission(Material *ma)
COLLADASW::ColorOrTexture bc_get_reflective(Material *ma)
double bc_get_reflectivity(Material *ma)
double bc_get_shininess(Material *ma)
COLLADASW::ColorOrTexture bc_get_base_color(Material *ma)
double bc_get_ior(Material *ma)
const char * bc_CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
std::map< std::string, Image * > KeyImageMap
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
local_group_size(16, 16) .push_constant(Type local_group_size(16, 16) .push_constant(Type input_tx sampler(1, ImageType::FLOAT_2D, "matte_tx") .image(0
local_group_size(16, 16) .push_constant(Type b
local_group_size(16, 16) .push_constant(Type texture
char uvname[68]
struct Tex * tex
void forEachMaterialInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
struct Image * ima