blender/intern/cycles/render/attribute.cpp
2011-05-31 11:31:00 +00:00

347 lines
7.2 KiB
C++

/*
* 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()
{
if(type == TypeDesc::TypeFloat)
return sizeof(float);
else
return sizeof(float3);
}
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