OpenSubdiv/opensubdiv/osdutil/topology.cpp
2013-11-06 00:13:04 -08:00

270 lines
7.5 KiB
C++

//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#include "topology.h"
#include <sstream>
#include <iostream>
using namespace std;
PxOsdUtilSubdivTopology::PxOsdUtilSubdivTopology():
name("noname"),
numVertices(0),
maxLevels(2) // arbitrary, start with a reasonable subdivision level
{
std::cout << "Creating subdiv topology object\n";
}
PxOsdUtilSubdivTopology::~PxOsdUtilSubdivTopology()
{
std::cout << "Destroying subdiv topology object\n";
}
bool
PxOsdUtilSubdivTopology::Initialize(
int numVerticesParam,
const int *nvertsParam, int numFaces,
const int *indicesParam, int indicesLen,
int levels,
string *errorMessage)
{
numVertices = numVerticesParam;
maxLevels = levels;
nverts.resize(numFaces);
for (int i=0; i<numFaces; ++i) {
nverts[i] = nvertsParam[i];
}
indices.resize(indicesLen);
for (int i=0; i<indicesLen; ++i) {
indices[i] = indicesParam[i];
}
return IsValid(errorMessage);
}
bool
PxOsdUtilSubdivTopology::IsValid(string *errorMessage) const
{
if (numVertices == 0) {
if (errorMessage) {
stringstream ss;
ss << "Topology " << name << " has no vertices";
*errorMessage = ss.str();
}
return false;
}
for (int i=0; i<(int)indices.size(); ++i) {
if ((indices[i] < 0) or
(indices[i] >= numVertices)) {
if (errorMessage) {
stringstream ss;
ss << "Topology " << name << " has bad index " << indices[i] << " at index " << i;
*errorMessage = ss.str();
}
return false;
}
}
int totalNumIndices = 0;
for (int i=0; i< (int)nverts.size(); ++i) {
if (nverts[i] < 1) {
if (errorMessage) {
stringstream ss;
ss << "Topology " << name << " has bad nverts " << nverts[i] << " at index " << i;
*errorMessage = ss.str();
}
return false;
}
totalNumIndices += nverts[i];
}
if (totalNumIndices != (int)indices.size()) {
if (errorMessage) {
*errorMessage = "Bad indexing for face topology";
}
return false;
}
std::cout << "\n";
return true;
}
void
PxOsdUtilSubdivTopology::Print() const
{
std::cout << "Mesh " << name << "\n";
std::cout << "\tnumVertices = " << numVertices << "\n";
std::cout << "\tmaxLevels = " << maxLevels << "\n";
std::cout << "\tindices ( " << indices.size() << ") : ";
for (int i=0; i<(int)indices.size(); ++i) {
std::cout << indices[i] << ", ";
}
std::cout << "\n";
std::cout << "\tnverts ( " << nverts.size() << ") : ";
for (int i=0; i<(int)nverts.size(); ++i) {
std::cout << nverts[i] << ", ";
}
std::cout << "\n";
}
bool
PxOsdUtilSubdivTopology::ReadFromObjFile( char const * fname,
vector<float> *pointPositions,
std::string *errorMessage ) {
FILE * handle = fopen( fname, "rt" );
if (not handle) {
stringstream ss;
ss << "Could not open .obj file " << fname ;
*errorMessage = ss.str();
return false;
}
fseek( handle, 0, SEEK_END );
size_t size = ftell(handle);
fseek( handle, 0, SEEK_SET );
char * shapeStr = new char[size+1];
if ( fread( shapeStr, size, 1, handle)!=1 ) {
stringstream ss;
ss << "Error reading .obj file " << fname ;
*errorMessage = ss.str();
return false;
}
fclose(handle);
shapeStr[size]='\0';
name = fname;
return ParseFromObjString(shapeStr, 1, pointPositions );
}
static char const * sgets( char * s, int size, char ** stream ) {
for (int i=0; i<size; ++i) {
if ( (*stream)[i]=='\n' or (*stream)[i]=='\0') {
memcpy(s, *stream, i);
s[i]='\0';
if ((*stream)[i]=='\0')
return 0;
else {
(*stream) += i+1;
return s;
}
}
}
return 0;
}
bool
PxOsdUtilSubdivTopology::ParseFromObjString(
char const * shapestr, int axis,
vector<float> *pointPositions,
std::string *errorMessage)
{
char * str=const_cast<char *>(shapestr), line[256];
bool done = false;
while( not done ) {
done = sgets(line, sizeof(line), &str)==0;
char* end = &line[strlen(line)-1];
if (*end == '\n')
*end = '\0'; // strip trailing nl
float x, y, z, u, v;
switch (line[0]) {
case 'v': switch (line[1]) {
case ' ':
if(sscanf(line, "v %f %f %f", &x, &y, &z) == 3) {
pointPositions->push_back(x);
switch( axis ) {
case 0 : pointPositions->push_back(-z);
pointPositions->push_back(y); break;
case 1 : pointPositions->push_back(y);
pointPositions->push_back(z); break;
}
} break;
case 't':
if(sscanf(line, "vt %f %f", &u, &v) == 2) {
//XXX:gelder
// extract UVs
// s->uvs.push_back(u);
// s->uvs.push_back(v);
} break;
case 'n' :
break; // skip normals for now
}
break;
case 'f':
if(line[1] == ' ') {
int vi, ti, ni;
const char* cp = &line[2];
while (*cp == ' ') cp++;
int numVerts = 0, nitems=0;
while( (nitems=sscanf(cp, "%d/%d/%d", &vi, &ti, &ni))>0) {
numVerts++;
indices.push_back(vi-1);
//XXX:gelder
// Extract face varying uvs
//if(nitems >= 1) s->faceuvs.push_back(ti-1);
//if(nitems >= 2) s->facenormals.push_back(ni-1);
while (*cp && *cp != ' ') cp++;
while (*cp == ' ') cp++;
}
nverts.push_back(numVerts);
}
break;
// case 't' : if(line[1] == ' ') {
// shape::tag * t = tag::parseTag( line );
// if (t)
// s->tags.push_back(t);
// } break;
}
}
numVertices = pointPositions->size()/3;
return true;
}