Cycles Volume Render: generated texture coordinates for volume render.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 31 Dec 2013 16:33:55 +0000 (17:33 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 31 Dec 2013 16:38:26 +0000 (17:38 +0100)
This does not support staying fixed while the surface deforms, but for static
meshes it should match up with the surface texture coordinates. Implemented
as a matrix transform from objects space to mesh texture space.

Making this work for deforming surfaces would be quite complicated, you might
need something like harmonic coordinates as used in the mesh deform modifier,
probably will not be possible anytime soon.

13 files changed:
intern/cycles/blender/blender_mesh.cpp
intern/cycles/kernel/kernel_primitive.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/osl/osl_services.cpp
intern/cycles/kernel/osl/osl_shader.cpp
intern/cycles/kernel/shaders/node_texture_coordinate.osl
intern/cycles/kernel/svm/svm_tex_coord.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/attribute.cpp
intern/cycles/render/attribute.h
intern/cycles/render/graph.cpp
intern/cycles/render/mesh.cpp
intern/cycles/render/nodes.cpp

index 0e46903a50cd8c2c64ca318c56859114e55e37e0..c761c004fe708b5de77c43b27ddd139723627c5d 100644 (file)
@@ -348,9 +348,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
                }
        }
 
-       /* create generated coordinates. todo: we should actually get the orco
-        * coordinates from modifiers, for now we use texspace loc/size which
-        * is available in the api. */
+       /* create generated coordinates from undeformed coordinates */
        if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
                Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
 
@@ -363,6 +361,19 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
                for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
                        generated[i++] = get_float3(v->undeformed_co())*size - loc;
        }
+
+       /* for volume objects, create a matrix to transform from object space to
+        * mesh texture space. this does not work with deformations but that can
+        * probably only be done well with a volume grid mapping of coordinates */
+       if(mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) {
+               Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM);
+               Transform *tfm = attr->data_transform();
+
+               float3 loc, size;
+               mesh_texture_space(b_mesh, loc, size);
+
+               *tfm = transform_translate(-loc)*transform_scale(size);
+       }
 }
 
 static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
index 5a050c443da9d0995c7b4ca87e49c09cfbb861f1..fa450c97cbf9bdad3e5edd067b6d08048589f193 100644 (file)
@@ -23,7 +23,7 @@ CCL_NAMESPACE_BEGIN
 
 ccl_device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, AttributeElement *elem)
 {
-       if(sd->object == ~0 || sd->prim == ~0)
+       if(sd->object == ~0)
                return (int)ATTR_STD_NOT_FOUND;
 
 #ifdef __OSL__
@@ -47,6 +47,9 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id,
 
                *elem = (AttributeElement)attr_map.y;
                
+               if(sd->prim == ~0 && (AttributeElement)attr_map.y != ATTR_ELEMENT_MESH)
+                       return ATTR_STD_NOT_FOUND;
+
                /* return result */
                return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
        }
@@ -76,6 +79,18 @@ ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData
 #endif
 }
 
+ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg, const ShaderData *sd, int offset)
+{
+       Transform tfm;
+
+       tfm.x = kernel_tex_fetch(__attributes_float3, offset + 0);
+       tfm.y = kernel_tex_fetch(__attributes_float3, offset + 1);
+       tfm.z = kernel_tex_fetch(__attributes_float3, offset + 2);
+       tfm.w = kernel_tex_fetch(__attributes_float3, offset + 3);
+
+       return tfm;
+}
+
 ccl_device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
 {
        AttributeElement elem_uv;
index 1463ce98d150eaeff4fb3ca798be717515ac551d..00cb73b1e34cd329edea8a66f132c2a34b5cdf81 100644 (file)
@@ -418,7 +418,8 @@ typedef struct Intersection {
 
 typedef enum AttributeElement {
        ATTR_ELEMENT_NONE,
-       ATTR_ELEMENT_VALUE,
+       ATTR_ELEMENT_OBJECT,
+       ATTR_ELEMENT_MESH,
        ATTR_ELEMENT_FACE,
        ATTR_ELEMENT_VERTEX,
        ATTR_ELEMENT_CORNER,
@@ -434,6 +435,7 @@ typedef enum AttributeStandard {
        ATTR_STD_UV_TANGENT,
        ATTR_STD_UV_TANGENT_SIGN,
        ATTR_STD_GENERATED,
+       ATTR_STD_GENERATED_TRANSFORM,
        ATTR_STD_POSITION_UNDEFORMED,
        ATTR_STD_POSITION_UNDISPLACED,
        ATTR_STD_MOTION_PRE,
index d7d3301c0b0b1fac4a451f4b98f73dcfa964bee7..9b2065d8892a2e22f2ecd9f7f3d9cebce08cbaaf 100644 (file)
@@ -510,12 +510,22 @@ static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives,
        return false;
 }
 
-static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr,
+static bool set_attribute_matrix(const Transform& tfm, TypeDesc type, void *val)
+{
+       if(type == TypeDesc::TypeMatrix) {
+               Transform transpose = transform_transpose(tfm);
+               memcpy(val, &transpose, sizeof(Transform));
+               return true;
+       }
+
+       return false;
+}
+
+static bool get_mesh_element_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr,
                                const TypeDesc& type, bool derivatives, void *val)
 {
        if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
-           attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
-       {
+           attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) {
                float3 fval[3];
                fval[0] = primitive_attribute_float3(kg, sd, attr.elem, attr.offset,
                                                     (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
@@ -532,6 +542,18 @@ static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OS
        }
 }
 
+static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr,
+                               const TypeDesc& type, bool derivatives, void *val)
+{
+       if (attr.type == TypeDesc::TypeMatrix) {
+               Transform tfm = primitive_attribute_matrix(kg, sd, attr.offset);
+               return set_attribute_matrix(tfm, type, val);
+       }
+       else {
+               return false;
+       }
+}
+
 static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivatives, void *val)
 {
        size_t datasize = attr.value.datasize();
@@ -745,9 +767,11 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
        if (it != attribute_map.end()) {
                const OSLGlobals::Attribute& attr = it->second;
 
-               if (attr.elem != ATTR_ELEMENT_VALUE) {
+               if (attr.elem != ATTR_ELEMENT_OBJECT) {
                        /* triangle and vertex attributes */
                        if (prim != ~0)
+                               return get_mesh_element_attribute(kg, sd, attr, type, derivatives, val);
+                       else
                                return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
                }
                else {
index 6062996af364e426a1ffbe66ac3229730ead1121..554f647df7cce15c8188bdc8bee27aef26ec71ad 100644 (file)
@@ -545,6 +545,10 @@ int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id,
        if (it != attr_map.end()) {
                const OSLGlobals::Attribute &osl_attr = it->second;
                *elem = osl_attr.elem;
+
+               if(sd->prim == ~0 && (AttributeElement)osl_attr.elem != ATTR_ELEMENT_MESH)
+                       return ATTR_STD_NOT_FOUND;
+
                /* return result */
                return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
        }
index 8739b77ca7856c66caee90f07ac81aafb42f3cf8..fdd0a51013bcc1cefc8a6637e16e7de79e1bc740 100644 (file)
@@ -19,6 +19,7 @@
 shader node_texture_coordinate(
        normal NormalIn = N,
        int is_background = 0,
+       int is_volume = 0,
        int from_dupli = 0,
        string bump_offset = "center",
 
@@ -45,6 +46,15 @@ shader node_texture_coordinate(
                        getattribute("geom:dupli_generated", Generated); 
                        getattribute("geom:dupli_uv", UV);
                }
+               else if(is_volume) {
+                       Generated = transform("object", P);
+
+                       matrix tfm;
+                       if(getattribute("geom:generated_transform", tfm))
+                               Generated = transform(tfm, Generated);
+
+                       getattribute("geom:uv", UV);
+               }
                else {
                        getattribute("geom:generated", Generated); 
                        getattribute("geom:uv", UV);
index 3044cbf81e0ba6fbf956372e0e645146b012e000..4b1f30e55bb929b77b590714cb7321fe1d5f0a65 100644 (file)
@@ -24,21 +24,15 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, int path_f
 
        switch(type) {
                case NODE_TEXCO_OBJECT: {
-                       if(sd->object != ~0) {
-                               data = sd->P;
+                       data = sd->P;
+                       if(sd->object != ~0)
                                object_inverse_position_transform(kg, sd, &data);
-                       }
-                       else
-                               data = sd->P;
                        break;
                }
                case NODE_TEXCO_NORMAL: {
-                       if(sd->object != ~0) {
-                               data = sd->N;
+                       data = sd->N;
+                       if(sd->object != ~0)
                                object_inverse_normal_transform(kg, sd, &data);
-                       }
-                       else
-                               data = sd->N;
                        break;
                }
                case NODE_TEXCO_CAMERA: {
@@ -73,6 +67,22 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, int path_f
                        data = object_dupli_uv(kg, sd->object);
                        break;
                }
+               case NODE_TEXCO_VOLUME_GENERATED: {
+                       data = sd->P;
+
+                       if(sd->object != ~0) {
+                               AttributeElement attr_elem;
+                               int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem);
+
+                               object_inverse_position_transform(kg, sd, &data);
+
+                               if(attr_offset != ATTR_STD_NOT_FOUND) {
+                                       Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset);
+                                       data = transform_point(&tfm, data);
+                               }
+                       }
+                       break;
+               }
        }
 
        stack_store_float3(stack, out_offset, data);
@@ -85,21 +95,15 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, in
 
        switch(type) {
                case NODE_TEXCO_OBJECT: {
-                       if(sd->object != ~0) {
-                               data = sd->P + sd->dP.dx;
+                       data = sd->P + sd->dP.dx;
+                       if(sd->object != ~0)
                                object_inverse_position_transform(kg, sd, &data);
-                       }
-                       else
-                               data = sd->P + sd->dP.dx;
                        break;
                }
                case NODE_TEXCO_NORMAL: {
-                       if(sd->object != ~0) {
-                               data = sd->N;
+                       data = sd->N;
+                       if(sd->object != ~0)
                                object_inverse_normal_transform(kg, sd, &data);
-                       }
-                       else
-                               data = sd->N;
                        break;
                }
                case NODE_TEXCO_CAMERA: {
@@ -134,6 +138,22 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, in
                        data = object_dupli_uv(kg, sd->object);
                        break;
                }
+               case NODE_TEXCO_VOLUME_GENERATED: {
+                       data = sd->P + sd->dP.dx;
+
+                       if(sd->object != ~0) {
+                               AttributeElement attr_elem;
+                               int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem);
+
+                               object_inverse_position_transform(kg, sd, &data);
+
+                               if(attr_offset != ATTR_STD_NOT_FOUND) {
+                                       Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset);
+                                       data = transform_point(&tfm, data);
+                               }
+                       }
+                       break;
+               }
        }
 
        stack_store_float3(stack, out_offset, data);
@@ -149,21 +169,15 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, in
 
        switch(type) {
                case NODE_TEXCO_OBJECT: {
-                       if(sd->object != ~0) {
-                               data = sd->P + sd->dP.dy;
+                       data = sd->P + sd->dP.dy;
+                       if(sd->object != ~0)
                                object_inverse_position_transform(kg, sd, &data);
-                       }
-                       else
-                               data = sd->P + sd->dP.dy;
                        break;
                }
                case NODE_TEXCO_NORMAL: {
-                       if(sd->object != ~0) {
-                               data = sd->N;
+                       data = sd->N;
+                       if(sd->object != ~0)
                                object_inverse_normal_transform(kg, sd, &data);
-                       }
-                       else
-                               data = sd->N;
                        break;
                }
                case NODE_TEXCO_CAMERA: {
@@ -198,6 +212,22 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, in
                        data = object_dupli_uv(kg, sd->object);
                        break;
                }
+               case NODE_TEXCO_VOLUME_GENERATED: {
+                       data = sd->P + sd->dP.dy;
+
+                       if(sd->object != ~0) {
+                               AttributeElement attr_elem;
+                               int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem);
+
+                               object_inverse_position_transform(kg, sd, &data);
+
+                               if(attr_offset != ATTR_STD_NOT_FOUND) {
+                                       Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset);
+                                       data = transform_point(&tfm, data);
+                               }
+                       }
+                       break;
+               }
        }
 
        stack_store_float3(stack, out_offset, data);
index e6df5fe17b727264baab2213c1436dd0f1cc580b..9850a058611a9466ba41cdd0471ccb21cd06073e 100644 (file)
@@ -107,7 +107,8 @@ typedef enum NodeType {
 
 typedef enum NodeAttributeType {
        NODE_ATTR_FLOAT = 0,
-       NODE_ATTR_FLOAT3
+       NODE_ATTR_FLOAT3,
+       NODE_ATTR_MATRIX
 } NodeAttributeType;
 
 typedef enum NodeGeometry {
@@ -173,7 +174,8 @@ typedef enum NodeTexCoord {
        NODE_TEXCO_WINDOW,
        NODE_TEXCO_REFLECTION,
        NODE_TEXCO_DUPLI_GENERATED,
-       NODE_TEXCO_DUPLI_UV
+       NODE_TEXCO_DUPLI_UV,
+       NODE_TEXCO_VOLUME_GENERATED
 } NodeTexCoord;
 
 typedef enum NodeMix {
index 6640439eca9e3ee6520df9a1678fdd7f5ac36737..61b9cf2f3bc25ae9e1a17ba2410d03835ca342c1 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "util_debug.h"
 #include "util_foreach.h"
+#include "util_transform.h"
 
 CCL_NAMESPACE_BEGIN
 
@@ -34,7 +35,7 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
        /* string and matrix not supported! */
        assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
                type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
-               type == TypeDesc::TypeNormal);
+               type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix);
 }
 
 void Attribute::reserve(int numverts, int numtris, int numcurves, int numkeys)
@@ -60,10 +61,21 @@ void Attribute::add(const float3& f)
                buffer.push_back(data[i]);
 }
 
+void Attribute::add(const Transform& f)
+{
+       char *data = (char*)&f;
+       size_t size = sizeof(f);
+
+       for(size_t i = 0; i < size; i++)
+               buffer.push_back(data[i]);
+}
+
 size_t Attribute::data_sizeof() const
 {
        if(type == TypeDesc::TypeFloat)
                return sizeof(float);
+       else if(type == TypeDesc::TypeMatrix)
+               return sizeof(Transform);
        else
                return sizeof(float3);
 }
@@ -73,7 +85,8 @@ size_t Attribute::element_size(int numverts, int numtris, int numcurves, int num
        size_t size;
        
        switch(element) {
-               case ATTR_ELEMENT_VALUE:
+               case ATTR_ELEMENT_OBJECT:
+               case ATTR_ELEMENT_MESH:
                        size = 1;
                        break;
                case ATTR_ELEMENT_VERTEX:
@@ -151,6 +164,8 @@ const char *Attribute::standard_name(AttributeStandard std)
                return "ptex_face_id";
        else if(std == ATTR_STD_PTEX_UV)
                return "ptex_uv";
+       else if(std == ATTR_STD_GENERATED_TRANSFORM)
+               return "generated_transform";
        
        return "";
 }
@@ -256,6 +271,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
                        case ATTR_STD_PTEX_UV:
                                attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
                                break;
+                       case ATTR_STD_GENERATED_TRANSFORM:
+                               attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
+                               break;
                        default:
                                assert(0);
                                break;
@@ -274,6 +292,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
                        case ATTR_STD_CURVE_INTERCEPT:
                                attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
                                break;
+                       case ATTR_STD_GENERATED_TRANSFORM:
+                               attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
+                               break;
                        default:
                                assert(0);
                                break;
index e17a65914dd151b2a98122641f6a32004117ab82..0b8905ae5a320bce2057dbe65724df63ee720437 100644 (file)
@@ -31,6 +31,7 @@ class AttributeSet;
 class AttributeRequest;
 class AttributeRequestSet;
 class Mesh;
+struct Transform;
 
 /* Attribute
  *
@@ -57,13 +58,16 @@ public:
        char *data() { return (buffer.size())? &buffer[0]: NULL; };
        float3 *data_float3() { return (float3*)data(); }
        float *data_float() { return (float*)data(); }
+       Transform *data_transform() { return (Transform*)data(); }
 
        const char *data() const { return (buffer.size())? &buffer[0]: NULL; }
        const float3 *data_float3() const { return (const float3*)data(); }
        const float *data_float() const { return (const float*)data(); }
+       const Transform *data_transform() const { return (const Transform*)data(); }
 
        void add(const float& f);
        void add(const float3& f);
+       void add(const Transform& f);
 
        static bool same_storage(TypeDesc a, TypeDesc b);
        static const char *standard_name(AttributeStandard std);
index af57470aa89ea2fb3ebaeaf124ac04dc345a5237..4256c5ed95b0631313986b12a8ce9c580d5a1250 100644 (file)
@@ -120,8 +120,10 @@ void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
 {
        foreach(ShaderInput *input, inputs) {
                if(!input->link) {
-                       if(input->default_value == ShaderInput::TEXTURE_GENERATED)
+                       if(input->default_value == ShaderInput::TEXTURE_GENERATED) {
                                attributes->add(ATTR_STD_GENERATED);
+                               attributes->add(ATTR_STD_GENERATED_TRANSFORM); // XXX only for volumes!
+                       }
                        else if(input->default_value == ShaderInput::TEXTURE_UV)
                                attributes->add(ATTR_STD_UV);
                }
index ecae35ae5ea611ad31460cc063e1c63b2f0cd5a1..93f24886dc9aa2b633e0a20e4056a34f272f81eb 100644 (file)
@@ -466,7 +466,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
                        OSLGlobals::Attribute osl_attr;
 
                        osl_attr.type = attr.type();
-                       osl_attr.elem = ATTR_ELEMENT_VALUE;
+                       osl_attr.elem = ATTR_ELEMENT_OBJECT;
                        osl_attr.value = attr;
                        osl_attr.offset = 0;
 
@@ -493,6 +493,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
 
                                if(req.triangle_type == TypeDesc::TypeFloat)
                                        osl_attr.type = TypeDesc::TypeFloat;
+                               else if(req.triangle_type == TypeDesc::TypeMatrix)
+                                       osl_attr.type = TypeDesc::TypeMatrix;
                                else
                                        osl_attr.type = TypeDesc::TypeColor;
 
@@ -513,6 +515,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
 
                                if(req.curve_type == TypeDesc::TypeFloat)
                                        osl_attr.type = TypeDesc::TypeFloat;
+                               else if(req.curve_type == TypeDesc::TypeMatrix)
+                                       osl_attr.type = TypeDesc::TypeMatrix;
                                else
                                        osl_attr.type = TypeDesc::TypeColor;
 
@@ -580,6 +584,8 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 
                                if(req.triangle_type == TypeDesc::TypeFloat)
                                        attr_map[index].w = NODE_ATTR_FLOAT;
+                               else if(req.triangle_type == TypeDesc::TypeMatrix)
+                                       attr_map[index].w = NODE_ATTR_MATRIX;
                                else
                                        attr_map[index].w = NODE_ATTR_FLOAT3;
                        }
@@ -593,6 +599,8 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 
                                if(req.curve_type == TypeDesc::TypeFloat)
                                        attr_map[index].w = NODE_ATTR_FLOAT;
+                               else if(req.curve_type == TypeDesc::TypeMatrix)
+                                       attr_map[index].w = NODE_ATTR_MATRIX;
                                else
                                        attr_map[index].w = NODE_ATTR_FLOAT3;
                        }
@@ -645,6 +653,15 @@ static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_floa
                        for(size_t k = 0; k < size; k++)
                                attr_float[offset+k] = data[k];
                }
+               else if(mattr->type == TypeDesc::TypeMatrix) {
+                       Transform *tfm = mattr->data_transform();
+                       offset = attr_float3.size();
+
+                       attr_float3.resize(attr_float3.size() + size*4);
+
+                       for(size_t k = 0; k < size*4; k++)
+                               attr_float3[offset+k] = (&tfm->x)[k];
+               }
                else {
                        float3 *data = mattr->data_float3();
                        offset = attr_float3.size();
index c6c050cd71804a3d9735d1f392bc9cd7fe7142fb..7bd370f6b26ef24dcfece7c47b8460ed0ccf79a4 100644 (file)
@@ -2193,6 +2193,13 @@ void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attr
                }
        }
 
+       if(shader->has_volume) {
+               if(!from_dupli) {
+                       if(!output("Generated")->links.empty())
+                               attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+               }
+       }
+
        ShaderNode::attributes(shader, attributes);
 }
 
@@ -2225,6 +2232,10 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler)
                                compiler.stack_assign(out);
                                compiler.add_node(texco_node, NODE_TEXCO_DUPLI_GENERATED, out->stack_offset);
                        }
+                       else if(compiler.output_type() == SHADER_TYPE_VOLUME) {
+                               compiler.stack_assign(out);
+                               compiler.add_node(texco_node, NODE_TEXCO_VOLUME_GENERATED, out->stack_offset);
+                       }
                        else {
                                int attr = compiler.attribute(ATTR_STD_GENERATED);
                                compiler.stack_assign(out);
@@ -2294,6 +2305,8 @@ void TextureCoordinateNode::compile(OSLCompiler& compiler)
        
        if(compiler.background)
                compiler.parameter("is_background", true);
+       if(compiler.output_type() == SHADER_TYPE_VOLUME)
+               compiler.parameter("is_volume", true);
        
        compiler.parameter("from_dupli", from_dupli);