@ -26,6 +26,7 @@
# include "ObjImporter.h"
# include "ObjImporter.h"
# include <climits>
# include <unordered_map>
# include <unordered_map>
# include <Corrade/Containers/GrowableArray.h>
# include <Corrade/Containers/GrowableArray.h>
# include <Corrade/Containers/Optional.h>
# include <Corrade/Containers/Optional.h>
@ -109,7 +110,7 @@ inline bool parseFloat(const char* const errorPrefix, const Containers::StringVi
return true ;
return true ;
}
}
inline bool parseUnsigned Int ( const char * const errorPrefix , const Containers : : StringView string , Unsigned Int& out ) {
inline bool parseInt ( const char * const errorPrefix , const Containers : : StringView string , Int & out ) {
/** @todo replace with something that can parse non-null-terminated stuff,
/** @todo replace with something that can parse non-null-terminated stuff,
then drop this " too long " error */
then drop this " too long " error */
char buffer [ 128 ] ;
char buffer [ 128 ] ;
@ -122,17 +123,17 @@ inline bool parseUnsignedInt(const char* const errorPrefix, const Containers::St
std : : memcpy ( buffer , string . data ( ) , size ) ;
std : : memcpy ( buffer , string . data ( ) , size ) ;
buffer [ size ] = ' \0 ' ;
buffer [ size ] = ' \0 ' ;
char * end ;
char * end ;
/* Not using strtou l() here as on Windows it's 32-bit and we wouldn't be
/* Not using strtol() here as on Windows it's 32-bit and we wouldn't be
able to detect overflows */
able to detect overflows */
/** @todo replace with something that can report errors in a non-insane
/** @todo replace with something that can report errors in a non-insane
way */
way */
const std : : u int64_t outLong = std : : strtou ll ( buffer , & end , 10 ) ;
const std : : int64_t outLong = std : : strtoll ( buffer , & end , 10 ) ;
if ( ! string | | std : : size_t ( end - buffer ) ! = size ) {
if ( ! string | | std : : size_t ( end - buffer ) ! = size ) {
Error { } < < errorPrefix < < " invalid integer literal " < < string ;
Error { } < < errorPrefix < < " invalid integer literal " < < string ;
return false ;
return false ;
}
}
if ( outLong > ~ std : : uint32_t { } ) {
if ( outLong < INT_MIN | | outLong > INT_MAX ) {
Error { } < < errorPrefix < < " too large integer literal " < < string ;
Error { } < < errorPrefix < < " too small or large integer literal " < < string ;
return false ;
return false ;
}
}
@ -399,9 +400,14 @@ Containers::Optional<MeshData> ObjImporter::doMesh(const UnsignedInt id, Unsigne
/* The number before first slash is a position index */
/* The number before first slash is a position index */
const Containers : : StringView foundSlash1 = indexTuple . findOr ( ' / ' , indexTuple . end ( ) ) ;
const Containers : : StringView foundSlash1 = indexTuple . findOr ( ' / ' , indexTuple . end ( ) ) ;
if ( ! parseUnsignedInt ( " Trade::ObjImporter::mesh(): " , indexTuple . prefix ( foundSlash1 . begin ( ) ) , data [ i ] [ 0 ] ) )
Int index ;
if ( ! parseInt ( " Trade::ObjImporter::mesh(): " , indexTuple . prefix ( foundSlash1 . begin ( ) ) , index ) )
return { } ;
return { } ;
data [ i ] [ 0 ] - = mesh . positionIndexOffset ;
/* If the number is negative, it counts from the end (-1 is
the last known position at this point , counting from 1 ) */
if ( index < 0 )
index + = positions . size ( ) + 1 ;
data [ i ] [ 0 ] = index - mesh . positionIndexOffset ;
/* If there was a slash, next is a texture coordinate or
/* If there was a slash, next is a texture coordinate or
empty */
empty */
@ -409,18 +415,28 @@ Containers::Optional<MeshData> ObjImporter::doMesh(const UnsignedInt id, Unsigne
indexTuple = indexTuple . suffix ( foundSlash1 . end ( ) ) ;
indexTuple = indexTuple . suffix ( foundSlash1 . end ( ) ) ;
const Containers : : StringView foundSlash2 = indexTuple . findOr ( ' / ' , indexTuple . end ( ) ) ;
const Containers : : StringView foundSlash2 = indexTuple . findOr ( ' / ' , indexTuple . end ( ) ) ;
if ( ! foundSlash2 | | foundSlash2 . begin ( ) ! = indexTuple . begin ( ) ) {
if ( ! foundSlash2 | | foundSlash2 . begin ( ) ! = indexTuple . begin ( ) ) {
if ( ! parseUnsigned Int ( " Trade::ObjImporter::mesh(): " , indexTuple . prefix ( foundSlash2 . begin ( ) ) , data [ i ] [ 1 ] ) )
if ( ! parseInt ( " Trade::ObjImporter::mesh(): " , indexTuple . prefix ( foundSlash2 . begin ( ) ) , index ) )
return { } ;
return { } ;
data [ i ] [ 1 ] - = mesh . textureCoordinateIndexOffset ;
/* If the number is negative, it counts from the end
( - 1 is the last known texture coordinate at this
point , counting from 1 ) */
if ( index < 0 )
index + = textureCoordinates . size ( ) + 1 ;
data [ i ] [ 1 ] = index - mesh . textureCoordinateIndexOffset ;
+ + textureCoordinateIndexCount ;
+ + textureCoordinateIndexCount ;
}
}
/* If there was a second slash, last is a normal */
/* If there was a second slash, last is a normal */
if ( foundSlash2 ) {
if ( foundSlash2 ) {
indexTuple = indexTuple . suffix ( foundSlash2 . end ( ) ) ;
indexTuple = indexTuple . suffix ( foundSlash2 . end ( ) ) ;
if ( ! parseUnsigned Int ( " Trade::ObjImporter::mesh(): " , indexTuple , data [ i ] [ 2 ] ) )
if ( ! parseInt ( " Trade::ObjImporter::mesh(): " , indexTuple , index ) )
return { } ;
return { } ;
data [ i ] [ 2 ] - = mesh . normalIndexOffset ;
/* If the number is negative, it counts from the end
( - 1 is the last known normal at this point , counting
from 1 ) */
if ( index < 0 )
index + = normals . size ( ) + 1 ;
data [ i ] [ 2 ] = index - mesh . normalIndexOffset ;
+ + normalIndexCount ;
+ + normalIndexCount ;
}
}
}
}