diff options
Diffstat (limited to 'intern/cycles/render/attribute.cpp')
-rw-r--r-- | intern/cycles/render/attribute.cpp | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp new file mode 100644 index 00000000000..815478cb733 --- /dev/null +++ b/intern/cycles/render/attribute.cpp @@ -0,0 +1,343 @@ +/* + * Copyright 2011, 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. + * + * 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. + * + * 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. + */ + +#include "mesh.h" +#include "attribute.h" + +#include "util_debug.h" +#include "util_foreach.h" + +CCL_NAMESPACE_BEGIN + +/* Attribute */ + +void Attribute::set(ustring name_, TypeDesc type_, Element element_) +{ + name = name_; + type = type_; + element = element_; + std = STD_NONE; + + /* string and matrix not supported! */ + assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor || + type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal); +} + +void Attribute::reserve(int numverts, int numtris) +{ + buffer.resize(buffer_size(numverts, numtris), 0); +} + +size_t Attribute::data_sizeof() +{ + return type.size(); +} + +size_t Attribute::element_size(int numverts, int numtris) +{ + if(element == VERTEX) + return numverts; + else if(element == FACE) + return numtris; + else + return numtris*3; +} + +size_t Attribute::buffer_size(int numverts, int numtris) +{ + return element_size(numverts, numtris)*data_sizeof(); +} + +bool Attribute::same_storage(TypeDesc a, TypeDesc b) +{ + if(a == b) + return true; + + if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint || + a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal) + if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint || + b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal) + return true; + + return false; +} + +ustring Attribute::standard_name(Attribute::Standard std) +{ + if(std == Attribute::STD_VERTEX_NORMAL) + return ustring("N"); + else if(std == Attribute::STD_FACE_NORMAL) + return ustring("Ng"); + else if(std == Attribute::STD_UV) + return ustring("uv"); + else if(std == Attribute::STD_GENERATED) + return ustring("generated"); + else if(std == Attribute::STD_POSITION_UNDEFORMED) + return ustring("undeformed"); + else if(std == Attribute::STD_POSITION_UNDISPLACED) + return ustring("undisplaced"); + + return ustring(); +} + +/* Attribute Set */ + +AttributeSet::AttributeSet(Mesh *mesh_) +{ + mesh = mesh_; +} + +AttributeSet::~AttributeSet() +{ +} + +Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element element) +{ + Attribute *attr = find(name); + + if(attr) { + /* return if same already exists */ + if(attr->type == type && attr->element == element) + return attr; + + /* overwrite attribute with same name but different type/element */ + remove(name); + } + + attributes.push_back(Attribute()); + attr = &attributes.back(); + + 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); + + attr->reserve(mesh->verts.size(), mesh->triangles.size()); + + return attr; +} + +Attribute *AttributeSet::find(ustring name) +{ + foreach(Attribute& attr, attributes) + if(attr.name == name) + return &attr; + + return NULL; +} + +void AttributeSet::remove(ustring name) +{ + Attribute *attr = find(name); + + if(attr) { + list<Attribute>::iterator it; + + for(it = attributes.begin(); it != attributes.end(); it++) { + if(&*it == attr) { + attributes.erase(it); + return; + } + } + } +} + +Attribute *AttributeSet::add(Attribute::Standard std, ustring name) +{ + Attribute *attr = NULL; + + if(name == ustring()) + name = Attribute::standard_name(std); + + if(std == Attribute::STD_VERTEX_NORMAL) + attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX); + else if(std == Attribute::STD_FACE_NORMAL) + attr = add(name, TypeDesc::TypeNormal, Attribute::FACE); + else if(std == Attribute::STD_UV) + attr = add(name, TypeDesc::TypePoint, Attribute::CORNER); + else if(std == Attribute::STD_GENERATED) + attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); + else if(std == Attribute::STD_POSITION_UNDEFORMED) + attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); + else if(std == Attribute::STD_POSITION_UNDISPLACED) + attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); + else + assert(0); + + attr->std = std; + + return attr; +} + +Attribute *AttributeSet::find(Attribute::Standard std) +{ + foreach(Attribute& attr, attributes) + if(attr.std == std) + return &attr; + + return NULL; +} + +void AttributeSet::remove(Attribute::Standard std) +{ + Attribute *attr = find(std); + + if(attr) { + list<Attribute>::iterator it; + + for(it = attributes.begin(); it != attributes.end(); it++) { + if(&*it == attr) { + attributes.erase(it); + return; + } + } + } +} + +Attribute *AttributeSet::find(AttributeRequest& req) +{ + if(req.std == Attribute::STD_NONE) + return find(req.name); + else + return find(req.std); +} + +void AttributeSet::reserve(int numverts, int numtris) +{ + foreach(Attribute& attr, attributes) + attr.reserve(numverts, numtris); +} + +void AttributeSet::clear() +{ + attributes.clear(); +} + +/* AttributeRequest */ + +AttributeRequest::AttributeRequest(ustring name_) +{ + name = name_; + std = Attribute::STD_NONE; + + type = TypeDesc::TypeFloat; + element = ATTR_ELEMENT_NONE; + offset = 0; +} + +AttributeRequest::AttributeRequest(Attribute::Standard std_) +{ + name = ustring(); + std = std_; + + type = TypeDesc::TypeFloat; + element = ATTR_ELEMENT_NONE; + offset = 0; +} + +/* AttributeRequestSet */ + +AttributeRequestSet::AttributeRequestSet() +{ +} + +AttributeRequestSet::~AttributeRequestSet() +{ +} + +bool AttributeRequestSet::modified(const AttributeRequestSet& other) +{ + if(requests.size() != other.requests.size()) + return true; + + for(size_t i = 0; i < requests.size(); i++) { + bool found = false; + + for(size_t j = 0; j < requests.size() && !found; j++) + if(requests[i].name == other.requests[j].name && + requests[i].std == other.requests[j].std) + found = true; + + if(!found) + return true; + } + + return false; +} + +void AttributeRequestSet::add(ustring name) +{ + foreach(AttributeRequest& req, requests) + if(req.name == name) + return; + + requests.push_back(AttributeRequest(name)); +} + +void AttributeRequestSet::add(Attribute::Standard std) +{ + foreach(AttributeRequest& req, requests) + if(req.std == std) + return; + + requests.push_back(AttributeRequest(std)); +} + +void AttributeRequestSet::add(AttributeRequestSet& reqs) +{ + foreach(AttributeRequest& req, reqs.requests) { + if(req.std == Attribute::STD_NONE) + add(req.name); + else + add(req.std); + } +} + +bool AttributeRequestSet::find(ustring name) +{ + foreach(AttributeRequest& req, requests) + if(req.name == name) + return true; + + return false; +} + +bool AttributeRequestSet::find(Attribute::Standard std) +{ + foreach(AttributeRequest& req, requests) + if(req.std == std) + return true; + + return false; +} + +size_t AttributeRequestSet::size() +{ + return requests.size(); +} + +void AttributeRequestSet::clear() +{ + requests.clear(); +} + +CCL_NAMESPACE_END + |