Cycles: Make all #include statements relative to cycles source directory
[blender.git] / intern / cycles / render / attribute.cpp
index 3137ea5327bcd1fdf8ceb297310554addc8d9605..e157a385904ad8809f1d3d553177ecb8147a159b 100644 (file)
@@ -1,47 +1,70 @@
 /*
- * Copyright 2011, Blender Foundation.
+ * Copyright 2011-2013 Blender Foundation
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-#include "mesh.h"
-#include "attribute.h"
+#include "render/image.h"
+#include "render/mesh.h"
+#include "render/attribute.h"
 
-#include "util_debug.h"
-#include "util_foreach.h"
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_transform.h"
 
 CCL_NAMESPACE_BEGIN
 
 /* Attribute */
 
+Attribute::~Attribute()
+{
+       /* for voxel data, we need to remove the image from the image manager */
+       if(element == ATTR_ELEMENT_VOXEL) {
+               VoxelAttribute *voxel_data = data_voxel();
+
+               if(voxel_data && voxel_data->slot != -1) {
+                       voxel_data->manager->remove_image(voxel_data->slot);
+               }
+       }
+}
+
 void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
 {
        name = name_;
        type = type_;
        element = element_;
        std = ATTR_STD_NONE;
+       flags = 0;
 
        /* 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)
+void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only)
 {
-       buffer.resize(buffer_size(numverts, numtris, numcurves, numkeys), 0);
+       if(reserve_only) {
+               buffer.reserve(buffer_size(mesh, prim));
+       }
+       else {
+               buffer.resize(buffer_size(mesh, prim), 0);
+       }
+}
+
+void Attribute::resize(size_t num_elements)
+{
+       buffer.resize(num_elements * data_sizeof(), 0);
 }
 
 void Attribute::add(const float& f)
@@ -53,6 +76,15 @@ void Attribute::add(const float& f)
                buffer.push_back(data[i]);
 }
 
+void Attribute::add(const uchar4& f)
+{
+       char *data = (char*)&f;
+       size_t size = sizeof(f);
+
+       for(size_t i = 0; i < size; i++)
+               buffer.push_back(data[i]);
+}
+
 void Attribute::add(const float3& f)
 {
        char *data = (char*)&f;
@@ -62,48 +94,109 @@ 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]);
+}
+
+void Attribute::add(const VoxelAttribute& f)
+{
+       char *data = (char*)&f;
+       size_t size = sizeof(f);
+
+       for(size_t i = 0; i < size; i++)
+               buffer.push_back(data[i]);
+}
+
+void Attribute::add(const char *data)
+{
+       size_t size = data_sizeof();
+
+       for(size_t i = 0; i < size; i++)
+               buffer.push_back(data[i]);
+}
+
 size_t Attribute::data_sizeof() const
 {
-       if(type == TypeDesc::TypeFloat)
+       if(element == ATTR_ELEMENT_VOXEL)
+               return sizeof(VoxelAttribute);
+       else if(element == ATTR_ELEMENT_CORNER_BYTE)
+               return sizeof(uchar4);
+       else if(type == TypeDesc::TypeFloat)
                return sizeof(float);
+       else if(type == TypeDesc::TypeMatrix)
+               return sizeof(Transform);
        else
                return sizeof(float3);
 }
 
-size_t Attribute::element_size(int numverts, int numtris, int numcurves, int numkeys) const
+size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const
 {
+       if(flags & ATTR_FINAL_SIZE) {
+               return buffer.size() / data_sizeof();
+       }
+
        size_t size;
-       
+
        switch(element) {
-               case ATTR_ELEMENT_VALUE:
+               case ATTR_ELEMENT_OBJECT:
+               case ATTR_ELEMENT_MESH:
+               case ATTR_ELEMENT_VOXEL:
                        size = 1;
                        break;
                case ATTR_ELEMENT_VERTEX:
-                       size = numverts;
+                       size = mesh->verts.size() + mesh->num_ngons;
+                       if(prim == ATTR_PRIM_SUBD) {
+                               size -= mesh->num_subd_verts;
+                       }
+                       break;
+               case ATTR_ELEMENT_VERTEX_MOTION:
+                       size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1);
+                       if(prim == ATTR_PRIM_SUBD) {
+                               size -= mesh->num_subd_verts * (mesh->motion_steps - 1);
+                       }
                        break;
                case ATTR_ELEMENT_FACE:
-                       size = numtris;
+                       if(prim == ATTR_PRIM_TRIANGLE) {
+                               size = mesh->num_triangles();
+                       }
+                       else {
+                               size = mesh->subd_faces.size() + mesh->num_ngons;
+                       }
                        break;
                case ATTR_ELEMENT_CORNER:
-                       size = numtris*3;
+               case ATTR_ELEMENT_CORNER_BYTE:
+                       if(prim == ATTR_PRIM_TRIANGLE) {
+                               size = mesh->num_triangles()*3;
+                       }
+                       else {
+                               size = mesh->subd_face_corners.size() + mesh->num_ngons;
+                       }
                        break;
                case ATTR_ELEMENT_CURVE:
-                       size = numcurves;
+                       size = mesh->num_curves();
                        break;
                case ATTR_ELEMENT_CURVE_KEY:
-                       size = numkeys;
+                       size = mesh->curve_keys.size();
+                       break;
+               case ATTR_ELEMENT_CURVE_KEY_MOTION:
+                       size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
                        break;
                default:
                        size = 0;
                        break;
        }
-       
+
        return size;
 }
 
-size_t Attribute::buffer_size(int numverts, int numtris, int numcurves, int numkeys) const
+size_t Attribute::buffer_size(Mesh *mesh, AttributePrimitive prim) const
 {
-       return element_size(numverts, numtris, numcurves, numkeys)*data_sizeof();
+       return element_size(mesh, prim)*data_sizeof();
 }
 
 bool Attribute::same_storage(TypeDesc a, TypeDesc b)
@@ -123,44 +216,99 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b)
        return false;
 }
 
+void Attribute::zero_data(void* dst)
+{
+       memset(dst, 0, data_sizeof());
+}
+
+void Attribute::add_with_weight(void* dst, void* src, float weight)
+{
+       if(element == ATTR_ELEMENT_CORNER_BYTE) {
+               for(int i = 0; i < 4; i++) {
+                       ((uchar*)dst)[i] += uchar(((uchar*)src)[i] * weight);
+               }
+       }
+       else if(same_storage(type, TypeDesc::TypeFloat)) {
+               *((float*)dst) += *((float*)src) * weight;
+       }
+       else if(same_storage(type, TypeDesc::TypeVector)) {
+               *((float4*)dst) += *((float4*)src) * weight;
+       }
+       else {
+               assert(!"not implemented for this type");
+       }
+}
+
 const char *Attribute::standard_name(AttributeStandard std)
 {
-       if(std == ATTR_STD_VERTEX_NORMAL)
-               return "N";
-       else if(std == ATTR_STD_FACE_NORMAL)
-               return "Ng";
-       else if(std == ATTR_STD_UV)
-               return "uv";
-       else if(std == ATTR_STD_GENERATED)
-               return "generated";
-       else if(std == ATTR_STD_UV_TANGENT)
-               return "tangent";
-       else if(std == ATTR_STD_UV_TANGENT_SIGN)
-               return "tangent_sign";
-       else if(std == ATTR_STD_POSITION_UNDEFORMED)
-               return "undeformed";
-       else if(std == ATTR_STD_POSITION_UNDISPLACED)
-               return "undisplaced";
-       else if(std == ATTR_STD_MOTION_PRE)
-               return "motion_pre";
-       else if(std == ATTR_STD_MOTION_POST)
-               return "motion_post";
-       else if(std == ATTR_STD_PARTICLE)
-               return "particle";
-       else if(std == ATTR_STD_CURVE_TANGENT)
-               return "curve_tangent";
-       else if(std == ATTR_STD_CURVE_INTERCEPT)
-               return "curve_intercept";
+       switch(std) {
+               case ATTR_STD_VERTEX_NORMAL:
+                       return "N";
+               case ATTR_STD_FACE_NORMAL:
+                       return "Ng";
+               case ATTR_STD_UV:
+                       return "uv";
+               case ATTR_STD_GENERATED:
+                       return "generated";
+               case ATTR_STD_GENERATED_TRANSFORM:
+                       return "generated_transform";
+               case ATTR_STD_UV_TANGENT:
+                       return "tangent";
+               case ATTR_STD_UV_TANGENT_SIGN:
+                       return "tangent_sign";
+               case ATTR_STD_POSITION_UNDEFORMED:
+                       return "undeformed";
+               case ATTR_STD_POSITION_UNDISPLACED:
+                       return "undisplaced";
+               case ATTR_STD_MOTION_VERTEX_POSITION:
+                       return "motion_P";
+               case ATTR_STD_MOTION_VERTEX_NORMAL:
+                       return "motion_N";
+               case ATTR_STD_PARTICLE:
+                       return "particle";
+               case ATTR_STD_CURVE_INTERCEPT:
+                       return "curve_intercept";
+               case ATTR_STD_PTEX_FACE_ID:
+                       return "ptex_face_id";
+               case ATTR_STD_PTEX_UV:
+                       return "ptex_uv";
+               case ATTR_STD_VOLUME_DENSITY:
+                       return "density";
+               case ATTR_STD_VOLUME_COLOR:
+                       return "color";
+               case ATTR_STD_VOLUME_FLAME:
+                       return "flame";
+               case ATTR_STD_VOLUME_HEAT:
+                       return "heat";
+               case ATTR_STD_VOLUME_VELOCITY:
+                       return "velocity";
+               case ATTR_STD_POINTINESS:
+                       return "pointiness";
+               case ATTR_STD_NOT_FOUND:
+               case ATTR_STD_NONE:
+               case ATTR_STD_NUM:
+                       return "";
+       }
        
        return "";
 }
 
+AttributeStandard Attribute::name_standard(const char *name)
+{
+       for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
+               if(strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0)
+                       return (AttributeStandard)std;
+
+       return ATTR_STD_NONE;
+}
+
 /* Attribute Set */
 
 AttributeSet::AttributeSet()
 {
        triangle_mesh = NULL;
        curve_mesh = NULL;
+       subd_mesh = NULL;
 }
 
 AttributeSet::~AttributeSet()
@@ -180,17 +328,27 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme
                remove(name);
        }
 
