forked from bartvdbraak/blender
347 lines
7.2 KiB
C++
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
|
|
|