Updated cmodtools:
- Removed normal generation code from convert3ds.cpp; use the (better) normal generator in cmodops.cpp instead. - Removed nonfunctional code to use smoothing groups - Added background color chooser for cmodview - Enabled automatic uniquification and better normal generation when converting 3ds to cmod in cmodview and 3dstocmod utilities.sensor-dev
parent
faedefec0e
commit
e8928c86cc
|
@ -10,6 +10,7 @@
|
|||
// Convert a 3DS file to a Celestia mesh (.cmod) file
|
||||
|
||||
#include "convert3ds.h"
|
||||
#include "cmodops.h"
|
||||
#include <celmodel/modelfile.h>
|
||||
#include <cel3ds/3dsread.h>
|
||||
#include <cstring>
|
||||
|
@ -53,6 +54,29 @@ int main(int argc, char* argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Generate normals for the model
|
||||
double smoothAngle = 45.0; // degrees
|
||||
double weldTolerance = 1.0e-6;
|
||||
bool weldVertices = true;
|
||||
|
||||
Model* newModel = GenerateModelNormals(*model, float(smoothAngle * 3.14159265 / 180.0), weldVertices, weldTolerance);
|
||||
delete model;
|
||||
|
||||
if (!newModel)
|
||||
{
|
||||
cerr << "Ran out of memory while generating surface normals.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Automatically uniquify vertices
|
||||
for (unsigned int i = 0; newModel->getMesh(i) != NULL; i++)
|
||||
{
|
||||
Mesh* mesh = newModel->getMesh(i);
|
||||
UniquifyVertices(*mesh);
|
||||
}
|
||||
|
||||
model = newModel;
|
||||
|
||||
#if 0
|
||||
// Print information about primitive groups
|
||||
for (uint32 i = 0; model->getMesh(i); i++)
|
||||
|
|
|
@ -1236,6 +1236,72 @@ MergeModelMeshes(const Model& model)
|
|||
}
|
||||
|
||||
|
||||
static Material*
|
||||
cloneMaterial(const Material* other)
|
||||
{
|
||||
Material* material = new Material();
|
||||
material->diffuse = other->diffuse;
|
||||
material->specular = other->specular;
|
||||
material->emissive = other->emissive;
|
||||
material->specularPower = other->specularPower;
|
||||
material->opacity = other->opacity;
|
||||
material->blend = other->blend;
|
||||
for (int i = 0; i < Material::TextureSemanticMax; ++i)
|
||||
{
|
||||
if (other->maps[i])
|
||||
{
|
||||
material->maps[i] = new Material::DefaultTextureResource(other->maps[i]->source());
|
||||
}
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
|
||||
/*! Generate normals for an entire model. Return the new model, or null if
|
||||
* normal generation failed due to an out of memory error.
|
||||
*/
|
||||
Model*
|
||||
GenerateModelNormals(const Model& model, float smoothAngle, bool weldVertices, float weldTolerance)
|
||||
{
|
||||
Model* newModel = new Model();
|
||||
|
||||
// Copy materials
|
||||
for (unsigned int i = 0; model.getMaterial(i) != NULL; i++)
|
||||
{
|
||||
newModel->addMaterial(cloneMaterial(model.getMaterial(i)));
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
for (unsigned int i = 0; model.getMesh(i) != NULL; i++)
|
||||
{
|
||||
Mesh* mesh = model.getMesh(i);
|
||||
Mesh* newMesh = NULL;
|
||||
|
||||
newMesh = GenerateNormals(*mesh, smoothAngle, weldVertices, weldTolerance);
|
||||
if (newMesh == NULL)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
newModel->addMesh(newMesh);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
// If all of the meshes weren't processed due to an out of memory error,
|
||||
// delete the new model and return NULL rather than a partially processed
|
||||
// model.
|
||||
delete newModel;
|
||||
newModel = NULL;
|
||||
}
|
||||
|
||||
return newModel;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TRISTRIP
|
||||
bool
|
||||
convertToStrips(Mesh& mesh)
|
||||
|
|
|
@ -39,10 +39,15 @@ struct Face
|
|||
};
|
||||
|
||||
|
||||
// Mesh operations
|
||||
extern cmod::Mesh* GenerateNormals(const cmod::Mesh& mesh, float smoothAngle, bool weld, float weldTolerance = 0.0f);
|
||||
extern cmod::Mesh* GenerateTangents(const cmod::Mesh& mesh, bool weld);
|
||||
extern bool UniquifyVertices(cmod::Mesh& mesh);
|
||||
|
||||
// Model operations
|
||||
extern cmod::Model* MergeModelMeshes(const cmod::Model& model);
|
||||
extern cmod::Model* GenerateModelNormals(const cmod::Model& model, float smoothAngle, bool weldVertices, float weldTolerance);
|
||||
|
||||
|
||||
template<typename T, typename U> void
|
||||
JoinVertices(std::vector<Face>& faces,
|
||||
|
@ -86,10 +91,10 @@ JoinVertices(std::vector<Face>& faces,
|
|||
uint32 uniqueCount = 0;
|
||||
for (uint32 i = 0; i < nVertices; i++)
|
||||
{
|
||||
if (i == 0 || !equivalencePredicate(vertices[i - 1], vertices[i]))
|
||||
{
|
||||
if (i == 0 || !equivalencePredicate(vertices[i - 1], vertices[i]))
|
||||
{
|
||||
lastUnique = i;
|
||||
uniqueCount++;
|
||||
uniqueCount++;
|
||||
}
|
||||
|
||||
mergeMap[vertices[i].index] = vertices[lastUnique].index;
|
||||
|
@ -99,7 +104,9 @@ JoinVertices(std::vector<Face>& faces,
|
|||
for (f = 0; f < faces.size(); f++)
|
||||
{
|
||||
for (uint32 k= 0; k < 3; k++)
|
||||
{
|
||||
faces[f].vi[k] = mergeMap[faces[f].i[k]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,178 +55,33 @@ Convert3DSMesh(Model& model,
|
|||
const M3DScene& scene,
|
||||
const string& meshName)
|
||||
{
|
||||
int nFaces = mesh3ds.getFaceCount();
|
||||
int nVertices = mesh3ds.getVertexCount();
|
||||
int nTexCoords = mesh3ds.getTexCoordCount();
|
||||
bool smooth = (mesh3ds.getSmoothingGroupCount() == nFaces);
|
||||
bool hasTexCoords = (nTexCoords == nVertices);
|
||||
int vertexSize = hasTexCoords ? 8 : 6;
|
||||
int i;
|
||||
|
||||
Vector3f* faceNormals = new Vector3f[nFaces];
|
||||
Vector3f* vertexNormals = new Vector3f[nFaces * 3];
|
||||
int* faceCounts = new int[nVertices];
|
||||
int** vertexFaces = new int*[nVertices];
|
||||
|
||||
int nOutputVertices = nFaces * 3;
|
||||
float* vertices = new float[nOutputVertices * vertexSize];
|
||||
|
||||
|
||||
for (i = 0; i < nVertices; i++)
|
||||
bool hasTexCoords = (nTexCoords >= nVertices);
|
||||
int vertexSize = 3;
|
||||
if (hasTexCoords)
|
||||
{
|
||||
faceCounts[i] = 0;
|
||||
vertexFaces[i] = NULL;
|
||||
vertexSize += 2;
|
||||
}
|
||||
|
||||
// generate face normals
|
||||
for (i = 0; i < nFaces; i++)
|
||||
float* vertices = new float[mesh3ds.getVertexCount() * vertexSize];
|
||||
|
||||
// Build the vertex list
|
||||
for (int i = 0; i < mesh3ds.getVertexCount(); ++i)
|
||||
{
|
||||
uint16 v0, v1, v2;
|
||||
mesh3ds.getFace(i, v0, v1, v2);
|
||||
int k = i * vertexSize;
|
||||
Vector3f pos = mesh3ds.getVertex(i);
|
||||
vertices[k + 0] = pos.x();
|
||||
vertices[k + 1] = pos.y();
|
||||
vertices[k + 2] = pos.z();
|
||||
|
||||
faceCounts[v0]++;
|
||||
faceCounts[v1]++;
|
||||
faceCounts[v2]++;
|
||||
|
||||
Vector3f p0 = mesh3ds.getVertex(v0);
|
||||
Vector3f p1 = mesh3ds.getVertex(v1);
|
||||
Vector3f p2 = mesh3ds.getVertex(v2);
|
||||
faceNormals[i] = (p1 - p0).cross(p2 - p1);
|
||||
faceNormals[i].normalize();
|
||||
}
|
||||
|
||||
if (!smooth && 0)
|
||||
{
|
||||
for (i = 0; i < nFaces; i++)
|
||||
if (hasTexCoords)
|
||||
{
|
||||
vertexNormals[i * 3] = faceNormals[i];
|
||||
vertexNormals[i * 3 + 1] = faceNormals[i];
|
||||
vertexNormals[i * 3 + 2] = faceNormals[i];
|
||||
Vector2f texCoord = mesh3ds.getTexCoord(i);
|
||||
vertices[k + 3] = texCoord.x();
|
||||
vertices[k + 4] = texCoord.y();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// allocate space for vertex face indices
|
||||
for (i = 0; i < nVertices; i++)
|
||||
{
|
||||
vertexFaces[i] = new int[faceCounts[i] + 1];
|
||||
vertexFaces[i][0] = faceCounts[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < nFaces; i++)
|
||||
{
|
||||
uint16 v0, v1, v2;
|
||||
mesh3ds.getFace(i, v0, v1, v2);
|
||||
vertexFaces[v0][faceCounts[v0]--] = i;
|
||||
vertexFaces[v1][faceCounts[v1]--] = i;
|
||||
vertexFaces[v2][faceCounts[v2]--] = i;
|
||||
}
|
||||
|
||||
// average face normals to compute the vertex normals
|
||||
for (i = 0; i < nFaces; i++)
|
||||
{
|
||||
uint16 v0, v1, v2;
|
||||
mesh3ds.getFace(i, v0, v1, v2);
|
||||
// uint32 smoothingGroups = mesh3ds.getSmoothingGroups(i);
|
||||
|
||||
int j;
|
||||
Vector3f v = Vector3f(0, 0, 0);
|
||||
for (j = 1; j <= vertexFaces[v0][0]; j++)
|
||||
{
|
||||
int k = vertexFaces[v0][j];
|
||||
// if (k == i || (smoothingGroups & mesh3ds.getSmoothingGroups(k)) != 0)
|
||||
if (faceNormals[i].dot(faceNormals[k]) > 0.5f)
|
||||
{
|
||||
v += faceNormals[k];
|
||||
}
|
||||
}
|
||||
if (v.squaredNorm() == 0.0f)
|
||||
{
|
||||
v = Vector3f::UnitX();
|
||||
}
|
||||
v.normalize();
|
||||
vertexNormals[i * 3] = v;
|
||||
|
||||
v = Vector3f(0, 0, 0);
|
||||
for (j = 1; j <= vertexFaces[v1][0]; j++)
|
||||
{
|
||||
int k = vertexFaces[v1][j];
|
||||
// if (k == i || (smoothingGroups & mesh3ds.getSmoothingGroups(k)) != 0)
|
||||
if (faceNormals[i].dot(faceNormals[k]) > 0.5f)
|
||||
{
|
||||
v += faceNormals[k];
|
||||
}
|
||||
}
|
||||
if (v.squaredNorm() == 0.0f)
|
||||
{
|
||||
v = Vector3f::UnitX();
|
||||
}
|
||||
|
||||
v.normalize();
|
||||
vertexNormals[i * 3 + 1] = v;
|
||||
|
||||
v = Vector3f(0, 0, 0);
|
||||
for (j = 1; j <= vertexFaces[v2][0]; j++)
|
||||
{
|
||||
int k = vertexFaces[v2][j];
|
||||
// if (k == i || (smoothingGroups & mesh3ds.getSmoothingGroups(k)) != 0)
|
||||
if (faceNormals[i].dot(faceNormals[k]) > 0.5f)
|
||||
{
|
||||
v += faceNormals[k];
|
||||
}
|
||||
}
|
||||
if (v.squaredNorm() == 0.0f)
|
||||
{
|
||||
v = Vector3f::UnitX();
|
||||
}
|
||||
v.normalize();
|
||||
vertexNormals[i * 3 + 2] = v;
|
||||
}
|
||||
}
|
||||
|
||||
// build the triangle list
|
||||
for (i = 0; i < nFaces; i++)
|
||||
{
|
||||
uint16 triVert[3];
|
||||
mesh3ds.getFace(i, triVert[0], triVert[1], triVert[2]);
|
||||
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
Vector3f pos = mesh3ds.getVertex(triVert[j]);
|
||||
Vector3f norm = vertexNormals[i * 3 + j];
|
||||
int k = (i * 3 + j) * vertexSize;
|
||||
|
||||
vertices[k + 0] = pos.x();
|
||||
vertices[k + 1] = pos.y();
|
||||
vertices[k + 2] = pos.z();
|
||||
vertices[k + 3] = norm.x();
|
||||
vertices[k + 4] = norm.y();
|
||||
vertices[k + 5] = norm.z();
|
||||
if (hasTexCoords)
|
||||
{
|
||||
vertices[k + 6] = mesh3ds.getTexCoord(triVert[j]).x();
|
||||
vertices[k + 7] = mesh3ds.getTexCoord(triVert[j]).y();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
if (faceNormals != NULL)
|
||||
delete[] faceNormals;
|
||||
if (vertexNormals != NULL)
|
||||
delete[] vertexNormals;
|
||||
if (faceCounts != NULL)
|
||||
delete[] faceCounts;
|
||||
if (vertexFaces != NULL)
|
||||
{
|
||||
for (i = 0; i < nVertices; i++)
|
||||
{
|
||||
if (vertexFaces[i] != NULL)
|
||||
delete[] vertexFaces[i];
|
||||
}
|
||||
delete[] vertexFaces;
|
||||
}
|
||||
|
||||
|
||||
Mesh::VertexAttribute attributes[8];
|
||||
uint32 nAttributes = 0;
|
||||
|
@ -237,11 +92,6 @@ Convert3DSMesh(Model& model,
|
|||
nAttributes++;
|
||||
offset += 12;
|
||||
|
||||
// Normal attribute is always present
|
||||
attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Normal, Mesh::Float3, offset);
|
||||
nAttributes++;
|
||||
offset += 12;
|
||||
|
||||
if (hasTexCoords)
|
||||
{
|
||||
attributes[nAttributes] = Mesh::VertexAttribute(Mesh::Texture0, Mesh::Float2, offset);
|
||||
|
@ -252,7 +102,7 @@ Convert3DSMesh(Model& model,
|
|||
// Create the Celestia mesh
|
||||
Mesh* mesh = new Mesh();
|
||||
mesh->setVertexDescription(Mesh::VertexDescription(offset, nAttributes, attributes));
|
||||
mesh->setVertices(nOutputVertices, vertices);
|
||||
mesh->setVertices(nVertices, vertices);
|
||||
|
||||
mesh->setName(meshName);
|
||||
|
||||
|
@ -265,9 +115,11 @@ Convert3DSMesh(Model& model,
|
|||
|
||||
for (unsigned int i = 0; i < faceCount; i++)
|
||||
{
|
||||
indices[i * 3 + 0] = i * 3 + 0;
|
||||
indices[i * 3 + 1] = i * 3 + 1;
|
||||
indices[i * 3 + 2] = i * 3 + 2;
|
||||
uint16 v0 = 0, v1 = 0, v2 = 0;
|
||||
mesh3ds.getFace(i, v0, v1, v2);
|
||||
indices[i * 3 + 0] = v0;
|
||||
indices[i * 3 + 1] = v1;
|
||||
indices[i * 3 + 2] = v2;
|
||||
}
|
||||
|
||||
mesh->addGroup(Mesh::TriList, ~0, faceCount * 3, indices);
|
||||
|
@ -280,21 +132,20 @@ Convert3DSMesh(Model& model,
|
|||
{
|
||||
M3DMeshMaterialGroup* matGroup = mesh3ds.getMeshMaterialGroup(groupIndex);
|
||||
|
||||
// Vertex lists are not indexed, so the conversion to an indexed format is
|
||||
// trivial (although much space is wasted storing unnecessary indices.)
|
||||
uint32 nMatGroupFaces = matGroup->faces.size();
|
||||
uint32 nMatGroupVertices = nMatGroupFaces * 3;
|
||||
uint32* indices = new uint32[nMatGroupVertices];
|
||||
uint32* indices = new uint32[nMatGroupFaces * 3];
|
||||
|
||||
for (unsigned int i = 0; i < nMatGroupFaces; i++)
|
||||
{
|
||||
uint16 v0 = 0, v1 = 0, v2 = 0;
|
||||
uint16 faceIndex = matGroup->faces[i];
|
||||
indices[i * 3 + 0] = faceIndex * 3 + 0;
|
||||
indices[i * 3 + 1] = faceIndex * 3 + 1;
|
||||
indices[i * 3 + 2] = faceIndex * 3 + 2;
|
||||
mesh3ds.getFace(faceIndex, v0, v1, v2);
|
||||
indices[i * 3 + 0] = v0;
|
||||
indices[i * 3 + 1] = v1;
|
||||
indices[i * 3 + 2] = v2;
|
||||
}
|
||||
|
||||
// Convert the 3DS mesh's material
|
||||
// Get the material index
|
||||
unsigned int materialIndex = ~0u;
|
||||
string material3dsName = matGroup->materialName;
|
||||
if (!material3dsName.empty())
|
||||
|
@ -309,7 +160,7 @@ Convert3DSMesh(Model& model,
|
|||
}
|
||||
}
|
||||
|
||||
mesh->addGroup(Mesh::TriList, materialIndex, nMatGroupVertices, indices);
|
||||
mesh->addGroup(Mesh::TriList, materialIndex, nMatGroupFaces * 3, indices);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,9 +59,12 @@ MainWindow::MainWindow() :
|
|||
QAction* wireFrameStyleAction = new QAction(tr("&Wireframe"), styleGroup);
|
||||
wireFrameStyleAction->setCheckable(true);
|
||||
wireFrameStyleAction->setData((int) ModelViewWidget::WireFrameStyle);
|
||||
QAction* backgroundColorAction = new QAction(tr("&Background Color..."), this);
|
||||
|
||||
styleMenu->addAction(normalStyleAction);
|
||||
styleMenu->addAction(wireFrameStyleAction);
|
||||
styleMenu->addSeparator();
|
||||
styleMenu->addAction(backgroundColorAction);
|
||||
menuBar->addMenu(styleMenu);
|
||||
|
||||
QMenu* operationsMenu = new QMenu(tr("&Operations"));
|
||||
|
@ -97,6 +100,7 @@ MainWindow::MainWindow() :
|
|||
|
||||
// Connect Style menu
|
||||
connect(styleGroup, SIGNAL(triggered(QAction*)), this, SLOT(setRenderStyle(QAction*)));
|
||||
connect(backgroundColorAction, SIGNAL(triggered()), this, SLOT(editBackgroundColor()));
|
||||
|
||||
// Connect Operations menu
|
||||
connect(generateNormalsAction, SIGNAL(triggered()), this, SLOT(generateNormals()));
|
||||
|
@ -105,6 +109,33 @@ MainWindow::MainWindow() :
|
|||
connect(mergeMeshesAction, SIGNAL(triggered()), this, SLOT(mergeMeshes()));
|
||||
editMaterialAction->setShortcut(QKeySequence("Ctrl+E"));
|
||||
connect(editMaterialAction, SIGNAL(triggered()), this, SLOT(editMaterial()));
|
||||
|
||||
// Apply settings
|
||||
QSettings settings;
|
||||
QColor backgroundColor = settings.value("BackgroundColor", QColor(0, 0, 128)).value<QColor>();
|
||||
m_modelView->setBackgroundColor(backgroundColor);
|
||||
}
|
||||
|
||||
|
||||
static Material*
|
||||
cloneMaterial(const Material* other)
|
||||
{
|
||||
Material* material = new Material();
|
||||
material->diffuse = other->diffuse;
|
||||
material->specular = other->specular;
|
||||
material->emissive = other->emissive;
|
||||
material->specularPower = other->specularPower;
|
||||
material->opacity = other->opacity;
|
||||
material->blend = other->blend;
|
||||
for (int i = 0; i < Material::TextureSemanticMax; ++i)
|
||||
{
|
||||
if (other->maps[i])
|
||||
{
|
||||
material->maps[i] = new Material::DefaultTextureResource(other->maps[i]->source());
|
||||
}
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
|
||||
|
@ -273,7 +304,29 @@ MainWindow::openModel(const QString& fileName)
|
|||
|
||||
delete scene;
|
||||
|
||||
setModel(fileName, model);
|
||||
// Generate normals for the model
|
||||
double smoothAngle = 45.0; // degrees
|
||||
double weldTolerance = 1.0e-6;
|
||||
bool weldVertices = true;
|
||||
|
||||
Model* newModel = GenerateModelNormals(*model, float(smoothAngle * 3.14159265 / 180.0), weldVertices, weldTolerance);
|
||||
delete model;
|
||||
|
||||
if (!newModel)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Mesh Load Error"), tr("Internal error when loading mesh"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Automatically uniquify vertices
|
||||
for (unsigned int i = 0; newModel->getMesh(i) != NULL; i++)
|
||||
{
|
||||
Mesh* mesh = newModel->getMesh(i);
|
||||
UniquifyVertices(*mesh);
|
||||
}
|
||||
|
||||
setModel(fileName, newModel);
|
||||
}
|
||||
}
|
||||
else if (info.suffix().toLower() == "cmod")
|
||||
{
|
||||
|
@ -367,28 +420,6 @@ MainWindow::setRenderStyle(QAction* action)
|
|||
}
|
||||
|
||||
|
||||
static Material*
|
||||
cloneMaterial(const Material* other)
|
||||
{
|
||||
Material* material = new Material();
|
||||
material->diffuse = other->diffuse;
|
||||
material->specular = other->specular;
|
||||
material->emissive = other->emissive;
|
||||
material->specularPower = other->specularPower;
|
||||
material->opacity = other->opacity;
|
||||
material->blend = other->blend;
|
||||
for (int i = 0; i < Material::TextureSemanticMax; ++i)
|
||||
{
|
||||
if (other->maps[i])
|
||||
{
|
||||
material->maps[i] = new Material::DefaultTextureResource(other->maps[i]->source());
|
||||
}
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWindow::generateNormals()
|
||||
{
|
||||
|
@ -436,33 +467,16 @@ MainWindow::generateNormals()
|
|||
double weldTolerance = toleranceEdit->text().toDouble();
|
||||
bool weldVertices = true;
|
||||
|
||||
Model* newModel = new Model();
|
||||
|
||||
// Copy materials
|
||||
for (unsigned int i = 0; model->getMaterial(i) != NULL; i++)
|
||||
Model* newModel = GenerateModelNormals(*model, float(smoothAngle * 3.14159265 / 180.0), weldVertices, weldTolerance);
|
||||
if (!newModel)
|
||||
{
|
||||
newModel->addMaterial(cloneMaterial(model->getMaterial(i)));
|
||||
QMessageBox::warning(this, tr("Internal Error"), tr("Out of memory error during normal generation"));
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; model->getMesh(i) != NULL; i++)
|
||||
else
|
||||
{
|
||||
Mesh* mesh = model->getMesh(i);
|
||||
Mesh* newMesh = NULL;
|
||||
|
||||
newMesh = GenerateNormals(*mesh, float(smoothAngle * 3.14159265 / 180.0), weldVertices, weldTolerance);
|
||||
if (newMesh == NULL)
|
||||
{
|
||||
cerr << "Error generating normals!\n";
|
||||
// TODO: Clone the mesh and add it to the model
|
||||
}
|
||||
else
|
||||
{
|
||||
newModel->addMesh(newMesh);
|
||||
}
|
||||
setModel(modelFileName(), newModel);
|
||||
}
|
||||
|
||||
setModel(modelFileName(), newModel);
|
||||
|
||||
settings.setValue("SmoothAngle", smoothAngle);
|
||||
settings.setValue("WeldTolerance", weldTolerance);
|
||||
}
|
||||
|
@ -615,3 +629,21 @@ MainWindow::changeCurrentMaterial(const Material& material)
|
|||
m_modelView->setMaterial(selectedGroup->materialIndex, material);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWindow::editBackgroundColor()
|
||||
{
|
||||
QColor originalColor = m_modelView->backgroundColor();
|
||||
QColorDialog dialog(originalColor, this);
|
||||
connect(&dialog, SIGNAL(currentColorChanged(QColor)), m_modelView, SLOT(setBackgroundColor(QColor)));
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
QSettings settings;
|
||||
settings.setValue("BackgroundColor", m_modelView->backgroundColor());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_modelView->setBackgroundColor(originalColor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ public slots:
|
|||
|
||||
void changeCurrentMaterial(const cmod::Material&);
|
||||
|
||||
void editBackgroundColor();
|
||||
|
||||
private:
|
||||
ModelViewWidget* m_modelView;
|
||||
QLabel* m_statusBarLabel;
|
||||
|
|
|
@ -311,6 +311,14 @@ ModelViewWidget::setMaterial(unsigned int index, const cmod::Material& material)
|
|||
update();
|
||||
}
|
||||
|
||||
void
|
||||
ModelViewWidget::setBackgroundColor(const QColor& color)
|
||||
{
|
||||
m_backgroundColor = color;
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModelViewWidget::initializeGL()
|
||||
{
|
||||
|
@ -320,7 +328,7 @@ ModelViewWidget::initializeGL()
|
|||
void
|
||||
ModelViewWidget::paintGL()
|
||||
{
|
||||
glClearColor(0.0f, 0.0f, 0.5f, 0.0f);
|
||||
glClearColor(m_backgroundColor.redF(), m_backgroundColor.greenF(), m_backgroundColor.blueF(), 0.0f);
|
||||
glDepthMask(GL_TRUE);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
|
|
|
@ -60,10 +60,18 @@ public:
|
|||
return m_renderStyle;
|
||||
}
|
||||
|
||||
QColor backgroundColor() const
|
||||
{
|
||||
return m_backgroundColor;
|
||||
}
|
||||
|
||||
Eigen::Transform3d cameraTransform() const;
|
||||
|
||||
void setMaterial(unsigned int index, const cmod::Material& material);
|
||||
|
||||
public slots:
|
||||
void setBackgroundColor(const QColor& color);
|
||||
|
||||
protected:
|
||||
void initializeGL();
|
||||
void paintGL();
|
||||
|
@ -86,6 +94,8 @@ private:
|
|||
MaterialLibrary* m_materialLibrary;
|
||||
|
||||
QSet<cmod::Mesh::PrimitiveGroup*> m_selection;
|
||||
|
||||
QColor m_backgroundColor;
|
||||
};
|
||||
|
||||
#endif // _CMODVIEW_MODEL_VIEW_WIDGET_H_
|
||||
|
|
Loading…
Reference in New Issue