Cycles: Make all #include statements relative to cycles source directory
[blender.git] / intern / cycles / render / attribute.cpp
index 5c7966d6d96f02993b6598d92c353f03eb64bc2e..e157a385904ad8809f1d3d553177ecb8147a159b 100644 (file)
 /*
- * 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 */
 
-void Attribute::set(ustring name_, TypeDesc type_, Element element_)
+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::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only)
+{
+       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)
+{
+       char *data = (char*)&f;
+       size_t size = sizeof(f);
+
+       for(size_t i = 0; i < size; i++)
+               buffer.push_back(data[i]);
 }
 
-void Attribute::reserve(int numverts, int numtris)
+void Attribute::add(const uchar4& f)
 {
-       buffer.resize(buffer_size(numverts, numtris), 0);
+       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()
+void Attribute::add(const float3& f)
 {
-       if(type == TypeDesc::TypeFloat)
+       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 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(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)
+size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const
 {
-       if(element == VERTEX)
-               return numverts;
-       else if(element == FACE)
-               return numtris;
-       else
-               return numtris*3;
+       if(flags & ATTR_FINAL_SIZE) {
+               return buffer.size() / data_sizeof();
+       }
+
+       size_t size;
+
+       switch(element) {
+               case ATTR_ELEMENT_OBJECT:
+               case ATTR_ELEMENT_MESH:
+               case ATTR_ELEMENT_VOXEL:
+                       size = 1;
+                       break;
+               case ATTR_ELEMENT_VERTEX:
+                       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:
+                       if(prim == ATTR_PRIM_TRIANGLE) {
+                               size = mesh->num_triangles();
+                       }
+                       else {
+                               size = mesh->subd_faces.size() + mesh->num_ngons;
+                       }
+                       break;
+               case ATTR_ELEMENT_CORNER:
+               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 = mesh->num_curves();
+                       break;
+               case ATTR_ELEMENT_CURVE_KEY:
+                       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)
+size_t Attribute::buffer_size(Mesh *mesh, AttributePrimitive prim) const
 {
-       return element_size(numverts, numtris)*data_sizeof();
+       return element_size(mesh, prim)*data_sizeof();
 }
 
 bool Attribute::same_storage(TypeDesc a, TypeDesc b)
@@ -84,40 +216,106 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b)
        return false;
 }
 
-ustring Attribute::standard_name(AttributeStandard std)
+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)
+{
+       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)
 {
-       if(std == ATTR_STD_VERTEX_NORMAL)
-               return ustring("N");
-       else if(std == ATTR_STD_FACE_NORMAL)
-               return ustring("Ng");
-       else if(std == ATTR_STD_UV)
-               return ustring("uv");
-       else if(std == ATTR_STD_GENERATED)
-               return ustring("generated");
-       else if(std == ATTR_STD_POSITION_UNDEFORMED)
-               return ustring("undeformed");
-       else if(std == ATTR_STD_POSITION_UNDISPLACED)
-               return ustring("undisplaced");
-       else if(std == ATTR_STD_MOTION_PRE)
-               return ustring("motion_pre");
-       else if(std == ATTR_STD_MOTION_POST)
-               return ustring("motion_post");
+       for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
+               if(strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0)
+                       return (AttributeStandard)std;
 
-       return ustring();
+       return ATTR_STD_NONE;
 }
 
 /* Attribute Set */
 
 AttributeSet::AttributeSet()
 {
-       mesh = NULL;
+       triangle_mesh = NULL;
+       curve_mesh = NULL;
+       subd_mesh = NULL;
 }
 
 AttributeSet::~AttributeSet()
 {
 }
 
-Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element element)
+Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
 {
        Attribute *attr = find(name);
 
@@ -130,27 +328,35 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element ele
                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->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false);
+       if(curve_mesh)
+               attr->resize(curve_mesh, ATTR_PRIM_CURVE, false);
+       if(subd_mesh)
+               attr->resize(subd_mesh, ATTR_PRIM_SUBD, false);
 
-       if(element == Attribute::VERTEX)
-               attr->set(name, type, element);
-       else if(element == Attribute::FACE)
-               attr->set(name, type, element);
-       else if(element == Attribute::CORNER)
-               attr->set(name, type, element);
-       
-       if(mesh)
-               attr->reserve(mesh->verts.size(), mesh->triangles.size());
-       
        return attr;
 }
 
