Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ACGL
acgl
Commits
4c547a0f
Commit
4c547a0f
authored
Apr 16, 2013
by
Janis Born
Browse files
add a geometry loader for the Virtual Aachen (VAP) file format
parent
1c7dd000
Changes
3
Hide whitespace changes
Inline
Side-by-side
include/ACGL/OpenGL/Data/GeometryDataLoadStore.hh
View file @
4c547a0f
...
@@ -35,6 +35,10 @@ SharedGeometryData loadGeometryData(const std::string& _filename);
...
@@ -35,6 +35,10 @@ SharedGeometryData loadGeometryData(const std::string& _filename);
//! face normals are computed from the geometry
//! face normals are computed from the geometry
SharedGeometryData
loadGeometryDataFromOBJ
(
const
std
::
string
&
_filename
,
bool
_computeNormals
=
true
);
SharedGeometryData
loadGeometryDataFromOBJ
(
const
std
::
string
&
_filename
,
bool
_computeNormals
=
true
);
//! Loads from a VirtualAachen project (VAP) file. If _computeNormals and the mesh had no normals stored,
//! face normals are computed from the geometry
SharedGeometryData
loadGeometryDataFromVAP
(
const
std
::
string
&
_filename
,
bool
_computeNormals
=
true
);
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// library specific save
// library specific save
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
...
...
src/ACGL/OpenGL/Data/GeometryDataLoadStore.cc
View file @
4c547a0f
...
@@ -25,10 +25,14 @@ SharedGeometryData loadGeometryData(const std::string& _filename)
...
@@ -25,10 +25,14 @@ SharedGeometryData loadGeometryData(const std::string& _filename)
// lower case file ending:
// lower case file ending:
std
::
string
fileEnding
=
Base
::
FileHelpers
::
getFileEnding
(
_filename
);
std
::
string
fileEnding
=
Base
::
FileHelpers
::
getFileEnding
(
_filename
);
if
(
fileEnding
==
"obj"
)
if
(
fileEnding
==
"obj"
)
{
{
return
loadGeometryDataFromOBJ
(
_filename
);
return
loadGeometryDataFromOBJ
(
_filename
);
}
}
else
if
(
fileEnding
==
"vap"
)
{
return
loadGeometryDataFromVAP
(
_filename
);
}
else
else
{
{
error
()
<<
"geometry file format of "
<<
_filename
<<
" not supported"
<<
std
::
endl
;
error
()
<<
"geometry file format of "
<<
_filename
<<
" not supported"
<<
std
::
endl
;
...
...
src/ACGL/OpenGL/Data/GeometryDataLoadStoreVAP.cc
0 → 100644
View file @
4c547a0f
/***********************************************************************
* Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#include
<ACGL/OpenGL/Data/GeometryDataLoadStore.hh>
#include
<ACGL/Math/Math.hh>
#include
<ACGL/Base/StringOperations.hh>
#include
<fstream>
#include
<string>
using
namespace
ACGL
;
using
namespace
ACGL
::
OpenGL
;
using
namespace
ACGL
::
Utils
;
namespace
{
struct
IndexTuple
{
IndexTuple
()
:
position
(
-
1
),
texCoord
(
-
1
),
normal
(
-
1
),
metaData
(
0
,
0
,
0
,
0
)
{
}
int
position
;
int
texCoord
;
int
normal
;
glm
::
ivec4
metaData
;
};
void
skipLine
(
std
::
fstream
&
_stream
)
{
_stream
.
ignore
(
std
::
numeric_limits
<
std
::
streamsize
>::
max
(),
'\n'
);
}
// Parses a string of space-separated numbers into a packed floating-point vector (_data) with a maximum number of _maxDimension elements
void
parseVector
(
const
std
::
string
&
_string
,
int
_maxDimension
,
int
&
_dimension
,
float
*
_data
)
{
std
::
stringstream
stream
(
_string
);
float
temp
;
_dimension
=
0
;
while
(
stream
>>
temp
&&
_dimension
<
_maxDimension
)
{
_data
[
_dimension
]
=
temp
;
_dimension
++
;
}
}
// Turns an index parameter string into a std::vector of IndexTuples, e.g.
// "1//2 3//4 5//6" --> { IndexTuple(1, -1, 2), IndexTuple(3, -1, 4), IndexTuple(5, -1, 6) }
std
::
vector
<
IndexTuple
>
parseIndices
(
const
std
::
string
&
_string
)
{
std
::
vector
<
IndexTuple
>
indices
;
std
::
stringstream
stream
(
_string
);
std
::
string
vertexString
;
while
(
stream
>>
vertexString
)
{
std
::
vector
<
std
::
string
>
componentsString
=
ACGL
::
Base
::
StringOperations
::
split
(
vertexString
,
'/'
,
false
);
IndexTuple
indexTuple
;
for
(
int
i
=
0
;
i
<
std
::
min
<
int
>
(
componentsString
.
size
(),
3
);
++
i
)
{
std
::
string
&
componentString
=
componentsString
[
i
];
int
index
=
atoi
(
componentString
.
c_str
());
if
(
i
==
0
)
indexTuple
.
position
=
index
-
1
;
if
(
i
==
1
)
indexTuple
.
texCoord
=
index
-
1
;
if
(
i
==
2
)
indexTuple
.
normal
=
index
-
1
;
}
indices
.
push_back
(
indexTuple
);
}
return
indices
;
}
template
<
typename
T
>
void
append
(
char
*&
_data
,
T
_value
)
{
*
((
T
*
)
_data
)
=
_value
;
_data
+=
sizeof
(
T
);
}
}
namespace
ACGL
{
namespace
OpenGL
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// library specific load
///////////////////////////////////////////////////////////////////////////////////////////////////
SharedGeometryData
loadGeometryDataFromVAP
(
const
std
::
string
&
_filename
,
bool
_computeNormals
)
{
SharedGeometryData
data
;
std
::
fstream
file
(
_filename
.
c_str
(),
std
::
ios_base
::
in
);
if
(
!
file
.
good
())
{
error
()
<<
"could not open file "
<<
_filename
<<
std
::
endl
;
return
data
;
}
GLenum
primitiveType
=
GL_INVALID_ENUM
;
bool
hasTexCoords
=
false
;
bool
hasNormals
=
false
;
int
positionDimension
=
4
;
int
texCoordDimension
=
-
1
;
int
normalDimension
=
3
;
int
metaDataDimension
=
4
;
std
::
vector
<
glm
::
vec4
>
positionData
;
std
::
vector
<
glm
::
vec3
>
texCoordData
;
std
::
vector
<
glm
::
vec3
>
normalData
;
std
::
vector
<
IndexTuple
>
indices
;
glm
::
ivec4
currentMetadata
=
glm
::
ivec4
(
0
,
0
,
0
,
0
);
size_t
startOfPreviousFace
=
0
;
std
::
string
keyword
;
std
::
string
parameters
;
while
(
file
.
good
())
{
// Parse the current line
// If the line starts with a #, it is a comment
if
(
file
.
peek
()
==
'#'
)
{
skipLine
(
file
);
continue
;
}
// Otherwise, extract the first word and the remainder
file
>>
keyword
;
std
::
getline
(
file
,
parameters
);
if
(
keyword
==
"v"
)
// vertex position
{
glm
::
vec4
position
;
int
dimension
;
parseVector
(
parameters
,
4
,
dimension
,
(
float
*
)
&
position
);
if
(
dimension
<
4
)
position
.
w
=
1.0
;
if
(
dimension
<
3
)
{
error
()
<<
"could not load OBJ: wrong vertex position dimension"
<<
std
::
endl
;
return
data
;
}
positionData
.
push_back
(
position
);
}
else
if
(
keyword
==
"vt"
)
// vertex tex coord
{
glm
::
vec3
texCoord
;
int
dimension
;
parseVector
(
parameters
,
3
,
dimension
,
(
float
*
)
&
texCoord
);
if
(
texCoordDimension
<
0
)
texCoordDimension
=
dimension
;
else
if
(
texCoordDimension
!=
dimension
)
{
error
()
<<
"could not load OBJ: contains mixed tex coord dimensions"
<<
std
::
endl
;
return
data
;
}
hasTexCoords
=
true
;
texCoordData
.
push_back
(
texCoord
);
}
else
if
(
keyword
==
"vn"
)
// vertex normal
{
glm
::
vec3
normal
;
int
dimension
;
parseVector
(
parameters
,
3
,
dimension
,
(
float
*
)
&
normal
);
if
(
dimension
<
3
)
{
error
()
<<
"could not load OBJ: wrong vertex normal dimension"
<<
std
::
endl
;
return
data
;
}
hasNormals
=
true
;
normalData
.
push_back
(
normal
);
}
else
if
(
keyword
==
"p"
)
// point
{
// parse metadata values
std
::
stringstream
stream
(
parameters
);
stream
>>
currentMetadata
[
0
];
stream
>>
currentMetadata
[
1
];
stream
>>
currentMetadata
[
2
];
stream
>>
currentMetadata
[
3
];
for
(
size_t
i
=
startOfPreviousFace
;
i
<
indices
.
size
();
++
i
)
{
indices
[
i
].
metaData
=
currentMetadata
;
}
}
else
if
(
keyword
==
"l"
)
// line
{
if
(
primitiveType
==
GL_INVALID_ENUM
)
primitiveType
=
GL_LINES
;
else
if
(
primitiveType
!=
GL_LINES
)
{
error
()
<<
"could not load OBJ: contains mixed primitive types"
<<
std
::
endl
;
return
data
;
}
std
::
vector
<
IndexTuple
>
lineIndices
=
parseIndices
(
parameters
);
// add line segments for the line strip defined by the vertices
for
(
size_t
i
=
0
;
i
<
lineIndices
.
size
()
-
1
;
++
i
)
{
indices
.
push_back
(
lineIndices
[
i
]);
indices
.
push_back
(
lineIndices
[
i
+
1
]);
}
}
else
if
(
keyword
==
"f"
)
// face
{
if
(
primitiveType
==
GL_INVALID_ENUM
)
primitiveType
=
GL_TRIANGLES
;
else
if
(
primitiveType
!=
GL_TRIANGLES
)
{
error
()
<<
"could not load OBJ: contains mixed primitive types"
<<
std
::
endl
;
return
data
;
}
std
::
vector
<
IndexTuple
>
faceIndices
=
parseIndices
(
parameters
);
// triangulate the polygon defined by the indices
startOfPreviousFace
=
indices
.
size
();
for
(
size_t
i
=
1
;
i
<
faceIndices
.
size
()
-
1
;
++
i
)
{
indices
.
push_back
(
faceIndices
[
0
]);
indices
.
push_back
(
faceIndices
[
i
]);
indices
.
push_back
(
faceIndices
[
i
+
1
]);
}
}
else
if
(
keyword
==
"bevel"
||
keyword
==
"bmat"
||
keyword
==
"bsp"
||
keyword
==
"bzp"
||
keyword
==
"c_interp"
||
keyword
==
"cdc"
||
keyword
==
"cdp"
||
keyword
==
"con"
||
keyword
==
"cstype"
||
keyword
==
"ctech"
||
keyword
==
"curv"
||
keyword
==
"curv2"
||
keyword
==
"d_interp"
||
keyword
==
"deg"
||
keyword
==
"end"
||
keyword
==
"g"
||
keyword
==
"hole"
||
keyword
==
"lod"
||
keyword
==
"maplib"
||
keyword
==
"mg"
||
keyword
==
"mtllib"
||
keyword
==
"o"
||
keyword
==
"parm"
||
keyword
==
"res"
||
keyword
==
"s"
||
keyword
==
"scrv"
||
keyword
==
"shadow_obj"
||
keyword
==
"sp"
||
keyword
==
"stech"
||
keyword
==
"step"
||
keyword
==
"surf"
||
keyword
==
"trace_obj"
||
keyword
==
"trim"
||
keyword
==
"usemap"
||
keyword
==
"usemtl"
||
keyword
==
"vp"
)
{
// part of the OBJ specification (i.e. non-polygonal geometry, object groups, etc.)
// is not supported and is silently ignored
}
else
{
warning
()
<<
"unknown OBJ keyword ignored: "
<<
keyword
<<
std
::
endl
;
}
}
if
(
!
hasNormals
&&
_computeNormals
)
{
// perform own per-face normal creation only if the model had no own normals!
if
(
primitiveType
!=
GL_TRIANGLES
)
{
warning
()
<<
"computing OBJ normals is only supported for models with faces"
<<
std
::
endl
;
_computeNormals
=
false
;
}
else
{
debug
()
<<
"model has no normals, computing face normals"
<<
std
::
endl
;
hasNormals
=
true
;
}
}
else
if
(
hasNormals
)
{
// if the model has normals defined, no face normals have to get computed
_computeNormals
=
false
;
}
// all data are read from the file. construct an ArrayBuffer from the data
data
=
SharedGeometryData
(
new
GeometryData
());
size_t
strideSize
=
0
;
ArrayBuffer
::
Attribute
attrPosition
=
{
"aPosition"
,
GL_FLOAT
,
positionDimension
,
(
GLuint
)
0
,
GL_FALSE
,
0
,
GL_FALSE
};
strideSize
+=
positionDimension
*
sizeof
(
GLfloat
);
data
->
mAttributes
.
push_back
(
attrPosition
);
if
(
hasTexCoords
)
{
ArrayBuffer
::
Attribute
attrTexCoord
=
{
"aTexCoord"
,
GL_FLOAT
,
texCoordDimension
,
(
GLuint
)
strideSize
,
GL_FALSE
,
0
,
GL_FALSE
};
strideSize
+=
texCoordDimension
*
sizeof
(
GLfloat
);
data
->
mAttributes
.
push_back
(
attrTexCoord
);
}
if
(
hasNormals
)
{
ArrayBuffer
::
Attribute
attrNormal
=
{
"aNormal"
,
GL_FLOAT
,
normalDimension
,
(
GLuint
)
strideSize
,
GL_FALSE
,
0
,
GL_FALSE
};
strideSize
+=
normalDimension
*
sizeof
(
GLfloat
);
data
->
mAttributes
.
push_back
(
attrNormal
);
}
ArrayBuffer
::
Attribute
attrHouseID
=
{
"aHouseID"
,
GL_INT
,
1
,
(
GLuint
)
strideSize
,
GL_FALSE
,
0
,
GL_TRUE
};
strideSize
+=
sizeof
(
GLint
);
ArrayBuffer
::
Attribute
attrSurfaceID
=
{
"aSurfaceID"
,
GL_INT
,
1
,
(
GLuint
)
strideSize
,
GL_FALSE
,
0
,
GL_TRUE
};
strideSize
+=
sizeof
(
GLint
);
ArrayBuffer
::
Attribute
attrSubType
=
{
"aSubType"
,
GL_INT
,
1
,
(
GLuint
)
strideSize
,
GL_FALSE
,
0
,
GL_TRUE
};
strideSize
+=
sizeof
(
GLint
);
ArrayBuffer
::
Attribute
attrSubID
=
{
"aSubID"
,
GL_INT
,
1
,
(
GLuint
)
strideSize
,
GL_FALSE
,
0
,
GL_TRUE
};
strideSize
+=
sizeof
(
GLint
);
data
->
mAttributes
.
push_back
(
attrHouseID
);
data
->
mAttributes
.
push_back
(
attrSurfaceID
);
data
->
mAttributes
.
push_back
(
attrSubType
);
data
->
mAttributes
.
push_back
(
attrSubID
);
size_t
abDataSize
=
strideSize
*
indices
.
size
();
char
*
abData
=
new
char
[
abDataSize
];
char
*
it
=
abData
;
for
(
size_t
i
=
0
;
i
<
indices
.
size
();
++
i
)
{
const
glm
::
vec4
&
position
=
positionData
[
indices
[
i
].
position
];
append
<
GLfloat
>
(
it
,
position
.
x
);
append
<
GLfloat
>
(
it
,
position
.
y
);
append
<
GLfloat
>
(
it
,
position
.
z
);
append
<
GLfloat
>
(
it
,
position
.
w
);
if
(
hasTexCoords
)
{
const
glm
::
vec3
&
texCoord
=
texCoordData
[
indices
[
i
].
texCoord
];
for
(
int
dim
=
0
;
dim
<
texCoordDimension
;
++
dim
)
{
append
<
GLfloat
>
(
it
,
texCoord
[
dim
]);
}
}
if
(
hasNormals
)
{
if
(
_computeNormals
)
{
size_t
triangleIndex
=
i
/
3
;
glm
::
vec3
v0
=
(
glm
::
vec3
)
positionData
[
indices
[
3
*
triangleIndex
+
0
].
position
];
glm
::
vec3
v1
=
(
glm
::
vec3
)
positionData
[
indices
[
3
*
triangleIndex
+
1
].
position
];
glm
::
vec3
v2
=
(
glm
::
vec3
)
positionData
[
indices
[
3
*
triangleIndex
+
2
].
position
];
glm
::
vec3
normal
=
glm
::
normalize
(
glm
::
cross
(
v1
-
v0
,
v2
-
v0
));
append
<
GLfloat
>
(
it
,
normal
.
x
);
append
<
GLfloat
>
(
it
,
normal
.
y
);
append
<
GLfloat
>
(
it
,
normal
.
z
);
}
else
{
const
glm
::
vec3
&
normal
=
normalData
[
indices
[
i
].
normal
];
append
<
GLfloat
>
(
it
,
normal
.
x
);
append
<
GLfloat
>
(
it
,
normal
.
y
);
append
<
GLfloat
>
(
it
,
normal
.
z
);
}
}
const
IndexTuple
&
index
=
indices
[
i
];
append
<
GLint
>
(
it
,
index
.
metaData
.
x
);
append
<
GLint
>
(
it
,
index
.
metaData
.
y
);
append
<
GLint
>
(
it
,
index
.
metaData
.
z
);
append
<
GLint
>
(
it
,
index
.
metaData
.
w
);
}
data
->
setStrideSize
(
strideSize
);
data
->
setSize
(
abDataSize
);
data
->
setData
((
GLubyte
*
)
abData
);
return
data
;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// library specific save
///////////////////////////////////////////////////////////////////////////////////////////////////
}
// OpenGL
}
// ACGL
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment