Commit ebff9d64 authored by David E. DeMarle's avatar David E. DeMarle
Browse files

add a quick and dirty material reader

before vtk ospray users run a python script to convert the familiar
mtl format to our custom vtkospray dialect of json format. Now users
can skip that and just load the mtl directly.

Note: Many concepts in mtl are not supported at this time.
parent 7961011a
......@@ -25,6 +25,7 @@
int TestPathTracerMaterialLibrary(int argc, char* argv[])
{
// read an ospray material file
const char* materialFile = vtkTestUtilities::ExpandDataFileName(
argc, argv, "Data/ospray_mats.json");
vtkSmartPointer<vtkOSPRayMaterialLibrary> lib =
......@@ -33,6 +34,14 @@ int TestPathTracerMaterialLibrary(int argc, char* argv[])
lib->ReadFile(materialFile);
cout << "Parsed file OK, now check for expected contents." << endl;
std::set<std::string> mats = lib->GetMaterialNames();
cout << "Materials are:" << endl;
std::set<std::string>::iterator it = mats.begin();
while (it != mats.end())
{
cout << *it << endl;
it++;
}
if (mats.find("Water") == mats.end())
{
cerr << "Problem, could not find expected material named water." << endl;
......@@ -41,13 +50,13 @@ int TestPathTracerMaterialLibrary(int argc, char* argv[])
cout << "Found Water material." << endl;
if (lib->LookupImplName("Water") != "Glass")
{
cerr << "Problem, expected Water's to be implemented by the Glass material." << endl;
cerr << "Problem, expected Water to be implemented by the Glass material." << endl;
return VTK_ERROR;
}
cout << "Water is the right type." << endl;
if (lib->GetDoubleShaderVariable("Water","attenuationColor").size() != 3)
{
cerr << "Problem, expected Water's to have a 3 component variable called attentuationColor." << endl;
cerr << "Problem, expected Water to have a 3 component variable called attentuationColor." << endl;
return VTK_ERROR;
}
cout << "Water has an expected variable." << endl;
......@@ -56,11 +65,57 @@ int TestPathTracerMaterialLibrary(int argc, char* argv[])
cerr << "Problem, expected Bumpy to have a texture called map_bump." << endl;
return VTK_ERROR;
}
cout << "We read in a texture too." << endl;
cout << "Bumpy has a good texture too." << endl;
cout << "We're all clear kid." << endl;
// read a wavefront mtl file
const char* materialFile2 = vtkTestUtilities::ExpandDataFileName(
argc, argv, "Data/ospray_mats.mtl");
cout << "Open " << materialFile2 << endl;
lib->ReadFile(materialFile2);
cout << "Parsed file OK, now check for expected contents." << endl;
mats = lib->GetMaterialNames();
cout << "Materials are now:" << endl;
it = mats.begin();
while (it != mats.end())
{
cout << *it << endl;
it++;
}
if (mats.find("mat2") == mats.end())
{
cerr << "Problem, could not find expected material named mat2." << endl;
return VTK_ERROR;
}
if (lib->GetDoubleShaderVariable("mat2","Ka").size() != 3)
{
cerr << "Problem, expected mat2 to have a 3 component variable called Ka." << endl;
return VTK_ERROR;
}
cout << "mat2 has an expected variable." << endl;
if (lib->GetTexture("mat2","map_Kd") == nullptr)
{
cerr << "Problem, expected mat2 to have a texture called map_Kd." << endl;
return VTK_ERROR;
}
cout << "mat2 has a good texture too." << endl;
if (mats.find("mat3") == mats.end())
{
cerr << "Problem, could not find expected material named mat3." << endl;
return VTK_ERROR;
}
if (lib->LookupImplName("mat3") != "Metal")
{
cerr << "Problem, expected mat3 to be implemented by the Metal material." << endl;
return VTK_ERROR;
}
cout << "mat3 is the right type." << endl;
cout << "We're all clear kid." << endl;
//serialize and deserialize
cout << "Serialize" << endl;
const char *buf = lib->WriteBuffer();
......
......@@ -181,11 +181,19 @@ OSPMaterial vtkOSPRayMaterialHelpers::MakeMaterial
OSPSET1F(ns);//aka "Ns", default 10.0
OSPSET1F(Ns);//aka "Ns", default 10.0
OSPSET3F(tf);//aka "Tf", default (0.0,0.0,0.0)
OSPSET3F(Tf);//aka "Tf", default (0.0,0.0,0.0)
OSPSETTEXTURE(map_d);
OSPSETTEXTURE(map_kd);
OSPSETTEXTURE(map_Kd);
OSPSETTEXTURE(colorMap);
OSPSETTEXTURE(map_ks);
OSPSETTEXTURE(map_Ks);
OSPSETTEXTURE(map_ns);
OSPSETTEXTURE(map_Ns);
OSPSETTEXTURE(map_bump);
OSPSETTEXTURE(map_Bump);
OSPSETTEXTURE(normalmap);
OSPSETTEXTURE(BumpMap);
/*
//todo hookup these texture transforms up, for now could be just in 9 long double vectors, but should really be a 3x3
......
......@@ -124,7 +124,6 @@ bool vtkOSPRayMaterialLibrary::InternalParse
return false;
}
//todo: this reader is a lot more fragile then I'ld like, need to make it robust
std::istream *doc;
if (fromfile)
{
......@@ -132,7 +131,18 @@ bool vtkOSPRayMaterialLibrary::InternalParse
} else {
doc = new std::istringstream(filename);
}
if (std::string(filename).rfind(".mtl") != std::string::npos)
{
return this->InternalParseMTL(filename, fromfile, doc);
}
return this->InternalParseJSON(filename, fromfile, doc);
}
// ----------------------------------------------------------------------------
bool vtkOSPRayMaterialLibrary::InternalParseJSON
(const char *filename, bool fromfile, std::istream *doc)
{
//todo: this reader is a lot more fragile then I'ld like, need to make it robust
Json::Value root;
*doc >> root;
delete doc;
......@@ -248,6 +258,198 @@ bool vtkOSPRayMaterialLibrary::InternalParse
return true;
}
namespace {
static std::string trim(std::string s)
{
size_t start = 0;
while ((start < s.length()) && (isspace(s[start])))
{
start++;
}
size_t end = s.length();
while ((end > start) && (isspace(s[end-1])))
{
end--;
}
return s.substr(start, end-start);
}
}
// ----------------------------------------------------------------------------
bool vtkOSPRayMaterialLibrary::InternalParseMTL
(const char *filename, bool fromfile, std::istream *doc)
{
std::string str;
std::string nickname = "";
std::string implname = "OBJMaterial";
const std::vector<std::string> singles
{"d ", "Ks ", "alpha ", "roughness ", "eta ", "thickness "};
const std::vector<std::string> triples
{"Ka ", "color ", "Kd ", "Ks "};
const std::vector<std::string> textures
{"map_d ",
"map_Kd ", "map_kd ", "colorMap ",
"map_Ks ", "map_ks ",
"map_Ns ", "map_ns ", "map_Bump", "map_bump", "normalMap", "bumpMap"};
while(getline(*doc, str))
{
std::string tstr = trim(str);
std::string key;
//a new material
key = "newmtl ";
if (tstr.find(key) == 0)
{
nickname = trim(tstr.substr(key.size()));
this->Internal->NickNames.insert(nickname);
this->Internal->ImplNames[nickname] = "OBJMaterial";
}
//ospray type of the material, if not obj
key = "type ";
if (tstr.find(key) == 0)
{
//this non standard entry is a quick way to break out of
//objmaterial and use one of the ospray specific materials
implname = trim(tstr.substr(key.size()));
if (implname == "matte")
{
implname = "OBJMaterial";
}
if (implname == "glass")
{
implname = "ThinGlass";
}
if (implname == "metal")
{
implname = "Metal";
}
if (implname == "glass")
{
implname = "ThinGlass";
}
if (implname == "metallicPaint")
{
implname = "MetallicPaint";
}
this->Internal->ImplNames[nickname] = implname;
}
//grab all the single valued settings we see
std::vector<std::string>::const_iterator sit1 = singles.begin();
while (sit1 != singles.end())
{
std::string key = *sit1;
sit1++;
if (tstr.find(key) == 0)
{
std::string v = tstr.substr(key.size());
double dv;
bool OK = false;
try
{
dv = std::stod(v);
OK = true;
}
catch (const std::invalid_argument&) {}
catch (const std::out_of_range&) {}
if (OK)
{
double vals[1] = {dv};
this->AddShaderVariable(nickname, key.substr(0,key.size()-1).c_str(), 1, vals);
}
}
}
//grab all the triple valued settings we see
std::vector<std::string>::const_iterator sit3 = triples.begin();
while (sit3 != triples.end())
{
std::string key = *sit3;
sit3++;
if (tstr.find(key) == 0)
{
std::string vs = tstr.substr(key.size());
size_t loc1 = vs.find(" ");
size_t loc2 = vs.find(" ", loc1);
std::string v1 = vs.substr(0,loc1);
std::string v2 = vs.substr(loc1+1,loc2);
std::string v3 = vs.substr(loc2+1);
double d1, d2, d3;
bool OK = false;
try
{
d1 = std::stod(v1);
d2 = std::stod(v1);
d3 = std::stod(v1);
OK = true;
}
catch (const std::invalid_argument&) {}
catch (const std::out_of_range&) {}
if (OK)
{
double vals[3] = {d1, d2, d3};
this->AddShaderVariable(nickname, key.substr(0,key.size()-1).c_str(), 3, vals);
}
}
}
//grab all the textures we see
std::vector<std::string>::const_iterator tit = textures.begin();
while (tit != textures.end())
{
std::string key = *tit;
tit++;
std::string tfname = "";
if (tstr.find(key) == 0)
{
tfname = trim(tstr.substr(key.size()));
}
if (tfname != "")
{
vtkSmartPointer<vtkTexture> textr = vtkSmartPointer<vtkTexture>::New();
vtkSmartPointer<vtkJPEGReader> jpgReader = vtkSmartPointer<vtkJPEGReader>::New();
vtkSmartPointer<vtkPNGReader> pngReader = vtkSmartPointer<vtkPNGReader>::New();
if (fromfile)
{
std::string parentDir
= vtksys::SystemTools::GetParentDirectory(filename);
std::string tfullname = parentDir + "/" + tfname;
if (!vtksys::SystemTools::FileExists(tfullname.c_str(), true))
{
cerr << "No such texture file " << tfullname << " skipping" << endl;
continue;
}
if (tfullname.substr( tfullname.length() - 3 ) == "png")
{
pngReader->SetFileName(tfullname.c_str());
pngReader->Update();
textr->SetInputConnection(pngReader->GetOutputPort(0));
} else {
jpgReader->SetFileName(tfullname.c_str());
jpgReader->Update();
textr->SetInputConnection(jpgReader->GetOutputPort(0));
}
} else {
vtkSmartPointer<vtkXMLImageDataReader> reader =
vtkSmartPointer<vtkXMLImageDataReader>::New();
reader->ReadFromInputStringOn();
reader->SetInputString(tfname);
textr->SetInputConnection(reader->GetOutputPort(0));
}
textr->Update();
this->AddTexture(nickname, key.substr(0,key.size()-1).c_str(), textr);
}
}
}
return true;
}
// ----------------------------------------------------------------------------
const char * vtkOSPRayMaterialLibrary::WriteBuffer()
{
......
......@@ -110,6 +110,8 @@ protected:
virtual ~vtkOSPRayMaterialLibrary();
bool InternalParse(const char *name, bool IsFile);
bool InternalParseJSON(const char *name, bool IsFile, std::istream *doc);
bool InternalParseMTL(const char *name, bool IsFile, std::istream *doc);
private:
vtkOSPRayMaterialLibrary(const vtkOSPRayMaterialLibrary&) = delete;
......
5f8a3aa0263b908fc616ebaf552dac1a
Markdown is supported
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