-Attribute *AttributeSet::find(ustring name)
+Attribute *AttributeSet::find(ustring name) const
 {
-       foreach(Attribute& attr, attributes)
+       foreach(const Attribute& attr, attributes)
                if(attr.name == name)
-                       return &attr;
+                       return (Attribute*)&attr;
 
        return NULL;
 }
@@ -178,35 +384,96 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
        if(name == ustring())
                name = Attribute::standard_name(std);
 
-       if(std == ATTR_STD_VERTEX_NORMAL)
-               attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX);
-       else if(std == ATTR_STD_FACE_NORMAL)
-               attr = add(name, TypeDesc::TypeNormal, Attribute::FACE);
-       else if(std == ATTR_STD_UV)
-               attr = add(name, TypeDesc::TypePoint, Attribute::CORNER);
-       else if(std == ATTR_STD_GENERATED)
-               attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
-       else if(std == ATTR_STD_POSITION_UNDEFORMED)
-               attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
-       else if(std == ATTR_STD_POSITION_UNDISPLACED)
-               attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
-       else if(std == ATTR_STD_MOTION_PRE)
-               attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
-       else if(std == ATTR_STD_MOTION_POST)
-               attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
-       else
-               assert(0);
+       if(triangle_mesh || subd_mesh) {
+               switch(std) {
+                       case ATTR_STD_VERTEX_NORMAL:
+                               attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
+                               break;
+                       case ATTR_STD_FACE_NORMAL:
+                               attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
+                               break;
+                       case ATTR_STD_UV:
+                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
+                               break;
+                       case ATTR_STD_UV_TANGENT:
+                               attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
+                               break;
+                       case ATTR_STD_UV_TANGENT_SIGN:
+                               attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
+                               break;
+                       case ATTR_STD_GENERATED:
+                       case ATTR_STD_POSITION_UNDEFORMED:
+                       case ATTR_STD_POSITION_UNDISPLACED:
+                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+                               break;
+                       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_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;
+               }
+       }
+       else if(curve_mesh) {
+               switch(std) {
+                       case ATTR_STD_UV:
+                       case ATTR_STD_GENERATED:
+                               attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
+                               break;
+                       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;
+               }
+       }
 
        attr->std = std;
        
        return attr;
 }
 
-Attribute *AttributeSet::find(AttributeStandard std)
+Attribute *AttributeSet::find(AttributeStandard std) const
 {
-       foreach(Attribute& attr, attributes)
+       foreach(const Attribute& attr, attributes)
                if(attr.std == std)
-                       return &attr;
+                       return (Attribute*)&attr;
 
        return NULL;
 }
@@ -235,10 +502,16 @@ Attribute *AttributeSet::find(AttributeRequest& req)
                return find(req.std);
 }
 
-void AttributeSet::reserve(int numverts, int numtris)
+void AttributeSet::resize(bool reserve_only)
 {
-       foreach(Attribute& attr, attributes)
-               attr.reserve(numverts, numtris);
+       foreach(Attribute& attr, attributes) {
+               if(triangle_mesh)
+                       attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only);
+               if(curve_mesh)
+                       attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only);
+               if(subd_mesh)
+                       attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only);
+       }
 }
 
 void AttributeSet::clear()
@@ -253,9 +526,20 @@ AttributeRequest::AttributeRequest(ustring name_)
        name = name_;
        std = ATTR_STD_NONE;
 
-       type = TypeDesc::TypeFloat;
-       element = ATTR_ELEMENT_NONE;
-       offset = 0;
+       triangle_type = TypeDesc::TypeFloat;
+       triangle_desc.element = ATTR_ELEMENT_NONE;
+       triangle_desc.offset = 0;
+       triangle_desc.type = NODE_ATTR_FLOAT;
+
+       curve_type = TypeDesc::TypeFloat;
+       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_)
@@ -263,9 +547,20 @@ AttributeRequest::AttributeRequest(AttributeStandard std_)
        name = ustring();
        std = std_;
 
-       type = TypeDesc::TypeFloat;
-       element = ATTR_ELEMENT_NONE;
-       offset = 0;
+       triangle_type = TypeDesc::TypeFloat;
+       triangle_desc.element = ATTR_ELEMENT_NONE;
+       triangle_desc.offset = 0;
+       triangle_desc.type = NODE_ATTR_FLOAT;
+
+       curve_type = TypeDesc::TypeFloat;
+       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 */