-       attributes.push_back(Attribute());
+#if __cplusplus >= 201103L
+       attributes.emplace_back();
        attr = &attributes.back();
-
        attr->set(name, type, element);
-       
+#else
+       {
+               Attribute attr_temp;
+               attr_temp.set(name, type, element);
+               attributes.push_back(attr_temp);
+               attr = &attributes.back();
+       }
+#endif
+
        /* this is weak .. */
        if(triangle_mesh)
-               attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
+               attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false);
        if(curve_mesh)
-               attr->reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
-       
+               attr->resize(curve_mesh, ATTR_PRIM_CURVE, false);
+       if(subd_mesh)
+               attr->resize(subd_mesh, ATTR_PRIM_SUBD, false);
+
        return attr;
 }
 
@@ -226,7 +384,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
        if(name == ustring())
                name = Attribute::standard_name(std);
 
-       if(triangle_mesh) {
+       if(triangle_mesh || subd_mesh) {
                switch(std) {
                        case ATTR_STD_VERTEX_NORMAL:
                                attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
@@ -244,20 +402,39 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
                                attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
                                break;
                        case ATTR_STD_GENERATED:
-                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
-                               break;
                        case ATTR_STD_POSITION_UNDEFORMED:
-                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
-                               break;
                        case ATTR_STD_POSITION_UNDISPLACED:
                                attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
                                break;
-                       case ATTR_STD_MOTION_PRE:
-                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+                       case ATTR_STD_MOTION_VERTEX_POSITION:
+                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
+                               break;
+                       case ATTR_STD_MOTION_VERTEX_NORMAL:
+                               attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
+                               break;
+                       case ATTR_STD_PTEX_FACE_ID:
+                               attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
                                break;
-                       case ATTR_STD_MOTION_POST:
+                       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;
+                       case ATTR_STD_VOLUME_DENSITY:
+                       case ATTR_STD_VOLUME_FLAME:
+                       case ATTR_STD_VOLUME_HEAT:
+                               attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
+                               break;
+                       case ATTR_STD_VOLUME_COLOR:
+                               attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
+                               break;
+                       case ATTR_STD_VOLUME_VELOCITY:
+                               attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
+                               break;
+                       case ATTR_STD_POINTINESS:
+                               attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
+                               break;
                        default:
                                assert(0);
                                break;
@@ -266,23 +443,21 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
        else if(curve_mesh) {
                switch(std) {
                        case ATTR_STD_UV:
-                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
-                               break;
                        case ATTR_STD_GENERATED:
                                attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
                                break;
-                       case ATTR_STD_MOTION_PRE:
-                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
-                               break;
-                       case ATTR_STD_MOTION_POST:
-                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
-                               break;
-                       case ATTR_STD_CURVE_TANGENT:
-                               attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CURVE_KEY);
+                       case ATTR_STD_MOTION_VERTEX_POSITION:
+                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
                                break;
                        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;
+                       case ATTR_STD_POINTINESS:
+                               attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
+                               break;
                        default:
                                assert(0);
                                break;
@@ -327,13 +502,15 @@ Attribute *AttributeSet::find(AttributeRequest& req)
                return find(req.std);
 }
 
-void AttributeSet::reserve()
+void AttributeSet::resize(bool reserve_only)
 {
        foreach(Attribute& attr, attributes) {
                if(triangle_mesh)
-                       attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
+                       attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only);
                if(curve_mesh)
-                       attr.reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
+                       attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only);
+               if(subd_mesh)
+                       attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only);
        }
 }
 
