Commit 517aed2b authored by Bill Lorensen's avatar Bill Lorensen
Browse files

BUG: vtkOBJImporter does not handle multiple groups using same material

The original code assumed that each material could only be used by one
actor (group). There is no mention of this restriction in the
Wavefront obj specification. The solution is to use a map of vectors
to map between material and actors.
New test added.

BUG: vtkOBJImporter fails if vt are present but texture indices not present
Another bug was discovered while addressing the original issue. If
texture coordinates are present via "vt" command but texture indices
are not defined for the faces, the actor was skipped. The solution is
to add a boolean variable that indicates whether texture indices are
defined. If there are no texture indices, do not add TCoords to the
PointData.
parent f7c3dfc2
......@@ -4,8 +4,6 @@ ExternalData_add_test(VTKData
DATA{../Data/Input/cube-scene.obj}
DATA{../Data/Input/cube-scene.mtl}
DATA{../Data/Input/noise.png}
-V DATA{../Data/Baseline/OBJImport-SolidAndTextured.png}
-T "${VTK_TEST_OUTPUT_DIR}"
)
include(vtkOpenGL)
......@@ -45,6 +43,19 @@ vtk_add_test_cxx(vtkIOImportCxxTests tests
DATA{../Data/Input/TestOBJImporter.png}
)
vtk_add_test_cxx(vtkIOImportCxxTests tests
TestOBJImporter-SharedMtl,TestOBJImporter.cxx
DATA{../Data/Input/TestOBJImporter-SharedMtl.obj}
DATA{../Data/Input/TestOBJImporter-SharedMtl.mtl}
)
vtk_add_test_cxx(vtkIOImportCxxTests tests
TestOBJImporter-VtNoIndices,TestOBJImporter.cxx
DATA{../Data/Input/TestOBJImporter-VtNoIndices.obj}
DATA{../Data/Input/TestOBJImporter-VtNoIndices.mtl}
DATA{../Data/Input/TestOBJImporter-VtNoIndices.png}
)
vtk_add_test_cxx(vtkIOImportCxxTests tests
TestVRMLImporter.cxx,NO_VALID
TestVRMLNormals.cxx
......
61f689cbcca2b0c34d87f00def24c8c7310b57418408d8c9e5b112a2b1fafae7d1f592d2a83abc7bdaeefd76c722c3638f36ae5b5eb97a8f3383510289078862
e29ead591b02c42b7ff62b63eb2edfecbee235b62d9468a2e3b96151a4e3368e97f3bd571683d1058c1f9fb3f35cbafce48d46a30d4a6092c69f24464c10a828
597856daa198780c0d0a73758b06caebf4f06d6a7eef5765289b4e4fdb5ea9def9a7284c76ee04d3079dbf965320793e27b7225430d24d9abebdd92888a0643b
4f654c8c1d9a446670c066cd0e6160dbc9093d9b001a123d7b96685f8c59f140881e7e891161302d475fc59a4dd5306e64e55b4e4c094e8a4031597b844a4e0b
ee5fa6ba987d4ec74a41fde1ea4770a20be15a43cc172822b0bb35a88a66a71fbf220e649fb0a37afc4f731f29225c171470ca70519c026a551361a62c9efbc1
b6ad4bb0f540d6e86ef9769082320443f09c288b3b35f5addbad8b86a8a0844e02ee73a3f09fa15ded050b2903e646aa6f1cbbecbb08a7b8397ebc7f3255e4a3
8c800b46e0bdac694be0d726b8007cfd03b08bb7a4710390a3ae2616fdf31d6d507b191fe0eddd04b59bc352abe2f55a0e3f3a747ea47c9850daa5c72a31e1b5
......@@ -397,7 +397,7 @@ int vtkOBJPolyDataProcessor::RequestData(
vtkSmartPointer<vtkFloatArray> shared_normals = vtkSmartPointer<vtkFloatArray>::New();
shared_normals->SetNumberOfComponents(3);
std::map<std::string,vtkOBJImportedPolyDataWithMaterial*> mtlName_to_Actor;
std::map<std::string,std::vector<vtkOBJImportedPolyDataWithMaterial*> > mtlName_to_Actors;
{
// always have at least one output
......@@ -427,8 +427,9 @@ int vtkOBJPolyDataProcessor::RequestData(
bool gotFirstUseMaterialTag = false;
int numPolysWithTCoords = 0;
bool hasTCoords = false;
bool hasNormals = false;
bool hasTCoords = false; // has vt x y z
bool hasPolysWithTextureIndices = false; // has f i/t/n or f i/t
bool hasNormals = false; // has f i/t/n or f i//n
bool tcoords_same_as_verts = true;
bool normals_same_as_verts = true;
bool everything_ok = true; // (use of this flag avoids early return and associated memory leak)
......@@ -687,6 +688,7 @@ int vtkOBJPolyDataProcessor::RequestData(
int iVert,iTCoord,iNormal;
if (sscanf(pLine, "%d/%d/%d", &iVert, &iTCoord, &iNormal) == 3)
{
hasPolysWithTextureIndices = true;
polys->InsertCellPoint(iVert-1); // convert to 0-based index
nVerts++;
tcoord_polys->InsertCellPoint(iTCoord-1);
......@@ -700,6 +702,7 @@ int vtkOBJPolyDataProcessor::RequestData(
}
else if (sscanf(pLine, "%d//%d", &iVert, &iNormal) == 2)
{
hasPolysWithTextureIndices = false;
polys->InsertCellPoint(iVert-1);
nVerts++;
normal_polys->InsertCellPoint(iNormal-1);
......@@ -709,6 +712,7 @@ int vtkOBJPolyDataProcessor::RequestData(
}
else if (sscanf(pLine, "%d/%d", &iVert, &iTCoord) == 2)
{
hasPolysWithTextureIndices = true;
polys->InsertCellPoint(iVert-1);
nVerts++;
tcoord_polys->InsertCellPoint(iTCoord-1);
......@@ -718,6 +722,7 @@ int vtkOBJPolyDataProcessor::RequestData(
}
else if (sscanf(pLine, "%d", &iVert) == 1)
{
hasPolysWithTextureIndices = false;
polys->InsertCellPoint(iVert-1);
nVerts++;
}
......@@ -816,14 +821,11 @@ int vtkOBJPolyDataProcessor::RequestData(
{
poly_list[0]->materialName = mtl_name;
poly_list[0]->mtlProperties = mtlName_to_mtlData[mtl_name];
mtlName_to_Actor[mtl_name] = poly_list[0];
mtlName_to_Actors[mtl_name].push_back(poly_list[0]);
// yep we have a usemtl command. check to make sure idiots don't try to add vertices later.
gotFirstUseMaterialTag = true;
}
size_t mtlCount = mtlName_to_Actor.count(mtl_name);
if ( 0 == mtlCount )
{
// new material encountered; bag and tag it, make a new named-poly-data-container
// create a new materia
vtkOBJImportedPolyDataWithMaterial* newMaterial = new vtkOBJImportedPolyDataWithMaterial;
newMaterial->SetSharedPoints(shared_vertexs);
newMaterial->SetSharedNormals(shared_normals);
......@@ -831,31 +833,14 @@ int vtkOBJPolyDataProcessor::RequestData(
poly_list.back()->materialName = mtl_name;
poly_list.back()->mtlProperties = mtlName_to_mtlData[mtl_name];
mtlName_to_Actor[mtl_name] = poly_list.back();
vtkOBJImportedPolyDataWithMaterial* active = mtlName_to_Actor[mtl_name];
vtkDebugMacro("name of material is: " << active->materialName);
mtlName_to_Actors[mtl_name].push_back(poly_list.back());
/** slightly tricky: all multi-polys share the vertex, normals, and tcoords,
but define unique polygons... */
vtkOBJImportedPolyDataWithMaterial* active = newMaterial;
polys = active->polys; // Update pointers reading file further
tcoord_polys = active->tcoord_polys;
pointElems = active->pointElems;
lineElems = active->lineElems;
normal_polys = active->normal_polys;
}
else /** This material name already exists; switch back to it! */
{
vtkOBJImportedPolyDataWithMaterial* known_mtl = mtlName_to_Actor[mtl_name];
vtkDebugMacro("switching to append faces with pre-existing material named "
<< known_mtl->materialName);
polys = known_mtl->polys; // Update pointers reading file further
tcoord_polys = known_mtl->tcoord_polys;
pointElems = known_mtl->pointElems;
lineElems = known_mtl->lineElems;
normal_polys = known_mtl->normal_polys;
}
}
else
{
......@@ -871,7 +856,7 @@ int vtkOBJPolyDataProcessor::RequestData(
set the number of output ports of vtkPolyData */
this->SetNumberOfOutputPorts( static_cast<int>(poly_list.size()) );
vtkDebugMacro("vtkOBJPolyDataProcessor.cxx, set # of output ports to "
<< poly_list.size());
<< poly_list.size());
this->outVector_of_vtkPolyData.clear();
for( size_t i = 0; i < poly_list.size(); ++i)
{
......@@ -919,7 +904,7 @@ int vtkOBJPolyDataProcessor::RequestData(
// if there is an exact correspondence between tcoords and vertices then can simply
// assign the tcoords points as point data
if (hasTCoords && tcoords_same_as_verts)
if (hasTCoords && tcoords_same_as_verts && hasPolysWithTextureIndices)
output->GetPointData()->SetTCoords(tcoords);
// if there is an exact correspondence between normals and vertices then can simply
......@@ -964,7 +949,7 @@ int vtkOBJPolyDataProcessor::RequestData(
// are any tcoords in the dataset) or normals (if there are any normals in the dataset).
if (
(n_pts != n_tcoord_pts && hasTCoords) ||
(n_pts != n_tcoord_pts && hasTCoords && hasPolysWithTextureIndices) ||
(n_pts != n_normal_pts && hasNormals)
)
{
......@@ -977,7 +962,7 @@ int vtkOBJPolyDataProcessor::RequestData(
for (int j = 0; j < n_pts; ++j)
{
// copy the tcoord for this point across (if there is one)
if (n_tcoord_pts>0)
if (n_tcoord_pts>0 && hasPolysWithTextureIndices)
{
new_tcoords->InsertNextTuple(tcoords->GetTuple(tcoord_pts[j]));
}
......@@ -1003,7 +988,7 @@ int vtkOBJPolyDataProcessor::RequestData(
vtkDebugMacro(" set new polys, count = "
<< new_polys->GetNumberOfCells() << " ...");
if (hasTCoords)
if (hasTCoords && hasPolysWithTextureIndices)
{
output->GetPointData()->SetTCoords(new_tcoords);
vtkDebugMacro(" set new tcoords");
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment