1 // Copyright 2009-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 
4 // ospray
5 #include "Material.h"
6 #include "common/Util.h"
7 #include "texture/Texture2D.h"
8 
9 #include "texture/TextureParam_ispc.h"
10 
11 namespace ospray {
12 
13 static FactoryMap<Material> g_materialsMap;
14 
15 // Material definitions ///////////////////////////////////////////////////////
16 
17 Material::Material()
18 {
19   managedObjectType = OSP_MATERIAL;
20 }
21 
22 Material *Material::createInstance(
23     const char */*ignored*/, const char *_material_type)
24 {
25   std::string name = _material_type;
26   return createInstanceHelper(name, g_materialsMap[name]);
27 }
28 
29 void Material::registerType(const char *name, FactoryFcn<Material> f)
30 {
31   g_materialsMap[name] = f;
32 }
33 
34 std::string Material::toString() const
35 {
36   return "ospray::Material";
37 }
38 
39 void Material::commit() {}
40 
41 ispc::TextureParam Material::getTextureParam(const char *texture_name)
numJobs(const int spp,int accumID)42 {
43   // Get texture pointer
44   Texture2D *ptr = (Texture2D *)getParamObject(texture_name);
45 
46   // Get 2D transformation if exists
47   int transformFlags = ispc::TRANSFORM_FLAG_NONE;
48   affine2f xfm2f = affine2f(one);
49   utility::Optional<affine2f> xform2f = getTextureTransform2f(texture_name);
50   if (xform2f.has_value()) {
51     xfm2f = xform2f.value();
52     transformFlags |= ispc::TRANSFORM_FLAG_2D;
53   }
54 
55   // Get 3D transformation if exists
56   affine3f xfm3f = affine3f(one);
57   auto xform3f =
58       getOptParam<affine3f>((std::string(texture_name) + ".transform").c_str());
59   if (xform3f.has_value()) {
60     xfm3f = xform3f.value();
61     transformFlags |= ispc::TRANSFORM_FLAG_3D;
62   }
63 
64   // Initialize ISPC structure
65   ispc::TextureParam param;
66   TextureParam_set(&param,
67       ptr ? ptr->getIE() : nullptr,
68       (ispc::TransformFlags)transformFlags,
69       (const ispc::AffineSpace2f &)xfm2f,
70       (const ispc::AffineSpace3f &)xfm3f);
71 
72   // Done
73   return param;
74 }
75 
76 MaterialParam1f Material::getMaterialParam1f(
77     const char *name, float valIfNotFound)
78 {
79   const std::string mapName = "map_" + std::string(name);
80   MaterialParam1f param;
81   param.tex = getTextureParam(mapName.c_str());
82   param.rot = ((linear2f *)(&param.tex.xform2f.l))->orthogonal().transposed();
83   param.factor = getParam<float>(name, param.tex.ptr ? 1.f : valIfNotFound);
84   return param;
85 }
86 
87 MaterialParam3f Material::getMaterialParam3f(
88     const char *name, vec3f valIfNotFound)
89 {
90   const std::string mapName = "map_" + std::string(name);
91   MaterialParam3f param;
92   param.tex = getTextureParam(mapName.c_str());
93   param.rot = ((linear2f *)(&param.tex.xform2f.l))->orthogonal().transposed();
94   param.factor =
95       getParam<vec3f>(name, param.tex.ptr ? vec3f(1.f) : valIfNotFound);
96   return param;
97 }
98 
99 utility::Optional<affine2f> Material::getTextureTransform2f(
100     const char *_texname)
101 {
102   std::string texname(_texname);
103   texname += ".";
104   utility::Optional<affine2f> xform;
105 
106   // Apply translation
107   const utility::Optional<vec2f> translation =
108       getOptParam<vec2f>((texname + "translation").c_str());
109   if (translation.has_value())
110     xform = affine2f::translate(-translation.value());
111 
112   // Apply scale
113   const utility::Optional<vec2f> scale =
114       getOptParam<vec2f>((texname + "scale").c_str());
115   if (scale.has_value()) {
116     xform = xform.value_or(affine2f(one)) * affine2f::translate(vec2f(0.5f));
117     xform = *xform * affine2f::scale(rcp(scale.value()));
118     xform = *xform * affine2f::translate(vec2f(-0.5f));
119   }
120 
121   // Apply rotation
122   const utility::Optional<float> rotation =
123       getOptParam<float>((texname + "rotation").c_str());
124   if (rotation.has_value()) {
125     xform = xform.value_or(affine2f(one)) * affine2f::translate(vec2f(0.5f));
126     xform = *xform * affine2f::rotate(-deg2rad(rotation.value()));
127     xform = *xform * affine2f::translate(vec2f(-0.5f));
128   }
129 
130   // Apply complete transformation
131   const utility::Optional<linear2f> transf =
132       getOptParam<linear2f>((texname + "transform").c_str());
133   if (transf.has_value())
134     xform = xform.value_or(affine2f(one)) * affine2f(transf.value());
135   const utility::Optional<vec4f> transf4 = // legacy / backwards compatible
136       getOptParam<vec4f>((texname + "transform").c_str());
137   if (transf4.has_value()) {
138     const linear2f transform = (const linear2f &)transf4.value();
139     xform = xform.value_or(affine2f(one)) * affine2f(transform);
140   }
141 
142   // Return optional transformation
143   return xform;
144 }
145 
146 OSPTYPEFOR_DEFINITION(Material *);
147 
148 } // namespace ospray
149