@@ -350,12 +527,19 @@ AttributeRequest::AttributeRequest(ustring name_)
        std = ATTR_STD_NONE;
 
        triangle_type = TypeDesc::TypeFloat;
-       triangle_element = ATTR_ELEMENT_NONE;
-       triangle_offset = 0;
+       triangle_desc.element = ATTR_ELEMENT_NONE;
+       triangle_desc.offset = 0;
+       triangle_desc.type = NODE_ATTR_FLOAT;
 
        curve_type = TypeDesc::TypeFloat;
-       curve_element = ATTR_ELEMENT_NONE;
-       curve_offset = 0;
+       curve_desc.element = ATTR_ELEMENT_NONE;
+       curve_desc.offset = 0;
+       curve_desc.type = NODE_ATTR_FLOAT;
+
+       subd_type = TypeDesc::TypeFloat;
+       subd_desc.element = ATTR_ELEMENT_NONE;
+       subd_desc.offset = 0;
+       subd_desc.type = NODE_ATTR_FLOAT;
 }
 
 AttributeRequest::AttributeRequest(AttributeStandard std_)
@@ -364,12 +548,19 @@ AttributeRequest::AttributeRequest(AttributeStandard std_)
        std = std_;
 
        triangle_type = TypeDesc::TypeFloat;
-       triangle_element = ATTR_ELEMENT_NONE;
-       triangle_offset = 0;
+       triangle_desc.element = ATTR_ELEMENT_NONE;
+       triangle_desc.offset = 0;
+       triangle_desc.type = NODE_ATTR_FLOAT;
 
        curve_type = TypeDesc::TypeFloat;
-       curve_element = ATTR_ELEMENT_NONE;
-       curve_offset = 0;
+       curve_desc.element = ATTR_ELEMENT_NONE;
+       curve_desc.offset = 0;
+       curve_desc.type = NODE_ATTR_FLOAT;
+
+       subd_type = TypeDesc::TypeFloat;
+       subd_desc.element = ATTR_ELEMENT_NONE;
+       subd_desc.offset = 0;
+       subd_desc.type = NODE_ATTR_FLOAT;
 }
 
 /* AttributeRequestSet */