Skip to content

Commit

Permalink
Obj texture fix -- simplified. (#3222)
Browse files Browse the repository at this point in the history
* Texture 2 element fix

* Allow for 0-3 fields in texture and 3-4 fields in vertex position

* Rename texture dimensions, add W

* Allow all dimensions

* Allow more than 4 fields in vertex specification

* Remove unused

* Copy over tests

* Add W dimension

* Check vertex length
  • Loading branch information
Ryan Pals authored and abellgithub committed Aug 28, 2020
1 parent 68adb9c commit af2450a
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 36 deletions.
111 changes: 85 additions & 26 deletions io/ObjReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ void ObjReader::addDimensions(PointLayoutPtr layout)
Dimension::Id::X,
Dimension::Id::Y,
Dimension::Id::Z,
Dimension::Id::W,
Dimension::Id::TextureU,
Dimension::Id::TextureV,
Dimension::Id::TextureW,
Dimension::Id::NormalX,
Dimension::Id::NormalY,
Dimension::Id::NormalZ,
Dimension::Id::TextureX,
Dimension::Id::TextureY
});
}

Expand Down Expand Up @@ -96,7 +98,8 @@ point_count_t ObjReader::read(PointViewPtr view, point_count_t cnt)
void ObjReader::newTriangle(PointViewPtr view, TRI tri)
{
// checks if a point exists yet, if not, adds it to the point table via addPoint()
auto insertPoint = [view, this](VTN vertex) {
auto insertPoint = [view, this](VTN vertex)
{
PointId id;
auto it = m_points.find(vertex);
if (it == m_points.end())
Expand All @@ -117,7 +120,7 @@ void ObjReader::newTriangle(PointViewPtr view, TRI tri)
// adds a point to the point table
PointId ObjReader::addPoint(PointViewPtr view, VTN vertex)
{
XYZ v, t, n;
XYZW v, t, n;
PointRef pt = view->point(m_index);
m_index++;

Expand All @@ -129,15 +132,17 @@ PointId ObjReader::addPoint(PointViewPtr view, VTN vertex)
pt.setField(Dimension::Id::X, v.x);
pt.setField(Dimension::Id::Y, v.y);
pt.setField(Dimension::Id::Z, v.z);
pt.setField(Dimension::Id::W, v.w);

int64_t textureIndex = std::get<1>(vertex) - 1;
if (textureIndex >= 0) {
if ((size_t)textureIndex >= m_textureVertices.size())
throwError("Texture vertex index '" + std::to_string(textureIndex + 1) + "' specified "
"for face doesn't exist.");
t = m_textureVertices.at(textureIndex);
pt.setField(Dimension::Id::TextureX, t.x);
pt.setField(Dimension::Id::TextureY, t.y);
pt.setField(Dimension::Id::TextureU, t.x);
pt.setField(Dimension::Id::TextureV, t.y);
pt.setField(Dimension::Id::TextureW, t.z);
}

int64_t normalIndex = std::get<2>(vertex) - 1;
Expand All @@ -155,17 +160,34 @@ PointId ObjReader::addPoint(PointViewPtr view, VTN vertex)

void ObjReader::newVertex(double x, double y, double z)
{
m_vertices.push_back({x, y, z});
// w defaults to 1 according to https://en.wikipedia.org/wiki/Wavefront_.obj_file
m_vertices.push_back({x, y, z, 1});
}

void ObjReader::newVertex(double x, double y, double z, double w)
{
m_vertices.push_back({x, y, z, w});
}

// undefined texture values default to 0 according to https://en.wikipedia.org/wiki/Wavefront_.obj_file
void ObjReader::newTextureVertex(double x)
{
m_textureVertices.push_back({x, 0, 0, 0});
}

void ObjReader::newTextureVertex(double x, double y)
{
m_textureVertices.push_back({x, y, 0, 0});
}

void ObjReader::newTextureVertex(double x, double y, double z)
{
m_textureVertices.push_back({x, y, z});
m_textureVertices.push_back({x, y, z, 0});
}

void ObjReader::newNormalVertex(double x, double y, double z)
{
m_normalVertices.push_back({x, y, z});
m_normalVertices.push_back({x, y, z, 0});
}

bool ObjReader::readFace(FACE& face, PointViewPtr view)
Expand All @@ -191,44 +213,81 @@ bool ObjReader::readFace(FACE& face, PointViewPtr view)
else if (key == "v")
{
// Vertex
double x, y, z;
if (Utils::fromString(fields[1], x) && Utils::fromString(fields[2], y) &&
Utils::fromString(fields[3], z))
newVertex( x, y, z );
else
size_t numDims = fields.size() - 1;

auto throwVertexError = [this, line, lineOfFile]()
{
std::stringstream ss;
ss << "Could not convert vertex specification to double on line #"
std::stringstream errorMessage;
errorMessage << "Could not convert vertex specification to double on line #"
<< lineOfFile << ": '" << line << "'" << std::endl;
throwError(ss.str());
throwError(errorMessage.str());
};

if(numDims < 3) {
throwVertexError();
}
else if(numDims == 3) {
double x, y, z;
if (Utils::fromString(fields[1], x) && Utils::fromString(fields[2], y) &&
Utils::fromString(fields[3], z))
newVertex(x, y, z);
else
throwVertexError();
}
else if(numDims > 3) {
double x, y, z, w;
if (Utils::fromString(fields[1], x) && Utils::fromString(fields[2], y) &&
Utils::fromString(fields[3], z) && Utils::fromString(fields[4], w))
newVertex(x, y, z, w);
else
throwVertexError();
}
}
else if (key == "vt")
{
// Vertex texture
double x, y, z;
if (Utils::fromString(fields[1], x) && Utils::fromString(fields[2], y) &&
Utils::fromString(fields[3], z))
newTextureVertex( x, y, z );
else
auto throwTextureError = [this, line, lineOfFile]()
{
std::stringstream ss;
ss << "Could not convert texture vertex specification to double on line #"
<< lineOfFile << ": '" << line << "'" << std::endl;
throwError(ss.str());
};
// Vertex texture
if(fields.size() == 4) {
double x, y, z;
if (Utils::fromString(fields[1], x) && Utils::fromString(fields[2], y) &&
Utils::fromString(fields[3], z))
newTextureVertex( x, y, z );
else
throwTextureError();
}
else if(fields.size() == 3) {
double x, y;
if (Utils::fromString(fields[1], x) && Utils::fromString(fields[2], y))
newTextureVertex( x, y );
else
throwTextureError();
}
else if(fields.size() == 2) {
double x;
if (Utils::fromString(fields[1], x))
newTextureVertex( x );
else
throwTextureError();
}

}
else if (key == "vn")
{
// Vertex normal
double x, y, z;
if (Utils::fromString(fields[1], x) && Utils::fromString(fields[2], y) &&
Utils::fromString(fields[3], z))
if (fields.size() >= 4 && Utils::fromString(fields[1], x) &&
Utils::fromString(fields[2], y) && Utils::fromString(fields[3], z))
newNormalVertex( x, y, z );
else
{
std::stringstream ss;
ss << "Could not convert texture vertex specification to double on line #"
ss << "Could not convert normal vertex specification to double on line #"
<< lineOfFile << ": '" << line << "'" << std::endl;
throwError(ss.str());
}
Expand Down
12 changes: 8 additions & 4 deletions io/ObjReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,16 @@ class PDAL_DLL ObjReader : public Reader
virtual point_count_t read(PointViewPtr view, point_count_t numPts);

private:
struct XYZ
struct XYZW
{
double x;
double y;
double z;
double w;
};
std::vector<XYZ> m_vertices;
std::vector<XYZ> m_textureVertices;
std::vector<XYZ> m_normalVertices;
std::vector<XYZW> m_vertices;
std::vector<XYZW> m_textureVertices;
std::vector<XYZW> m_normalVertices;
TriangularMesh *m_mesh;
using VTN = std::tuple<int64_t, int64_t, int64_t>;
std::map<VTN, PointId> m_points;
Expand All @@ -80,6 +81,9 @@ class PDAL_DLL ObjReader : public Reader
using FACE = std::vector<VTN>;

void newVertex(double x, double y, double z);
void newVertex(double x, double y, double z, double w);
void newTextureVertex(double x);
void newTextureVertex(double x, double y);
void newTextureVertex(double x, double y, double z);
void newNormalVertex(double x, double y, double z);
void newTriangle(PointViewPtr view, TRI tri);
Expand Down
23 changes: 17 additions & 6 deletions pdal/Dimension.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
"description": "Z coordinate"
},
{
"name": "W",
"type": "double",
"description": "W coordinate"
},
{
"name": "Intensity",
"type": "uint16",
"description": "Representation of the pulse return magnitude"
Expand Down Expand Up @@ -385,16 +390,22 @@
"description": "Distance metric related to a point's nearest neighbors."
},
{
"name": "TextureX",
"alt_names": ["tx", "texture_x", "texturex" ],
"name": "TextureU",
"alt_names": ["tu", "texture_u", "textureu" ],
"type": "double",
"description": "U component of a texture location at this point"
},
{
"name": "TextureV",
"alt_names": ["tv", "texture_v", "texturev" ],
"type": "double",
"description": "X component of a texture location at this point"
"description": "V component of a texture location at this point"
},
{
"name": "TextureY",
"alt_names": ["ty", "texture_y", "texturey" ],
"name": "TextureW",
"alt_names": ["tw", "texture_w", "texturew" ],
"type": "double",
"description": "Y component of a texture location at this point"
"description": "W component of a texture location at this point"
},
{
"name": "Linearity",
Expand Down
48 changes: 48 additions & 0 deletions test/data/obj/box_texture.obj
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Vertices: 8
# Points: 0
# Lines: 0
# Faces: 6
# Materials: 1

o 1

# Vertex list

v -0.5 -0.5 0.5
v -0.5 -0.5 -0.5
v -0.5 0.5 -0.5
v -0.5 0.5 0.5
v 0.5 -0.5 0.5
v 0.5 -0.5 -0.5
v 0.5 0.5 -0.5
v 0.5 0.5 0.5

vt -0.5 -0.5
vt -0.5 -0.5
vt -0.5 0.5
vt -0.5 0.5
vt 0.5 -0.5
vt 0.5 -0.5
vt 0.5 0.5
vt 0.5 0.5

vn -0.5 -0.5 0.5
vn -0.5 -0.5 -0.5
vn -0.5 0.5 -0.5
vn -0.5 0.5 0.5
vn 0.5 -0.5 0.5
vn 0.5 -0.5 -0.5
vn 0.5 0.5 -0.5
vn 0.5 0.5 0.5

# Point/Line/Face list

usemtl Default
f 4/4/4 3/3/3 2/2/2 1/1/1
f 2/2/2 6/6/6 5/5/5 1/1/1
f 3/3/3 7/7/7 6/6/6 2/2/2
f 8/8/8 7/7/7 3/3/3 4/4/4
f 5/5/5 8/8/8 4/4/4 1/1/1
f 6/6/6 7/7/7 8/8/8 5/5/5

# End of file
49 changes: 49 additions & 0 deletions test/data/obj/hyper_box.obj
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Vertices: 8
# Points: 0
# Lines: 0
# Faces: 6
# Materials: 1

o 1

# Vertex list

v -0.5 -0.5 0.5 0.5
v -0.5 -0.5 -0.5 0.5
v -0.5 0.5 -0.5 0.5
v -0.5 0.5 0.5 0.5
v 0.5 -0.5 0.5 0.5
v 0.5 -0.5 -0.5 0.5
v 0.5 0.5 -0.5 0.5
v 0.5 0.5 0.5 0.5


v -0.5 -0.5 0.5 -0.5
v -0.5 -0.5 -0.5 -0.5
v -0.5 0.5 -0.5 -0.5
v -0.5 0.5 0.5 -0.5
v 0.5 -0.5 0.5 -0.5
v 0.5 -0.5 -0.5 -0.5
v 0.5 0.5 -0.5 -0.5
v 0.5 0.5 0.5 -0.5


# Point/Line/Face list

usemtl Default
f 4 3 2 1
f 2 6 5 1
f 3 7 6 2
f 8 7 3 4
f 5 8 4 1
f 6 7 8 5

f 12 11 10 9
f 10 14 13 9
f 11 15 14 10
f 14 15 11 12
f 13 16 12 9
f 14 15 16 13


# End of file

0 comments on commit af2450a

Please sign in to comment.