Merge remote-tracking branch 'github/master' into contrib
commit
4974c99288
|
@ -5,7 +5,8 @@ function generate()
|
||||||
|
|
||||||
if [ $ANDROID ]; then
|
if [ $ANDROID ]; then
|
||||||
ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
|
ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
|
||||||
else
|
fi
|
||||||
|
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||||
generate \
|
generate \
|
||||||
&& make -j4 \
|
&& make -j4 \
|
||||||
&& sudo make install \
|
&& sudo make install \
|
||||||
|
|
39
.travis.yml
39
.travis.yml
|
@ -1,22 +1,18 @@
|
||||||
|
language: cpp
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get update -qq
|
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
|
||||||
- sudo apt-get install cmake
|
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install cmake python3 homebrew/x11/freeglut; fi
|
||||||
- sudo apt-get install cmake python3
|
|
||||||
- if [ $LINUX ]; then sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
|
|
||||||
- echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
|
- echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
|
||||||
# install latest LCOV (1.9 was failing)
|
# install latest LCOV (1.9 was failing)
|
||||||
- cd ${TRAVIS_BUILD_DIR}
|
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz && tar xf lcov_1.11.orig.tar.gz && sudo make -C lcov-1.11/ install && gem install coveralls-lcov && lcov --version && g++ --version ; fi
|
||||||
- wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz
|
|
||||||
- tar xf lcov_1.11.orig.tar.gz
|
|
||||||
- sudo make -C lcov-1.11/ install
|
|
||||||
- gem install coveralls-lcov
|
|
||||||
- lcov --version
|
|
||||||
- g++ --version
|
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
osx_image: xcode8.3
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
|
- secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
|
||||||
|
@ -26,10 +22,11 @@ env:
|
||||||
- LINUX=1 TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
|
- LINUX=1 TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
|
||||||
- LINUX=1 SHARED_BUILD=ON ENABLE_COVERALLS=OFF
|
- LINUX=1 SHARED_BUILD=ON ENABLE_COVERALLS=OFF
|
||||||
- LINUX=1 SHARED_BUILD=OFF ENABLE_COVERALLS=OFF
|
- LINUX=1 SHARED_BUILD=OFF ENABLE_COVERALLS=OFF
|
||||||
- ANDROID=1
|
#exclude:
|
||||||
|
# - os: linux
|
||||||
language: cpp
|
# compiler: clang
|
||||||
|
# - os: osx
|
||||||
|
# compiler: gcc
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
- clang
|
- clang
|
||||||
|
@ -38,21 +35,19 @@ install:
|
||||||
- if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
|
- if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- cd ${TRAVIS_BUILD_DIR}
|
|
||||||
# init coverage to 0 (optional)
|
# init coverage to 0 (optional)
|
||||||
- lcov --directory . --zerocounters
|
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --zerocounters ; fi
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- export COVERALLS_SERVICE_NAME=travis-ci
|
- export COVERALLS_SERVICE_NAME=travis-ci
|
||||||
- export COVERALLS_REPO_TOKEN=abc12345
|
- export COVERALLS_REPO_TOKEN=abc12345
|
||||||
- . ./.travis.sh
|
- . ./.travis.sh
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
- cd ${TRAVIS_BUILD_DIR}
|
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info && lcov --list coverage.info && coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info ; fi
|
||||||
- lcov --directory . --capture --output-file coverage.info
|
|
||||||
- lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info
|
|
||||||
- lcov --list coverage.info
|
|
||||||
- coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info
|
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
coverity_scan:
|
coverity_scan:
|
||||||
|
|
|
@ -89,6 +89,10 @@ OPTION ( BUILD_DOCS
|
||||||
OFF
|
OFF
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
add_definitions( -DWIN32_LEAN_AND_MEAN )
|
||||||
|
endif()
|
||||||
|
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
set (CMAKE_PREFIX_PATH "D:\\libs\\devil")
|
set (CMAKE_PREFIX_PATH "D:\\libs\\devil")
|
||||||
OPTION( ASSIMP_INSTALL_PDB
|
OPTION( ASSIMP_INSTALL_PDB
|
||||||
|
@ -141,6 +145,13 @@ IF(ASSIMP_DOUBLE_PRECISION)
|
||||||
ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
|
ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
|
||||||
ENDIF(ASSIMP_DOUBLE_PRECISION)
|
ENDIF(ASSIMP_DOUBLE_PRECISION)
|
||||||
|
|
||||||
|
# Check for OpenMP support
|
||||||
|
find_package(OpenMP)
|
||||||
|
if (OPENMP_FOUND)
|
||||||
|
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
|
||||||
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_CURRENT_LIST_DIR}/revision.h.in
|
${CMAKE_CURRENT_LIST_DIR}/revision.h.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/revision.h
|
${CMAKE_CURRENT_BINARY_DIR}/revision.h
|
||||||
|
|
|
@ -66,8 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp {
|
||||||
{
|
|
||||||
// underlying structure for aiPropertyStore
|
// underlying structure for aiPropertyStore
|
||||||
typedef BatchLoader::PropertyMap PropertyMap;
|
typedef BatchLoader::PropertyMap PropertyMap;
|
||||||
|
|
||||||
|
@ -110,12 +109,11 @@ static std::mutex gLogStreamMutex;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Custom LogStream implementation for the C-API
|
// Custom LogStream implementation for the C-API
|
||||||
class LogToCallbackRedirector : public LogStream
|
class LogToCallbackRedirector : public LogStream {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
explicit LogToCallbackRedirector(const aiLogStream& s)
|
explicit LogToCallbackRedirector(const aiLogStream& s)
|
||||||
: stream (s) {
|
: stream (s) {
|
||||||
ai_assert(NULL != s.callback);
|
ai_assert(NULL != s.callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
~LogToCallbackRedirector() {
|
~LogToCallbackRedirector() {
|
||||||
|
@ -146,8 +144,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ReportSceneNotFoundError()
|
void ReportSceneNotFoundError() {
|
||||||
{
|
|
||||||
DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
|
DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
|
||||||
"The C-API does not accept scenes produced by the C++ API and vice versa");
|
"The C-API does not accept scenes produced by the C++ API and vice versa");
|
||||||
|
|
||||||
|
@ -156,22 +153,18 @@ void ReportSceneNotFoundError()
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Reads the given file and returns its content.
|
// Reads the given file and returns its content.
|
||||||
const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
|
const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) {
|
||||||
{
|
|
||||||
return aiImportFileEx(pFile,pFlags,NULL);
|
return aiImportFileEx(pFile,pFlags,NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS)
|
const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) {
|
||||||
{
|
|
||||||
return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
|
return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
|
const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
|
||||||
aiFileIO* pFS,
|
aiFileIO* pFS, const aiPropertyStore* props) {
|
||||||
const aiPropertyStore* props)
|
|
||||||
{
|
|
||||||
ai_assert(NULL != pFile);
|
ai_assert(NULL != pFile);
|
||||||
|
|
||||||
const aiScene* scene = NULL;
|
const aiScene* scene = NULL;
|
||||||
|
@ -190,7 +183,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
|
||||||
pimpl->mMatrixProperties = pp->matrices;
|
pimpl->mMatrixProperties = pp->matrices;
|
||||||
}
|
}
|
||||||
// setup a custom IO system if necessary
|
// setup a custom IO system if necessary
|
||||||
if (pFS) {
|
if (pFS) {
|
||||||
imp->SetIOHandler( new CIOSystemWrapper (pFS) );
|
imp->SetIOHandler( new CIOSystemWrapper (pFS) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,8 +194,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
|
||||||
if( scene) {
|
if( scene) {
|
||||||
ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
|
ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
|
||||||
priv->mOrigImporter = imp;
|
priv->mOrigImporter = imp;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// if failed, extract error code and destroy the import
|
// if failed, extract error code and destroy the import
|
||||||
gLastErrorString = imp->GetErrorString();
|
gLastErrorString = imp->GetErrorString();
|
||||||
delete imp;
|
delete imp;
|
||||||
|
@ -210,6 +202,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
|
||||||
|
|
||||||
// return imported data. If the import failed the pointer is NULL anyways
|
// return imported data. If the import failed the pointer is NULL anyways
|
||||||
ASSIMP_END_EXCEPTION_REGION(const aiScene*);
|
ASSIMP_END_EXCEPTION_REGION(const aiScene*);
|
||||||
|
|
||||||
return scene;
|
return scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1726,6 +1726,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
|
||||||
aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
|
aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
|
||||||
const Collada::Effect& pEffect, const std::string& pName)
|
const Collada::Effect& pEffect, const std::string& pName)
|
||||||
{
|
{
|
||||||
|
aiString result;
|
||||||
|
|
||||||
// recurse through the param references until we end up at an image
|
// recurse through the param references until we end up at an image
|
||||||
std::string name = pName;
|
std::string name = pName;
|
||||||
while( 1)
|
while( 1)
|
||||||
|
@ -1744,11 +1746,17 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
|
||||||
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
|
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
|
||||||
if( imIt == pParser.mImageLibrary.end())
|
if( imIt == pParser.mImageLibrary.end())
|
||||||
{
|
{
|
||||||
throw DeadlyImportError( format() <<
|
//missing texture should not stop the conversion
|
||||||
"Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
|
//throw DeadlyImportError( format() <<
|
||||||
}
|
// "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
|
||||||
|
|
||||||
aiString result;
|
DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\".");
|
||||||
|
|
||||||
|
//set default texture file name
|
||||||
|
result.Set(name + ".jpg");
|
||||||
|
ConvertPath(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// if this is an embedded texture image setup an aiTexture for it
|
// if this is an embedded texture image setup an aiTexture for it
|
||||||
if (imIt->second.mFileName.empty())
|
if (imIt->second.mFileName.empty())
|
||||||
|
|
|
@ -45,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/IOStream.hpp>
|
#include <assimp/IOStream.hpp>
|
||||||
#include "ParsingUtils.h"
|
#include "ParsingUtils.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -69,8 +71,8 @@ public:
|
||||||
/// @return true if successful.
|
/// @return true if successful.
|
||||||
bool close();
|
bool close();
|
||||||
|
|
||||||
/// @brief Returns the filesize.
|
/// @brief Returns the file-size.
|
||||||
/// @return The filesize.
|
/// @return The file-size.
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
|
|
||||||
/// @brief Returns the cache size.
|
/// @brief Returns the cache size.
|
||||||
|
@ -96,7 +98,17 @@ public:
|
||||||
/// @brief Will read the next line.
|
/// @brief Will read the next line.
|
||||||
/// @param buffer The buffer for the next line.
|
/// @param buffer The buffer for the next line.
|
||||||
/// @return true if successful.
|
/// @return true if successful.
|
||||||
bool getNextLine( std::vector<T> &buffer );
|
bool getNextDataLine( std::vector<T> &buffer, T continuationToken );
|
||||||
|
|
||||||
|
/// @brief Will read the next line ascii or binary end line char.
|
||||||
|
/// @param buffer The buffer for the next line.
|
||||||
|
/// @return true if successful.
|
||||||
|
bool getNextLine(std::vector<T> &buffer);
|
||||||
|
|
||||||
|
/// @brief Will read the next block.
|
||||||
|
/// @param buffer The buffer for the next block.
|
||||||
|
/// @return true if successful.
|
||||||
|
bool getNextBlock( std::vector<T> &buffer );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IOStream *m_stream;
|
IOStream *m_stream;
|
||||||
|
@ -227,15 +239,35 @@ size_t IOStreamBuffer<T>::getFilePos() const {
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool IOStreamBuffer<T>::getNextLine( std::vector<T> &buffer ) {
|
bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
|
||||||
buffer.resize( m_cacheSize );
|
buffer.resize( m_cacheSize );
|
||||||
if ( m_cachePos == m_cacheSize || 0 == m_filePos ) {
|
if ( m_cachePos == m_cacheSize || 0 == m_filePos ) {
|
||||||
if ( !readNextBlock() ) {
|
if ( !readNextBlock() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool continuationFound( false ), endOfDataLine( false );
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while ( !IsLineEnd( m_cache[ m_cachePos ] ) ) {
|
while ( !endOfDataLine ) {
|
||||||
|
if ( continuationToken == m_cache[ m_cachePos ] ) {
|
||||||
|
continuationFound = true;
|
||||||
|
++m_cachePos;
|
||||||
|
}
|
||||||
|
if ( IsLineEnd( m_cache[ m_cachePos ] ) ) {
|
||||||
|
if ( !continuationFound ) {
|
||||||
|
// the end of the data line
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// skip line end
|
||||||
|
while ( m_cache[m_cachePos] != '\n') {
|
||||||
|
++m_cachePos;
|
||||||
|
}
|
||||||
|
++m_cachePos;
|
||||||
|
continuationFound = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buffer[ i ] = m_cache[ m_cachePos ];
|
buffer[ i ] = m_cache[ m_cachePos ];
|
||||||
m_cachePos++;
|
m_cachePos++;
|
||||||
i++;
|
i++;
|
||||||
|
@ -245,10 +277,63 @@ bool IOStreamBuffer<T>::getNextLine( std::vector<T> &buffer ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[ i ] = '\n';
|
buffer[ i ] = '\n';
|
||||||
m_cachePos++;
|
m_cachePos++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
|
||||||
|
buffer.resize(m_cacheSize);
|
||||||
|
if (m_cachePos == m_cacheSize || 0 == m_filePos) {
|
||||||
|
if (!readNextBlock()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsLineEnd(m_cache[m_cachePos])) {
|
||||||
|
// skip line end
|
||||||
|
while (m_cache[m_cachePos] != '\n') {
|
||||||
|
++m_cachePos;
|
||||||
|
}
|
||||||
|
++m_cachePos;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (!IsLineEnd(m_cache[m_cachePos])) {
|
||||||
|
buffer[i] = m_cache[m_cachePos];
|
||||||
|
m_cachePos++;
|
||||||
|
i++;
|
||||||
|
if (m_cachePos >= m_cacheSize) {
|
||||||
|
if (!readNextBlock()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer[i] = '\n';
|
||||||
|
m_cachePos++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline
|
||||||
|
bool IOStreamBuffer<T>::getNextBlock( std::vector<T> &buffer) {
|
||||||
|
//just return the last blockvalue if getNextLine was used before
|
||||||
|
if ( m_cachePos != 0) {
|
||||||
|
buffer = std::vector<T>(m_cache.begin() + m_cachePos, m_cache.end());
|
||||||
|
m_cachePos = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( !readNextBlock() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
buffer = std::vector<T>(m_cache.begin(), m_cache.end());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // !ns Assimp
|
} // !ns Assimp
|
||||||
|
|
|
@ -109,7 +109,7 @@ ObjFile::Model *ObjFileParser::GetModel() const {
|
||||||
return m_pModel;
|
return m_pModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer)
|
/*void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer)
|
||||||
{
|
{
|
||||||
auto curPosition = buffer.begin();
|
auto curPosition = buffer.begin();
|
||||||
do
|
do
|
||||||
|
@ -123,13 +123,13 @@ void ignoreNewLines(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffe
|
||||||
std::vector<char> tempBuf;
|
std::vector<char> tempBuf;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
streamBuffer.getNextLine(tempBuf);
|
streamBuffer.getNextDataLine(tempBuf, '\\' );
|
||||||
} while (tempBuf[0]=='\n');
|
} while (tempBuf[0]=='\n');
|
||||||
*curPosition = ' ';
|
*curPosition = ' ';
|
||||||
std::copy(tempBuf.cbegin(), tempBuf.cend(), ++curPosition);
|
std::copy(tempBuf.cbegin(), tempBuf.cend(), ++curPosition);
|
||||||
}
|
}
|
||||||
} while (*curPosition!='\n');
|
} while (*curPosition!='\n');
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
|
void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
|
||||||
// only update every 100KB or it'll be too slow
|
// only update every 100KB or it'll be too slow
|
||||||
|
@ -142,7 +142,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
|
||||||
size_t lastFilePos( 0 );
|
size_t lastFilePos( 0 );
|
||||||
|
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
while ( streamBuffer.getNextLine( buffer ) ) {
|
while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) {
|
||||||
m_DataIt = buffer.begin();
|
m_DataIt = buffer.begin();
|
||||||
m_DataItEnd = buffer.end();
|
m_DataItEnd = buffer.end();
|
||||||
|
|
||||||
|
@ -154,14 +154,14 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
|
||||||
progressCounter++;
|
progressCounter++;
|
||||||
m_progress->UpdateFileRead( progressOffset + processed * 2, progressTotal );
|
m_progress->UpdateFileRead( progressOffset + processed * 2, progressTotal );
|
||||||
}
|
}
|
||||||
//ignoreNewLines(streamBuffer, buffer);
|
|
||||||
// parse line
|
// parse line
|
||||||
switch (*m_DataIt) {
|
switch (*m_DataIt) {
|
||||||
case 'v': // Parse a vertex texture coordinate
|
case 'v': // Parse a vertex texture coordinate
|
||||||
{
|
{
|
||||||
++m_DataIt;
|
++m_DataIt;
|
||||||
if (*m_DataIt == ' ' || *m_DataIt == '\t') {
|
if (*m_DataIt == ' ' || *m_DataIt == '\t') {
|
||||||
size_t numComponents = getNumComponentsInLine();
|
size_t numComponents = getNumComponentsInDataDefinition();
|
||||||
if (numComponents == 3) {
|
if (numComponents == 3) {
|
||||||
// read in vertex definition
|
// read in vertex definition
|
||||||
getVector3(m_pModel->m_Vertices);
|
getVector3(m_pModel->m_Vertices);
|
||||||
|
@ -245,7 +245,6 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
pf_skip_line:
|
pf_skip_line:
|
||||||
|
|
||||||
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -274,21 +273,44 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length) {
|
||||||
pBuffer[index] = '\0';
|
pBuffer[index] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ObjFileParser::getNumComponentsInLine() {
|
static bool isDataDefinitionEnd( const char *tmp ) {
|
||||||
|
if ( *tmp == '\\' ) {
|
||||||
|
tmp++;
|
||||||
|
if ( IsLineEnd( *tmp ) ) {
|
||||||
|
tmp++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ObjFileParser::getNumComponentsInDataDefinition() {
|
||||||
size_t numComponents( 0 );
|
size_t numComponents( 0 );
|
||||||
const char* tmp( &m_DataIt[0] );
|
const char* tmp( &m_DataIt[0] );
|
||||||
while( !IsLineEnd( *tmp ) ) {
|
bool end_of_definition = false;
|
||||||
|
while ( !end_of_definition ) {
|
||||||
|
if ( isDataDefinitionEnd( tmp ) ) {
|
||||||
|
tmp += 2;
|
||||||
|
} else if ( IsLineEnd( *tmp ) ) {
|
||||||
|
end_of_definition = true;
|
||||||
|
}
|
||||||
if ( !SkipSpaces( &tmp ) ) {
|
if ( !SkipSpaces( &tmp ) ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
const bool isNum( IsNumeric( *tmp ) );
|
||||||
SkipToken( tmp );
|
SkipToken( tmp );
|
||||||
++numComponents;
|
if ( isNum ) {
|
||||||
|
++numComponents;
|
||||||
|
}
|
||||||
|
if ( !SkipSpaces( &tmp ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return numComponents;
|
return numComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
|
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
|
||||||
size_t numComponents = getNumComponentsInLine();
|
size_t numComponents = getNumComponentsInDataDefinition();
|
||||||
ai_real x, y, z;
|
ai_real x, y, z;
|
||||||
if( 2 == numComponents ) {
|
if( 2 == numComponents ) {
|
||||||
copyNextWord( m_buffer, Buffersize );
|
copyNextWord( m_buffer, Buffersize );
|
||||||
|
@ -397,10 +419,6 @@ static const std::string DefaultObjName = "defaultobject";
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Get values for a new face instance
|
// Get values for a new face instance
|
||||||
void ObjFileParser::getFace( aiPrimitiveType type ) {
|
void ObjFileParser::getFace( aiPrimitiveType type ) {
|
||||||
//copyNextLine(m_buffer, Buffersize);
|
|
||||||
//char *pPtr = m_DataIt;
|
|
||||||
//char *pPtr = m_buffer;
|
|
||||||
//char *pEnd = &pPtr[Buffersize];
|
|
||||||
m_DataIt = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
|
m_DataIt = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
|
||||||
if ( m_DataIt == m_DataItEnd || *m_DataIt == '\0' ) {
|
if ( m_DataIt == m_DataItEnd || *m_DataIt == '\0' ) {
|
||||||
return;
|
return;
|
||||||
|
@ -571,14 +589,7 @@ void ObjFileParser::getMaterialDesc() {
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Get a comment, values will be skipped
|
// Get a comment, values will be skipped
|
||||||
void ObjFileParser::getComment() {
|
void ObjFileParser::getComment() {
|
||||||
while (m_DataIt != m_DataItEnd) {
|
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
||||||
if ( '\n' == (*m_DataIt)) {
|
|
||||||
++m_DataIt;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
++m_DataIt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
|
@ -91,6 +91,8 @@ protected:
|
||||||
void copyNextWord(char *pBuffer, size_t length);
|
void copyNextWord(char *pBuffer, size_t length);
|
||||||
/// Method to copy the new line.
|
/// Method to copy the new line.
|
||||||
// void copyNextLine(char *pBuffer, size_t length);
|
// void copyNextLine(char *pBuffer, size_t length);
|
||||||
|
/// Get the number of components in a line.
|
||||||
|
size_t getNumComponentsInDataDefinition();
|
||||||
/// Stores the vector
|
/// Stores the vector
|
||||||
void getVector( std::vector<aiVector3D> &point3d_array );
|
void getVector( std::vector<aiVector3D> &point3d_array );
|
||||||
/// Stores the following 3d vector.
|
/// Stores the following 3d vector.
|
||||||
|
@ -129,8 +131,6 @@ protected:
|
||||||
bool needsNewMesh( const std::string &rMaterialName );
|
bool needsNewMesh( const std::string &rMaterialName );
|
||||||
/// Error report in token
|
/// Error report in token
|
||||||
void reportErrorTokenInFace();
|
void reportErrorTokenInFace();
|
||||||
/// Get the number of components in a line.
|
|
||||||
size_t getNumComponentsInLine();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Copy and assignment constructor should be private
|
// Copy and assignment constructor should be private
|
||||||
|
|
|
@ -116,14 +116,16 @@ inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
|
||||||
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
|
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
if ( it != end )
|
|
||||||
{
|
if ( it != end ) {
|
||||||
++it;
|
++it;
|
||||||
++uiLine;
|
++uiLine;
|
||||||
}
|
}
|
||||||
// fix .. from time to time there are spaces at the beginning of a material line
|
// fix .. from time to time there are spaces at the beginning of a material line
|
||||||
while ( it != end && (*it == '\t' || *it == ' ') )
|
while ( it != end && ( *it == '\t' || *it == ' ' ) ) {
|
||||||
++it;
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1826
code/PlyLoader.cpp
1826
code/PlyLoader.cpp
File diff suppressed because it is too large
Load Diff
|
@ -68,7 +68,6 @@ public:
|
||||||
PLYImporter();
|
PLYImporter();
|
||||||
~PLYImporter();
|
~PLYImporter();
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
@ -78,6 +77,16 @@ public:
|
||||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
|
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
|
||||||
bool checkSig) const;
|
bool checkSig) const;
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Extract a vertex from the DOM
|
||||||
|
*/
|
||||||
|
void LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Extract a face from the DOM
|
||||||
|
*/
|
||||||
|
void LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
@ -94,53 +103,10 @@ protected:
|
||||||
IOSystem* pIOHandler);
|
IOSystem* pIOHandler);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
/** Extract vertices from the DOM
|
|
||||||
*/
|
|
||||||
void LoadVertices(std::vector<aiVector3D>* pvOut,
|
|
||||||
bool p_bNormals = false);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
/** Extract vertex color channels from the DOM
|
|
||||||
*/
|
|
||||||
void LoadVertexColor(std::vector<aiColor4D>* pvOut);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
/** Extract texture coordinate channels from the DOM
|
|
||||||
*/
|
|
||||||
void LoadTextureCoordinates(std::vector<aiVector2D>* pvOut);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
/** Extract a face list from the DOM
|
|
||||||
*/
|
|
||||||
void LoadFaces(std::vector<PLY::Face>* pvOut);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Extract a material list from the DOM
|
/** Extract a material list from the DOM
|
||||||
*/
|
*/
|
||||||
void LoadMaterial(std::vector<aiMaterial*>* pvOut);
|
void LoadMaterial(std::vector<aiMaterial*>* pvOut, std::string &defaultTexture, const bool pointsOnly);
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
/** Validate material indices, replace default material identifiers
|
|
||||||
*/
|
|
||||||
void ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces,
|
|
||||||
std::vector<aiMaterial*>* avMaterials);
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
/** Convert all meshes into our ourer representation
|
|
||||||
*/
|
|
||||||
void ConvertMeshes(std::vector<PLY::Face>* avFaces,
|
|
||||||
const std::vector<aiVector3D>* avPositions,
|
|
||||||
const std::vector<aiVector3D>* avNormals,
|
|
||||||
const std::vector<aiColor4D>* avColors,
|
|
||||||
const std::vector<aiVector2D>* avTexCoords,
|
|
||||||
const std::vector<aiMaterial*>* avMaterials,
|
|
||||||
std::vector<aiMesh*>* avOut);
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Static helper to parse a color from four single channels in
|
/** Static helper to parse a color from four single channels in
|
||||||
|
@ -151,7 +117,6 @@ protected:
|
||||||
PLY::EDataType aiTypes[4],
|
PLY::EDataType aiTypes[4],
|
||||||
aiColor4D* clrOut);
|
aiColor4D* clrOut);
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Static helper to parse a color channel value. The input value
|
/** Static helper to parse a color channel value. The input value
|
||||||
* is normalized to 0-1.
|
* is normalized to 0-1.
|
||||||
|
@ -160,12 +125,14 @@ protected:
|
||||||
PLY::PropertyInstance::ValueUnion val,
|
PLY::PropertyInstance::ValueUnion val,
|
||||||
PLY::EDataType eType);
|
PLY::EDataType eType);
|
||||||
|
|
||||||
|
|
||||||
/** Buffer to hold the loaded file */
|
/** Buffer to hold the loaded file */
|
||||||
unsigned char* mBuffer;
|
unsigned char* mBuffer;
|
||||||
|
|
||||||
/** Document object model representation extracted from the file */
|
/** Document object model representation extracted from the file */
|
||||||
PLY::DOM* pcDOM;
|
PLY::DOM* pcDOM;
|
||||||
|
|
||||||
|
/** Mesh generated by loader */
|
||||||
|
aiMesh* mGeneratedMesh;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
1792
code/PlyParser.cpp
1792
code/PlyParser.cpp
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,6 @@ Open Asset Import Library (assimp)
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006-2017, assimp team
|
Copyright (c) 2006-2017, assimp team
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -46,19 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
#include "ParsingUtils.h"
|
#include "ParsingUtils.h"
|
||||||
|
#include "IOStreamBuffer.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace Assimp
|
namespace Assimp
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//pre-declaration
|
||||||
|
class PLYImporter;
|
||||||
|
|
||||||
// http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/
|
// http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/
|
||||||
// http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf
|
// http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf
|
||||||
// http://www.okino.com/conv/exp_ply.htm
|
// http://www.okino.com/conv/exp_ply.htm
|
||||||
namespace PLY
|
namespace PLY
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
/*
|
/*
|
||||||
name type number of bytes
|
name type number of bytes
|
||||||
|
@ -197,6 +198,9 @@ enum EElementSemantic
|
||||||
//! The element is a material description
|
//! The element is a material description
|
||||||
EEST_Material,
|
EEST_Material,
|
||||||
|
|
||||||
|
//! texture path
|
||||||
|
EEST_TextureFile,
|
||||||
|
|
||||||
//! Marks invalid entries
|
//! Marks invalid entries
|
||||||
EEST_INVALID
|
EEST_INVALID
|
||||||
};
|
};
|
||||||
|
@ -238,16 +242,15 @@ public:
|
||||||
//! string is either '\n', '\r' or '\0'. Return value is false
|
//! string is either '\n', '\r' or '\0'. Return value is false
|
||||||
//! if the input string is NOT a valid property (E.g. does
|
//! if the input string is NOT a valid property (E.g. does
|
||||||
//! not start with the "property" keyword)
|
//! not start with the "property" keyword)
|
||||||
static bool ParseProperty (const char* pCur, const char** pCurOut,
|
static bool ParseProperty(std::vector<char> &buffer, Property* pOut);
|
||||||
Property* pOut);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse a data type from a string
|
//! Parse a data type from a string
|
||||||
static EDataType ParseDataType(const char* pCur,const char** pCurOut);
|
static EDataType ParseDataType(std::vector<char> &buffer);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse a semantic from a string
|
//! Parse a semantic from a string
|
||||||
static ESemantic ParseSemantic(const char* pCur,const char** pCurOut);
|
static ESemantic ParseSemantic(std::vector<char> &buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
@ -285,13 +288,11 @@ public:
|
||||||
//! Parse an element from a string.
|
//! Parse an element from a string.
|
||||||
//! The function will parse all properties contained in the
|
//! The function will parse all properties contained in the
|
||||||
//! element, too.
|
//! element, too.
|
||||||
static bool ParseElement (const char* pCur, const char** pCurOut,
|
static bool ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, Element* pOut);
|
||||||
Element* pOut);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse a semantic from a string
|
//! Parse a semantic from a string
|
||||||
static EElementSemantic ParseSemantic(const char* pCur,
|
static EElementSemantic ParseSemantic(std::vector<char> &buffer);
|
||||||
const char** pCurOut);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
@ -331,13 +332,13 @@ public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse a property instance
|
//! Parse a property instance
|
||||||
static bool ParseInstance (const char* pCur,const char** pCurOut,
|
static bool ParseInstance(const char* &pCur,
|
||||||
const Property* prop, PropertyInstance* p_pcOut);
|
const Property* prop, PropertyInstance* p_pcOut);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse a property instance in binary format
|
//! Parse a property instance in binary format
|
||||||
static bool ParseInstanceBinary (const char* pCur,const char** pCurOut,
|
static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
|
||||||
const Property* prop, PropertyInstance* p_pcOut,bool p_bBE);
|
const char* &pCur, unsigned int &bufferSize, const Property* prop, PropertyInstance* p_pcOut, bool p_bBE);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Get the default value for a given data type
|
//! Get the default value for a given data type
|
||||||
|
@ -345,13 +346,12 @@ public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse a value
|
//! Parse a value
|
||||||
static bool ParseValue(const char* pCur,const char** pCurOut,
|
static bool ParseValue(const char* &pCur, EDataType eType, ValueUnion* out);
|
||||||
EDataType eType,ValueUnion* out);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse a binary value
|
//! Parse a binary value
|
||||||
static bool ParseValueBinary(const char* pCur,const char** pCurOut,
|
static bool ParseValueBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
|
||||||
EDataType eType,ValueUnion* out,bool p_bBE);
|
const char* &pCur, unsigned int &bufferSize, EDataType eType, ValueUnion* out, bool p_bBE);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Convert a property value to a given type TYPE
|
//! Convert a property value to a given type TYPE
|
||||||
|
@ -375,13 +375,13 @@ public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse an element instance
|
//! Parse an element instance
|
||||||
static bool ParseInstance (const char* pCur,const char** pCurOut,
|
static bool ParseInstance(const char* &pCur,
|
||||||
const Element* pcElement, ElementInstance* p_pcOut);
|
const Element* pcElement, ElementInstance* p_pcOut);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse a binary element instance
|
//! Parse a binary element instance
|
||||||
static bool ParseInstanceBinary (const char* pCur,const char** pCurOut,
|
static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
|
||||||
const Element* pcElement, ElementInstance* p_pcOut,bool p_bBE);
|
const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstance* p_pcOut, bool p_bBE);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
@ -400,13 +400,13 @@ public:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse an element instance list
|
//! Parse an element instance list
|
||||||
static bool ParseInstanceList (const char* pCur,const char** pCurOut,
|
static bool ParseInstanceList(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
|
||||||
const Element* pcElement, ElementInstanceList* p_pcOut);
|
const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Parse a binary element instance list
|
//! Parse a binary element instance list
|
||||||
static bool ParseInstanceListBinary (const char* pCur,const char** pCurOut,
|
static bool ParseInstanceListBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer,
|
||||||
const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE);
|
const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader, bool p_bBE);
|
||||||
};
|
};
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
/** \brief Class to represent the document object model of an ASCII or binary
|
/** \brief Class to represent the document object model of an ASCII or binary
|
||||||
|
@ -428,50 +428,33 @@ public:
|
||||||
|
|
||||||
//! Parse the DOM for a PLY file. The input string is assumed
|
//! Parse the DOM for a PLY file. The input string is assumed
|
||||||
//! to be terminated with zero
|
//! to be terminated with zero
|
||||||
static bool ParseInstance (const char* pCur,DOM* p_pcOut);
|
static bool ParseInstance(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader);
|
||||||
static bool ParseInstanceBinary (const char* pCur,
|
static bool ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE);
|
||||||
DOM* p_pcOut,bool p_bBE);
|
|
||||||
|
|
||||||
//! Skip all comment lines after this
|
//! Skip all comment lines after this
|
||||||
static bool SkipComments (const char* pCur,const char** pCurOut);
|
static bool SkipComments(std::vector<char> &buffer);
|
||||||
|
|
||||||
|
static bool SkipSpaces(std::vector<char> &buffer);
|
||||||
|
|
||||||
|
static bool SkipLine(std::vector<char> &buffer);
|
||||||
|
|
||||||
|
static bool TokenMatch(std::vector<char> &buffer, const char* token, unsigned int len);
|
||||||
|
|
||||||
|
static bool SkipSpacesAndLineEnd(std::vector<char> &buffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Handle the file header and read all element descriptions
|
//! Handle the file header and read all element descriptions
|
||||||
bool ParseHeader (const char* pCur,const char** pCurOut, bool p_bBE);
|
bool ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool p_bBE);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Read in all element instance lists
|
//! Read in all element instance lists
|
||||||
bool ParseElementInstanceLists (const char* pCur,const char** pCurOut);
|
bool ParseElementInstanceLists(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, PLYImporter* loader);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
//! Read in all element instance lists for a binary file format
|
//! Read in all element instance lists for a binary file format
|
||||||
bool ParseElementInstanceListsBinary (const char* pCur,
|
bool ParseElementInstanceListsBinary(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, const char* &pCur, unsigned int &bufferSize, PLYImporter* loader, bool p_bBE);
|
||||||
const char** pCurOut,bool p_bBE);
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
|
||||||
/** \brief Helper class to represent a loaded PLY face
|
|
||||||
*/
|
|
||||||
class Face
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
Face()
|
|
||||||
: iMaterialIndex(0xFFFFFFFF)
|
|
||||||
{
|
|
||||||
// set all indices to zero by default
|
|
||||||
mIndices.resize(3,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//! List of vertex indices
|
|
||||||
std::vector<unsigned int> mIndices;
|
|
||||||
|
|
||||||
//! Material index
|
|
||||||
unsigned int iMaterialIndex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
|
@ -211,20 +211,20 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
||||||
for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
|
for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
|
||||||
pScene->mRootNode->mMeshes[i] = i;
|
pScene->mRootNode->mMeshes[i] = i;
|
||||||
|
|
||||||
// create a single default material, using a light gray diffuse color for consistency with
|
// create a single default material, using a white diffuse color for consistency with
|
||||||
// other geometric types (e.g., PLY).
|
// other geometric types (e.g., PLY).
|
||||||
aiMaterial* pcMat = new aiMaterial();
|
aiMaterial* pcMat = new aiMaterial();
|
||||||
aiString s;
|
aiString s;
|
||||||
s.Set(AI_DEFAULT_MATERIAL_NAME);
|
s.Set(AI_DEFAULT_MATERIAL_NAME);
|
||||||
pcMat->AddProperty(&s, AI_MATKEY_NAME);
|
pcMat->AddProperty(&s, AI_MATKEY_NAME);
|
||||||
|
|
||||||
aiColor4D clrDiffuse(ai_real(0.6),ai_real(0.6),ai_real(0.6),ai_real(1.0));
|
aiColor4D clrDiffuse(ai_real(1.0),ai_real(1.0),ai_real(1.0),ai_real(1.0));
|
||||||
if (bMatClr) {
|
if (bMatClr) {
|
||||||
clrDiffuse = clrColorDefault;
|
clrDiffuse = clrColorDefault;
|
||||||
}
|
}
|
||||||
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
|
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
|
||||||
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
|
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
|
||||||
clrDiffuse = aiColor4D( ai_real( 0.05), ai_real( 0.05), ai_real( 0.05), ai_real( 1.0));
|
clrDiffuse = aiColor4D( ai_real(1.0), ai_real(1.0), ai_real(1.0), ai_real(1.0));
|
||||||
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
|
pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
|
||||||
|
|
||||||
pScene->mNumMaterials = 1;
|
pScene->mNumMaterials = 1;
|
||||||
|
|
|
@ -126,9 +126,8 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
|
||||||
const ai_real dist = pPosition * mPlaneNormal;
|
const ai_real dist = pPosition * mPlaneNormal;
|
||||||
const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
|
const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
|
||||||
|
|
||||||
// clear the array in this strange fashion because a simple clear() would also deallocate
|
// clear the array
|
||||||
// the array which we want to avoid
|
poResults.clear();
|
||||||
poResults.erase( poResults.begin(), poResults.end());
|
|
||||||
|
|
||||||
// quick check for positions outside the range
|
// quick check for positions outside the range
|
||||||
if( mPositions.size() == 0)
|
if( mPositions.size() == 0)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
||||||
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
|
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
|
||||||
// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
|
// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
|
||||||
|
@ -22,6 +24,7 @@
|
||||||
#include <assimp/defs.h>
|
#include <assimp/defs.h>
|
||||||
|
|
||||||
#include "StringComparison.h"
|
#include "StringComparison.h"
|
||||||
|
#include <assimp/DefaultLogger.hpp>
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -192,7 +195,7 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
|
||||||
uint64_t value = 0;
|
uint64_t value = 0;
|
||||||
|
|
||||||
if ( *in < '0' || *in > '9' )
|
if ( *in < '0' || *in > '9' )
|
||||||
throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value.");
|
throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value.");
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
while ( running )
|
while ( running )
|
||||||
|
@ -202,8 +205,12 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int*
|
||||||
|
|
||||||
const uint64_t new_value = ( value * 10 ) + ( *in - '0' );
|
const uint64_t new_value = ( value * 10 ) + ( *in - '0' );
|
||||||
|
|
||||||
if (new_value < value) /* numeric overflow, we rely on you */
|
// numeric overflow, we rely on you
|
||||||
throw std::overflow_error(std::string("Converting the string \"") + in + "\" into a value resulted in overflow.");
|
if ( new_value < value ) {
|
||||||
|
DefaultLogger::get()->warn( std::string( "Converting the string \"" ) + in + "\" into a value resulted in overflow." );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//throw std::overflow_error();
|
||||||
|
|
||||||
value = new_value;
|
value = new_value;
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ void Triangle::Clear()
|
||||||
points_[0]=points_[1]=points_[2] = NULL;
|
points_[0]=points_[1]=points_[2] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Triangle::ClearNeighbor(Triangle *triangle )
|
void Triangle::ClearNeighbor(const Triangle *triangle )
|
||||||
{
|
{
|
||||||
if( neighbors_[0] == triangle )
|
if( neighbors_[0] == triangle )
|
||||||
{
|
{
|
||||||
|
@ -116,13 +116,9 @@ void Triangle::ClearDelunayEdges()
|
||||||
delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
|
delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point* Triangle::OppositePoint(Triangle& t, Point& p)
|
Point* Triangle::OppositePoint(Triangle& t, const Point& p)
|
||||||
{
|
{
|
||||||
Point *cw = t.PointCW(p);
|
Point *cw = t.PointCW(p);
|
||||||
//double x = cw->x;
|
|
||||||
//double y = cw->y;
|
|
||||||
//x = p.x;
|
|
||||||
//y = p.y;
|
|
||||||
return PointCW(*cw);
|
return PointCW(*cw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,8 +160,7 @@ int Triangle::Index(const Point* p)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
|
return -1;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Triangle::EdgeIndex(const Point* p1, const Point* p2)
|
int Triangle::EdgeIndex(const Point* p1, const Point* p2)
|
||||||
|
@ -192,7 +187,7 @@ int Triangle::EdgeIndex(const Point* p1, const Point* p2)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Triangle::MarkConstrainedEdge(const int index)
|
void Triangle::MarkConstrainedEdge(int index)
|
||||||
{
|
{
|
||||||
constrained_edge[index] = true;
|
constrained_edge[index] = true;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +210,7 @@ void Triangle::MarkConstrainedEdge(Point* p, Point* q)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The point counter-clockwise to given point
|
// The point counter-clockwise to given point
|
||||||
Point* Triangle::PointCW(Point& point)
|
Point* Triangle::PointCW(const Point& point)
|
||||||
{
|
{
|
||||||
if (&point == points_[0]) {
|
if (&point == points_[0]) {
|
||||||
return points_[2];
|
return points_[2];
|
||||||
|
@ -225,12 +220,11 @@ Point* Triangle::PointCW(Point& point)
|
||||||
return points_[1];
|
return points_[1];
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
|
return NULL;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The point counter-clockwise to given point
|
// The point counter-clockwise to given point
|
||||||
Point* Triangle::PointCCW(Point& point)
|
Point* Triangle::PointCCW(const Point& point)
|
||||||
{
|
{
|
||||||
if (&point == points_[0]) {
|
if (&point == points_[0]) {
|
||||||
return points_[1];
|
return points_[1];
|
||||||
|
@ -240,12 +234,11 @@ Point* Triangle::PointCCW(Point& point)
|
||||||
return points_[0];
|
return points_[0];
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
|
return NULL;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The neighbor clockwise to given point
|
// The neighbor clockwise to given point
|
||||||
Triangle* Triangle::NeighborCW(Point& point)
|
Triangle* Triangle::NeighborCW(const Point& point)
|
||||||
{
|
{
|
||||||
if (&point == points_[0]) {
|
if (&point == points_[0]) {
|
||||||
return neighbors_[1];
|
return neighbors_[1];
|
||||||
|
@ -256,7 +249,7 @@ Triangle* Triangle::NeighborCW(Point& point)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The neighbor counter-clockwise to given point
|
// The neighbor counter-clockwise to given point
|
||||||
Triangle* Triangle::NeighborCCW(Point& point)
|
Triangle* Triangle::NeighborCCW(const Point& point)
|
||||||
{
|
{
|
||||||
if (&point == points_[0]) {
|
if (&point == points_[0]) {
|
||||||
return neighbors_[2];
|
return neighbors_[2];
|
||||||
|
@ -266,7 +259,7 @@ Triangle* Triangle::NeighborCCW(Point& point)
|
||||||
return neighbors_[1];
|
return neighbors_[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Triangle::GetConstrainedEdgeCCW(Point& p)
|
bool Triangle::GetConstrainedEdgeCCW(const Point& p)
|
||||||
{
|
{
|
||||||
if (&p == points_[0]) {
|
if (&p == points_[0]) {
|
||||||
return constrained_edge[2];
|
return constrained_edge[2];
|
||||||
|
@ -276,7 +269,7 @@ bool Triangle::GetConstrainedEdgeCCW(Point& p)
|
||||||
return constrained_edge[1];
|
return constrained_edge[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Triangle::GetConstrainedEdgeCW(Point& p)
|
bool Triangle::GetConstrainedEdgeCW(const Point& p)
|
||||||
{
|
{
|
||||||
if (&p == points_[0]) {
|
if (&p == points_[0]) {
|
||||||
return constrained_edge[1];
|
return constrained_edge[1];
|
||||||
|
@ -286,7 +279,7 @@ bool Triangle::GetConstrainedEdgeCW(Point& p)
|
||||||
return constrained_edge[0];
|
return constrained_edge[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
|
void Triangle::SetConstrainedEdgeCCW(const Point& p, bool ce)
|
||||||
{
|
{
|
||||||
if (&p == points_[0]) {
|
if (&p == points_[0]) {
|
||||||
constrained_edge[2] = ce;
|
constrained_edge[2] = ce;
|
||||||
|
@ -297,7 +290,7 @@ void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Triangle::SetConstrainedEdgeCW(Point& p, bool ce)
|
void Triangle::SetConstrainedEdgeCW(const Point& p, bool ce)
|
||||||
{
|
{
|
||||||
if (&p == points_[0]) {
|
if (&p == points_[0]) {
|
||||||
constrained_edge[1] = ce;
|
constrained_edge[1] = ce;
|
||||||
|
@ -308,7 +301,7 @@ void Triangle::SetConstrainedEdgeCW(Point& p, bool ce)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Triangle::GetDelunayEdgeCCW(Point& p)
|
bool Triangle::GetDelunayEdgeCCW(const Point& p)
|
||||||
{
|
{
|
||||||
if (&p == points_[0]) {
|
if (&p == points_[0]) {
|
||||||
return delaunay_edge[2];
|
return delaunay_edge[2];
|
||||||
|
@ -318,7 +311,7 @@ bool Triangle::GetDelunayEdgeCCW(Point& p)
|
||||||
return delaunay_edge[1];
|
return delaunay_edge[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Triangle::GetDelunayEdgeCW(Point& p)
|
bool Triangle::GetDelunayEdgeCW(const Point& p)
|
||||||
{
|
{
|
||||||
if (&p == points_[0]) {
|
if (&p == points_[0]) {
|
||||||
return delaunay_edge[1];
|
return delaunay_edge[1];
|
||||||
|
@ -328,7 +321,7 @@ bool Triangle::GetDelunayEdgeCW(Point& p)
|
||||||
return delaunay_edge[0];
|
return delaunay_edge[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
|
void Triangle::SetDelunayEdgeCCW(const Point& p, bool e)
|
||||||
{
|
{
|
||||||
if (&p == points_[0]) {
|
if (&p == points_[0]) {
|
||||||
delaunay_edge[2] = e;
|
delaunay_edge[2] = e;
|
||||||
|
@ -339,7 +332,7 @@ void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Triangle::SetDelunayEdgeCW(Point& p, bool e)
|
void Triangle::SetDelunayEdgeCW(const Point& p, bool e)
|
||||||
{
|
{
|
||||||
if (&p == points_[0]) {
|
if (&p == points_[0]) {
|
||||||
delaunay_edge[1] = e;
|
delaunay_edge[1] = e;
|
||||||
|
@ -351,7 +344,7 @@ void Triangle::SetDelunayEdgeCW(Point& p, bool e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The neighbor across to given point
|
// The neighbor across to given point
|
||||||
Triangle& Triangle::NeighborAcross(Point& opoint)
|
Triangle& Triangle::NeighborAcross(const Point& opoint)
|
||||||
{
|
{
|
||||||
if (&opoint == points_[0]) {
|
if (&opoint == points_[0]) {
|
||||||
return *neighbors_[0];
|
return *neighbors_[0];
|
||||||
|
@ -370,4 +363,3 @@ void Triangle::DebugPrint()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ struct Point {
|
||||||
/// Convert this point into a unit point. Returns the Length.
|
/// Convert this point into a unit point. Returns the Length.
|
||||||
double Normalize()
|
double Normalize()
|
||||||
{
|
{
|
||||||
double len = Length();
|
const double len = Length();
|
||||||
x /= len;
|
x /= len;
|
||||||
y /= len;
|
y /= len;
|
||||||
return len;
|
return len;
|
||||||
|
@ -162,50 +162,50 @@ bool constrained_edge[3];
|
||||||
/// Flags to determine if an edge is a Delauney edge
|
/// Flags to determine if an edge is a Delauney edge
|
||||||
bool delaunay_edge[3];
|
bool delaunay_edge[3];
|
||||||
|
|
||||||
Point* GetPoint(const int& index);
|
Point* GetPoint(int index);
|
||||||
Point* PointCW(Point& point);
|
Point* PointCW(const Point& point);
|
||||||
Point* PointCCW(Point& point);
|
Point* PointCCW(const Point& point);
|
||||||
Point* OppositePoint(Triangle& t, Point& p);
|
Point* OppositePoint(Triangle& t, const Point& p);
|
||||||
|
|
||||||
Triangle* GetNeighbor(const int& index);
|
Triangle* GetNeighbor(int index);
|
||||||
void MarkNeighbor(Point* p1, Point* p2, Triangle* t);
|
void MarkNeighbor(Point* p1, Point* p2, Triangle* t);
|
||||||
void MarkNeighbor(Triangle& t);
|
void MarkNeighbor(Triangle& t);
|
||||||
|
|
||||||
void MarkConstrainedEdge(const int index);
|
void MarkConstrainedEdge(int index);
|
||||||
void MarkConstrainedEdge(Edge& edge);
|
void MarkConstrainedEdge(Edge& edge);
|
||||||
void MarkConstrainedEdge(Point* p, Point* q);
|
void MarkConstrainedEdge(Point* p, Point* q);
|
||||||
|
|
||||||
int Index(const Point* p);
|
int Index(const Point* p);
|
||||||
int EdgeIndex(const Point* p1, const Point* p2);
|
int EdgeIndex(const Point* p1, const Point* p2);
|
||||||
|
|
||||||
Triangle* NeighborCW(Point& point);
|
Triangle* NeighborCW(const Point& point);
|
||||||
Triangle* NeighborCCW(Point& point);
|
Triangle* NeighborCCW(const Point& point);
|
||||||
bool GetConstrainedEdgeCCW(Point& p);
|
bool GetConstrainedEdgeCCW(const Point& p);
|
||||||
bool GetConstrainedEdgeCW(Point& p);
|
bool GetConstrainedEdgeCW(const Point& p);
|
||||||
void SetConstrainedEdgeCCW(Point& p, bool ce);
|
void SetConstrainedEdgeCCW(const Point& p, bool ce);
|
||||||
void SetConstrainedEdgeCW(Point& p, bool ce);
|
void SetConstrainedEdgeCW(const Point& p, bool ce);
|
||||||
bool GetDelunayEdgeCCW(Point& p);
|
bool GetDelunayEdgeCCW(const Point& p);
|
||||||
bool GetDelunayEdgeCW(Point& p);
|
bool GetDelunayEdgeCW(const Point& p);
|
||||||
void SetDelunayEdgeCCW(Point& p, bool e);
|
void SetDelunayEdgeCCW(const Point& p, bool e);
|
||||||
void SetDelunayEdgeCW(Point& p, bool e);
|
void SetDelunayEdgeCW(const Point& p, bool e);
|
||||||
|
|
||||||
bool Contains(Point* p);
|
bool Contains(const Point* p);
|
||||||
bool Contains(const Edge& e);
|
bool Contains(const Edge& e);
|
||||||
bool Contains(Point* p, Point* q);
|
bool Contains(const Point* p, const Point* q);
|
||||||
void Legalize(Point& point);
|
void Legalize(Point& point);
|
||||||
void Legalize(Point& opoint, Point& npoint);
|
void Legalize(Point& opoint, Point& npoint);
|
||||||
/**
|
/**
|
||||||
* Clears all references to all other triangles and points
|
* Clears all references to all other triangles and points
|
||||||
*/
|
*/
|
||||||
void Clear();
|
void Clear();
|
||||||
void ClearNeighbor(Triangle *triangle );
|
void ClearNeighbor(const Triangle *triangle);
|
||||||
void ClearNeighbors();
|
void ClearNeighbors();
|
||||||
void ClearDelunayEdges();
|
void ClearDelunayEdges();
|
||||||
|
|
||||||
inline bool IsInterior();
|
inline bool IsInterior();
|
||||||
inline void IsInterior(bool b);
|
inline void IsInterior(bool b);
|
||||||
|
|
||||||
Triangle& NeighborAcross(Point& opoint);
|
Triangle& NeighborAcross(const Point& opoint);
|
||||||
|
|
||||||
void DebugPrint();
|
void DebugPrint();
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ inline bool operator ==(const Point& a, const Point& b)
|
||||||
|
|
||||||
inline bool operator !=(const Point& a, const Point& b)
|
inline bool operator !=(const Point& a, const Point& b)
|
||||||
{
|
{
|
||||||
return a.x != b.x || a.y != b.y;
|
return !(a.x == b.x) && !(a.y == b.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Peform the dot product on two vectors.
|
/// Peform the dot product on two vectors.
|
||||||
|
@ -282,22 +282,22 @@ inline Point Cross(const Point& a, double s)
|
||||||
|
|
||||||
/// Perform the cross product on a scalar and a point. In 2D this produces
|
/// Perform the cross product on a scalar and a point. In 2D this produces
|
||||||
/// a point.
|
/// a point.
|
||||||
inline Point Cross(const double s, const Point& a)
|
inline Point Cross(double s, const Point& a)
|
||||||
{
|
{
|
||||||
return Point(-s * a.y, s * a.x);
|
return Point(-s * a.y, s * a.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Point* Triangle::GetPoint(const int& index)
|
inline Point* Triangle::GetPoint(int index)
|
||||||
{
|
{
|
||||||
return points_[index];
|
return points_[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Triangle* Triangle::GetNeighbor(const int& index)
|
inline Triangle* Triangle::GetNeighbor(int index)
|
||||||
{
|
{
|
||||||
return neighbors_[index];
|
return neighbors_[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Triangle::Contains(Point* p)
|
inline bool Triangle::Contains(const Point* p)
|
||||||
{
|
{
|
||||||
return p == points_[0] || p == points_[1] || p == points_[2];
|
return p == points_[0] || p == points_[1] || p == points_[2];
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ inline bool Triangle::Contains(const Edge& e)
|
||||||
return Contains(e.p) && Contains(e.q);
|
return Contains(e.p) && Contains(e.q);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Triangle::Contains(Point* p, Point* q)
|
inline bool Triangle::Contains(const Point* p, const Point* q)
|
||||||
{
|
{
|
||||||
return Contains(p) && Contains(q);
|
return Contains(p) && Contains(q);
|
||||||
}
|
}
|
||||||
|
@ -325,5 +325,3 @@ inline void Triangle::IsInterior(bool b)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,14 +32,22 @@
|
||||||
#ifndef UTILS_H
|
#ifndef UTILS_H
|
||||||
#define UTILS_H
|
#define UTILS_H
|
||||||
|
|
||||||
|
// Otherwise #defines like M_PI are undeclared under Visual Studio
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// C99 removes M_PI from math.h
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846264338327
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace p2t {
|
namespace p2t {
|
||||||
|
|
||||||
const double PI = 3.1415926535897932384626433832795029;
|
const double PI_3div4 = 3 * M_PI / 4;
|
||||||
const double PI_2 = 2 * PI;
|
const double PI_div2 = 1.57079632679489661923;
|
||||||
const double PI_3div4 = 3 * PI / 4;
|
const double EPSILON = 1e-12;
|
||||||
const double EPSILON = 1e-15;
|
|
||||||
|
|
||||||
enum Orientation { CW, CCW, COLLINEAR };
|
enum Orientation { CW, CCW, COLLINEAR };
|
||||||
|
|
||||||
|
@ -53,7 +61,7 @@ enum Orientation { CW, CCW, COLLINEAR };
|
||||||
* = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
|
* = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
Orientation Orient2d(Point& pa, Point& pb, Point& pc)
|
Orientation Orient2d(const Point& pa, const Point& pb, const Point& pc)
|
||||||
{
|
{
|
||||||
double detleft = (pa.x - pc.x) * (pb.y - pc.y);
|
double detleft = (pa.x - pc.x) * (pb.y - pc.y);
|
||||||
double detright = (pa.y - pc.y) * (pb.x - pc.x);
|
double detright = (pa.y - pc.y) * (pb.x - pc.x);
|
||||||
|
@ -66,6 +74,7 @@ Orientation Orient2d(Point& pa, Point& pb, Point& pc)
|
||||||
return CW;
|
return CW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
|
bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
|
||||||
{
|
{
|
||||||
double pdx = pd.x;
|
double pdx = pd.x;
|
||||||
|
@ -97,7 +106,22 @@ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool InScanArea(const Point& pa, const Point& pb, const Point& pc, const Point& pd)
|
||||||
|
{
|
||||||
|
double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y);
|
||||||
|
if (oadb >= -EPSILON) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y);
|
||||||
|
if (oadc <= EPSILON) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -36,4 +36,3 @@
|
||||||
#include "sweep/cdt.h"
|
#include "sweep/cdt.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ AdvancingFront::AdvancingFront(Node& head, Node& tail)
|
||||||
search_node_ = &head;
|
search_node_ = &head;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* AdvancingFront::LocateNode(const double& x)
|
Node* AdvancingFront::LocateNode(double x)
|
||||||
{
|
{
|
||||||
Node* node = search_node_;
|
Node* node = search_node_;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ Node* AdvancingFront::LocateNode(const double& x)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* AdvancingFront::FindSearchNode(const double& x)
|
Node* AdvancingFront::FindSearchNode(double x)
|
||||||
{
|
{
|
||||||
(void)x; // suppress compiler warnings "unused parameter 'x'"
|
(void)x; // suppress compiler warnings "unused parameter 'x'"
|
||||||
// TODO: implement BST index
|
// TODO: implement BST index
|
||||||
|
@ -106,4 +106,3 @@ AdvancingFront::~AdvancingFront()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ Node* search();
|
||||||
void set_search(Node* node);
|
void set_search(Node* node);
|
||||||
|
|
||||||
/// Locate insertion point along advancing front
|
/// Locate insertion point along advancing front
|
||||||
Node* LocateNode(const double& x);
|
Node* LocateNode(double x);
|
||||||
|
|
||||||
Node* LocatePoint(const Point* point);
|
Node* LocatePoint(const Point* point);
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ private:
|
||||||
|
|
||||||
Node* head_, *tail_, *search_node_;
|
Node* head_, *tail_, *search_node_;
|
||||||
|
|
||||||
Node* FindSearchNode(const double& x);
|
Node* FindSearchNode(double x);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Node* AdvancingFront::head()
|
inline Node* AdvancingFront::head()
|
||||||
|
|
|
@ -32,13 +32,13 @@
|
||||||
|
|
||||||
namespace p2t {
|
namespace p2t {
|
||||||
|
|
||||||
CDT::CDT(std::vector<Point*> polyline)
|
CDT::CDT(const std::vector<Point*>& polyline)
|
||||||
{
|
{
|
||||||
sweep_context_ = new SweepContext(polyline);
|
sweep_context_ = new SweepContext(polyline);
|
||||||
sweep_ = new Sweep;
|
sweep_ = new Sweep;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDT::AddHole(std::vector<Point*> polyline)
|
void CDT::AddHole(const std::vector<Point*>& polyline)
|
||||||
{
|
{
|
||||||
sweep_context_->AddHole(polyline);
|
sweep_context_->AddHole(polyline);
|
||||||
}
|
}
|
||||||
|
@ -69,4 +69,3 @@ CDT::~CDT()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ public:
|
||||||
*
|
*
|
||||||
* @param polyline
|
* @param polyline
|
||||||
*/
|
*/
|
||||||
CDT(std::vector<Point*> polyline);
|
CDT(const std::vector<Point*>& polyline);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor - clean up memory
|
* Destructor - clean up memory
|
||||||
|
@ -65,7 +65,7 @@ public:
|
||||||
*
|
*
|
||||||
* @param polyline
|
* @param polyline
|
||||||
*/
|
*/
|
||||||
void AddHole(std::vector<Point*> polyline);
|
void AddHole(const std::vector<Point*>& polyline);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a steiner point
|
* Add a steiner point
|
||||||
|
|
|
@ -49,7 +49,7 @@ void Sweep::Triangulate(SweepContext& tcx)
|
||||||
|
|
||||||
void Sweep::SweepPoints(SweepContext& tcx)
|
void Sweep::SweepPoints(SweepContext& tcx)
|
||||||
{
|
{
|
||||||
for (int i = 1; i < tcx.point_count(); i++) {
|
for (size_t i = 1; i < tcx.point_count(); i++) {
|
||||||
Point& point = *tcx.GetPoint(i);
|
Point& point = *tcx.GetPoint(i);
|
||||||
Node* node = &PointEvent(tcx, point);
|
Node* node = &PointEvent(tcx, point);
|
||||||
for (unsigned int i = 0; i < point.edge_list.size(); i++) {
|
for (unsigned int i = 0; i < point.edge_list.size(); i++) {
|
||||||
|
@ -166,7 +166,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
|
||||||
|
|
||||||
bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq)
|
bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq)
|
||||||
{
|
{
|
||||||
int index = triangle.EdgeIndex(&ep, &eq);
|
const int index = triangle.EdgeIndex(&ep, &eq);
|
||||||
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
triangle.MarkConstrainedEdge(index);
|
triangle.MarkConstrainedEdge(index);
|
||||||
|
@ -230,8 +230,8 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
|
||||||
Node* node = n.next;
|
Node* node = n.next;
|
||||||
|
|
||||||
while (node->next) {
|
while (node->next) {
|
||||||
double angle = HoleAngle(*node);
|
// if HoleAngle exceeds 90 degrees then break.
|
||||||
if (angle > PI_2 || angle < -PI_2) break;
|
if (LargeHole_DontFill(node)) break;
|
||||||
Fill(tcx, *node);
|
Fill(tcx, *node);
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
|
@ -240,29 +240,81 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
|
||||||
node = n.prev;
|
node = n.prev;
|
||||||
|
|
||||||
while (node->prev) {
|
while (node->prev) {
|
||||||
double angle = HoleAngle(*node);
|
// if HoleAngle exceeds 90 degrees then break.
|
||||||
if (angle > PI_2 || angle < -PI_2) break;
|
if (LargeHole_DontFill(node)) break;
|
||||||
Fill(tcx, *node);
|
Fill(tcx, *node);
|
||||||
node = node->prev;
|
node = node->prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill right basins
|
// Fill right basins
|
||||||
if (n.next && n.next->next) {
|
if (n.next && n.next->next) {
|
||||||
double angle = BasinAngle(n);
|
const double angle = BasinAngle(n);
|
||||||
if (angle < PI_3div4) {
|
if (angle < PI_3div4) {
|
||||||
FillBasin(tcx, n);
|
FillBasin(tcx, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double Sweep::BasinAngle(Node& node)
|
// True if HoleAngle exceeds 90 degrees.
|
||||||
|
bool Sweep::LargeHole_DontFill(const Node* node) const {
|
||||||
|
|
||||||
|
const Node* nextNode = node->next;
|
||||||
|
const Node* prevNode = node->prev;
|
||||||
|
if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check additional points on front.
|
||||||
|
const Node* next2Node = nextNode->next;
|
||||||
|
// "..Plus.." because only want angles on same side as point being added.
|
||||||
|
if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const Node* prev2Node = prevNode->prev;
|
||||||
|
// "..Plus.." because only want angles on same side as point being added.
|
||||||
|
if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sweep::AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const {
|
||||||
|
const double angle = Angle(origin, pa, pb);
|
||||||
|
return ((angle > PI_div2) || (angle < -PI_div2));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const {
|
||||||
|
const double angle = Angle(origin, pa, pb);
|
||||||
|
return (angle > PI_div2) || (angle < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Sweep::Angle(const Point* origin, const Point* pa, const Point* pb) const {
|
||||||
|
/* Complex plane
|
||||||
|
* ab = cosA +i*sinA
|
||||||
|
* ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
|
||||||
|
* atan2(y,x) computes the principal value of the argument function
|
||||||
|
* applied to the complex number x+iy
|
||||||
|
* Where x = ax*bx + ay*by
|
||||||
|
* y = ax*by - ay*bx
|
||||||
|
*/
|
||||||
|
const double px = origin->x;
|
||||||
|
const double py = origin->y;
|
||||||
|
const double ax = pa->x- px;
|
||||||
|
const double ay = pa->y - py;
|
||||||
|
const double bx = pb->x - px;
|
||||||
|
const double by = pb->y - py;
|
||||||
|
const double x = ax * by - ay * bx;
|
||||||
|
const double y = ax * bx + ay * by;
|
||||||
|
return atan2(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Sweep::BasinAngle(const Node& node) const
|
||||||
{
|
{
|
||||||
double ax = node.point->x - node.next->next->point->x;
|
const double ax = node.point->x - node.next->next->point->x;
|
||||||
double ay = node.point->y - node.next->next->point->y;
|
const double ay = node.point->y - node.next->next->point->y;
|
||||||
return atan2(ay, ax);
|
return atan2(ay, ax);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Sweep::HoleAngle(Node& node)
|
double Sweep::HoleAngle(const Node& node) const
|
||||||
{
|
{
|
||||||
/* Complex plane
|
/* Complex plane
|
||||||
* ab = cosA +i*sinA
|
* ab = cosA +i*sinA
|
||||||
|
@ -272,10 +324,10 @@ double Sweep::HoleAngle(Node& node)
|
||||||
* Where x = ax*bx + ay*by
|
* Where x = ax*bx + ay*by
|
||||||
* y = ax*by - ay*bx
|
* y = ax*by - ay*bx
|
||||||
*/
|
*/
|
||||||
double ax = node.next->point->x - node.point->x;
|
const double ax = node.next->point->x - node.point->x;
|
||||||
double ay = node.next->point->y - node.point->y;
|
const double ay = node.next->point->y - node.point->y;
|
||||||
double bx = node.prev->point->x - node.point->x;
|
const double bx = node.prev->point->x - node.point->x;
|
||||||
double by = node.prev->point->y - node.point->y;
|
const double by = node.prev->point->y - node.point->y;
|
||||||
return atan2(ax * by - ay * bx, ax * bx + ay * by);
|
return atan2(ax * by - ay * bx, ax * bx + ay * by);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,43 +392,43 @@ bool Sweep::Legalize(SweepContext& tcx, Triangle& t)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd)
|
bool Sweep::Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const
|
||||||
{
|
{
|
||||||
double adx = pa.x - pd.x;
|
const double adx = pa.x - pd.x;
|
||||||
double ady = pa.y - pd.y;
|
const double ady = pa.y - pd.y;
|
||||||
double bdx = pb.x - pd.x;
|
const double bdx = pb.x - pd.x;
|
||||||
double bdy = pb.y - pd.y;
|
const double bdy = pb.y - pd.y;
|
||||||
|
|
||||||
double adxbdy = adx * bdy;
|
const double adxbdy = adx * bdy;
|
||||||
double bdxady = bdx * ady;
|
const double bdxady = bdx * ady;
|
||||||
double oabd = adxbdy - bdxady;
|
const double oabd = adxbdy - bdxady;
|
||||||
|
|
||||||
if (oabd <= 0)
|
if (oabd <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
double cdx = pc.x - pd.x;
|
const double cdx = pc.x - pd.x;
|
||||||
double cdy = pc.y - pd.y;
|
const double cdy = pc.y - pd.y;
|
||||||
|
|
||||||
double cdxady = cdx * ady;
|
const double cdxady = cdx * ady;
|
||||||
double adxcdy = adx * cdy;
|
const double adxcdy = adx * cdy;
|
||||||
double ocad = cdxady - adxcdy;
|
const double ocad = cdxady - adxcdy;
|
||||||
|
|
||||||
if (ocad <= 0)
|
if (ocad <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
double bdxcdy = bdx * cdy;
|
const double bdxcdy = bdx * cdy;
|
||||||
double cdxbdy = cdx * bdy;
|
const double cdxbdy = cdx * bdy;
|
||||||
|
|
||||||
double alift = adx * adx + ady * ady;
|
const double alift = adx * adx + ady * ady;
|
||||||
double blift = bdx * bdx + bdy * bdy;
|
const double blift = bdx * bdx + bdy * bdy;
|
||||||
double clift = cdx * cdx + cdy * cdy;
|
const double clift = cdx * cdx + cdy * cdy;
|
||||||
|
|
||||||
double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
|
const double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
|
||||||
|
|
||||||
return det > 0;
|
return det > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op)
|
void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const
|
||||||
{
|
{
|
||||||
Triangle* n1, *n2, *n3, *n4;
|
Triangle* n1, *n2, *n3, *n4;
|
||||||
n1 = t.NeighborCCW(p);
|
n1 = t.NeighborCCW(p);
|
||||||
|
@ -708,11 +760,8 @@ Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
|
||||||
} else if (o2d == CCW) {
|
} else if (o2d == CCW) {
|
||||||
// Left
|
// Left
|
||||||
return *ot.PointCW(op);
|
return *ot.PointCW(op);
|
||||||
} else{
|
|
||||||
//throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
|
|
||||||
// ASSIMP_CHANGE (aramis_acg)
|
|
||||||
throw std::runtime_error("[Unsupported] Opposing point on constrained edge");
|
|
||||||
}
|
}
|
||||||
|
throw std::runtime_error("[Unsupported] Opposing point on constrained edge");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
|
void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
|
||||||
|
@ -740,7 +789,7 @@ void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle&
|
||||||
Sweep::~Sweep() {
|
Sweep::~Sweep() {
|
||||||
|
|
||||||
// Clean up memory
|
// Clean up memory
|
||||||
for(unsigned int i = 0; i < nodes_.size(); i++) {
|
for(size_t i = 0; i < nodes_.size(); i++) {
|
||||||
delete nodes_[i];
|
delete nodes_[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
* Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
|
* Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
|
||||||
* International Journal of Geographical Information Science
|
* International Journal of Geographical Information Science
|
||||||
*
|
*
|
||||||
* "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com
|
* "FlipScan" Constrained Edge Algorithm invented by Thomas ?hl?n, thahlen@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SWEEP_H
|
#ifndef SWEEP_H
|
||||||
|
@ -142,7 +142,7 @@ private:
|
||||||
* @param d - point opposite a
|
* @param d - point opposite a
|
||||||
* @return true if d is inside circle, false if on circle edge
|
* @return true if d is inside circle, false if on circle edge
|
||||||
*/
|
*/
|
||||||
bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd);
|
bool Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotates a triangle pair one vertex CW
|
* Rotates a triangle pair one vertex CW
|
||||||
|
@ -158,7 +158,7 @@ private:
|
||||||
* n4 n4
|
* n4 n4
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op);
|
void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills holes in the Advancing Front
|
* Fills holes in the Advancing Front
|
||||||
|
@ -169,17 +169,24 @@ private:
|
||||||
*/
|
*/
|
||||||
void FillAdvancingFront(SweepContext& tcx, Node& n);
|
void FillAdvancingFront(SweepContext& tcx, Node& n);
|
||||||
|
|
||||||
|
// Decision-making about when to Fill hole.
|
||||||
|
// Contributed by ToolmakerSteve2
|
||||||
|
bool LargeHole_DontFill(const Node* node) const;
|
||||||
|
bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const;
|
||||||
|
bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const;
|
||||||
|
double Angle(const Point* origin, const Point* pa, const Point* pb) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param node - middle node
|
* @param node - middle node
|
||||||
* @return the angle between 3 front nodes
|
* @return the angle between 3 front nodes
|
||||||
*/
|
*/
|
||||||
double HoleAngle(Node& node);
|
double HoleAngle(const Node& node) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The basin angle is decided against the horizontal line [1,0]
|
* The basin angle is decided against the horizontal line [1,0]
|
||||||
*/
|
*/
|
||||||
double BasinAngle(Node& node);
|
double BasinAngle(const Node& node) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills a basin that has formed on the Advancing Front to the right
|
* Fills a basin that has formed on the Advancing Front to the right
|
||||||
|
|
|
@ -34,17 +34,18 @@
|
||||||
|
|
||||||
namespace p2t {
|
namespace p2t {
|
||||||
|
|
||||||
SweepContext::SweepContext(std::vector<Point*> polyline)
|
SweepContext::SweepContext(const std::vector<Point*>& polyline) : points_(polyline),
|
||||||
|
front_(0),
|
||||||
|
head_(0),
|
||||||
|
tail_(0),
|
||||||
|
af_head_(0),
|
||||||
|
af_middle_(0),
|
||||||
|
af_tail_(0)
|
||||||
{
|
{
|
||||||
basin = Basin();
|
|
||||||
edge_event = EdgeEvent();
|
|
||||||
|
|
||||||
points_ = polyline;
|
|
||||||
|
|
||||||
InitEdges(points_);
|
InitEdges(points_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SweepContext::AddHole(std::vector<Point*> polyline)
|
void SweepContext::AddHole(const std::vector<Point*>& polyline)
|
||||||
{
|
{
|
||||||
InitEdges(polyline);
|
InitEdges(polyline);
|
||||||
for(unsigned int i = 0; i < polyline.size(); i++) {
|
for(unsigned int i = 0; i < polyline.size(); i++) {
|
||||||
|
@ -56,12 +57,12 @@ void SweepContext::AddPoint(Point* point) {
|
||||||
points_.push_back(point);
|
points_.push_back(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Triangle*> SweepContext::GetTriangles()
|
std::vector<Triangle*> &SweepContext::GetTriangles()
|
||||||
{
|
{
|
||||||
return triangles_;
|
return triangles_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<Triangle*> SweepContext::GetMap()
|
std::list<Triangle*> &SweepContext::GetMap()
|
||||||
{
|
{
|
||||||
return map_;
|
return map_;
|
||||||
}
|
}
|
||||||
|
@ -94,16 +95,16 @@ void SweepContext::InitTriangulation()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SweepContext::InitEdges(std::vector<Point*> polyline)
|
void SweepContext::InitEdges(const std::vector<Point*>& polyline)
|
||||||
{
|
{
|
||||||
int num_points = static_cast<int>(polyline.size());
|
size_t num_points = polyline.size();
|
||||||
for (int i = 0; i < num_points; i++) {
|
for (size_t i = 0; i < num_points; i++) {
|
||||||
int j = i < num_points - 1 ? i + 1 : 0;
|
size_t j = i < num_points - 1 ? i + 1 : 0;
|
||||||
edge_list.push_back(new Edge(*polyline[i], *polyline[j]));
|
edge_list.push_back(new Edge(*polyline[i], *polyline[j]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Point* SweepContext::GetPoint(const int& index)
|
Point* SweepContext::GetPoint(size_t index)
|
||||||
{
|
{
|
||||||
return points_[index];
|
return points_[index];
|
||||||
}
|
}
|
||||||
|
@ -113,13 +114,13 @@ void SweepContext::AddToMap(Triangle* triangle)
|
||||||
map_.push_back(triangle);
|
map_.push_back(triangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node& SweepContext::LocateNode(Point& point)
|
Node& SweepContext::LocateNode(const Point& point)
|
||||||
{
|
{
|
||||||
// TODO implement search tree
|
// TODO implement search tree
|
||||||
return *front_->LocateNode(point.x);
|
return *front_->LocateNode(point.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SweepContext::CreateAdvancingFront(std::vector<Node*> nodes)
|
void SweepContext::CreateAdvancingFront(const std::vector<Node*>& nodes)
|
||||||
{
|
{
|
||||||
|
|
||||||
(void) nodes;
|
(void) nodes;
|
||||||
|
@ -164,12 +165,20 @@ void SweepContext::RemoveFromMap(Triangle* triangle)
|
||||||
|
|
||||||
void SweepContext::MeshClean(Triangle& triangle)
|
void SweepContext::MeshClean(Triangle& triangle)
|
||||||
{
|
{
|
||||||
if (!triangle.IsInterior()) {
|
std::vector<Triangle *> triangles;
|
||||||
triangle.IsInterior(true);
|
triangles.push_back(&triangle);
|
||||||
triangles_.push_back(&triangle);
|
|
||||||
for (int i = 0; i < 3; i++) {
|
while(!triangles.empty()){
|
||||||
if (!triangle.constrained_edge[i])
|
Triangle *t = triangles.back();
|
||||||
MeshClean(*triangle.GetNeighbor(i));
|
triangles.pop_back();
|
||||||
|
|
||||||
|
if (t != NULL && !t->IsInterior()) {
|
||||||
|
t->IsInterior(true);
|
||||||
|
triangles_.push_back(t);
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
if (!t->constrained_edge[i])
|
||||||
|
triangles.push_back(t->GetNeighbor(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,47 +52,47 @@ class SweepContext {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
SweepContext(std::vector<Point*> polyline);
|
SweepContext(const std::vector<Point*>& polyline);
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~SweepContext();
|
~SweepContext();
|
||||||
|
|
||||||
void set_head(Point* p1);
|
void set_head(Point* p1);
|
||||||
|
|
||||||
Point* head();
|
Point* head() const;
|
||||||
|
|
||||||
void set_tail(Point* p1);
|
void set_tail(Point* p1);
|
||||||
|
|
||||||
Point* tail();
|
Point* tail() const;
|
||||||
|
|
||||||
int point_count();
|
size_t point_count() const;
|
||||||
|
|
||||||
Node& LocateNode(Point& point);
|
Node& LocateNode(const Point& point);
|
||||||
|
|
||||||
void RemoveNode(Node* node);
|
void RemoveNode(Node* node);
|
||||||
|
|
||||||
void CreateAdvancingFront(std::vector<Node*> nodes);
|
void CreateAdvancingFront(const std::vector<Node*>& nodes);
|
||||||
|
|
||||||
/// Try to map a node to all sides of this triangle that don't have a neighbor
|
/// Try to map a node to all sides of this triangle that don't have a neighbor
|
||||||
void MapTriangleToNodes(Triangle& t);
|
void MapTriangleToNodes(Triangle& t);
|
||||||
|
|
||||||
void AddToMap(Triangle* triangle);
|
void AddToMap(Triangle* triangle);
|
||||||
|
|
||||||
Point* GetPoint(const int& index);
|
Point* GetPoint(size_t index);
|
||||||
|
|
||||||
Point* GetPoints();
|
Point* GetPoints();
|
||||||
|
|
||||||
void RemoveFromMap(Triangle* triangle);
|
void RemoveFromMap(Triangle* triangle);
|
||||||
|
|
||||||
void AddHole(std::vector<Point*> polyline);
|
void AddHole(const std::vector<Point*>& polyline);
|
||||||
|
|
||||||
void AddPoint(Point* point);
|
void AddPoint(Point* point);
|
||||||
|
|
||||||
AdvancingFront* front();
|
AdvancingFront* front() const;
|
||||||
|
|
||||||
void MeshClean(Triangle& triangle);
|
void MeshClean(Triangle& triangle);
|
||||||
|
|
||||||
std::vector<Triangle*> GetTriangles();
|
std::vector<Triangle*> &GetTriangles();
|
||||||
std::list<Triangle*> GetMap();
|
std::list<Triangle*> &GetMap();
|
||||||
|
|
||||||
std::vector<Edge*> edge_list;
|
std::vector<Edge*> edge_list;
|
||||||
|
|
||||||
|
@ -147,18 +147,18 @@ Point* tail_;
|
||||||
Node *af_head_, *af_middle_, *af_tail_;
|
Node *af_head_, *af_middle_, *af_tail_;
|
||||||
|
|
||||||
void InitTriangulation();
|
void InitTriangulation();
|
||||||
void InitEdges(std::vector<Point*> polyline);
|
void InitEdges(const std::vector<Point*>& polyline);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline AdvancingFront* SweepContext::front()
|
inline AdvancingFront* SweepContext::front() const
|
||||||
{
|
{
|
||||||
return front_;
|
return front_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int SweepContext::point_count()
|
inline size_t SweepContext::point_count() const
|
||||||
{
|
{
|
||||||
return static_cast<int>(points_.size());
|
return points_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SweepContext::set_head(Point* p1)
|
inline void SweepContext::set_head(Point* p1)
|
||||||
|
@ -166,7 +166,7 @@ inline void SweepContext::set_head(Point* p1)
|
||||||
head_ = p1;
|
head_ = p1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Point* SweepContext::head()
|
inline Point* SweepContext::head() const
|
||||||
{
|
{
|
||||||
return head_;
|
return head_;
|
||||||
}
|
}
|
||||||
|
@ -176,7 +176,7 @@ inline void SweepContext::set_tail(Point* p1)
|
||||||
tail_ = p1;
|
tail_ = p1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Point* SweepContext::tail()
|
inline Point* SweepContext::tail() const
|
||||||
{
|
{
|
||||||
return tail_;
|
return tail_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,6 @@ AI_FORCE_INLINE const aiColor4t<TReal>& aiColor4t<TReal>::operator /= (TReal f)
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
template <typename TReal>
|
template <typename TReal>
|
||||||
AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
|
AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
|
||||||
//return *(&r + i);
|
|
||||||
switch ( i ) {
|
switch ( i ) {
|
||||||
case 0:
|
case 0:
|
||||||
return r;
|
return r;
|
||||||
|
@ -93,7 +92,6 @@ AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
template <typename TReal>
|
template <typename TReal>
|
||||||
AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
|
AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
|
||||||
// return *(&r + i);
|
|
||||||
switch ( i ) {
|
switch ( i ) {
|
||||||
case 0:
|
case 0:
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -224,7 +224,7 @@ public:
|
||||||
* @return Reference to the output matrix
|
* @return Reference to the output matrix
|
||||||
*/
|
*/
|
||||||
static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis,
|
static aiMatrix4x4t& Rotation(TReal a, const aiVector3t<TReal>& axis,
|
||||||
aiMatrix4x4t& out);
|
aiMatrix4x4t& out);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** @brief Returns a translation matrix
|
/** @brief Returns a translation matrix
|
||||||
|
@ -232,7 +232,8 @@ public:
|
||||||
* @param out Receives the output matrix
|
* @param out Receives the output matrix
|
||||||
* @return Reference to the output matrix
|
* @return Reference to the output matrix
|
||||||
*/
|
*/
|
||||||
static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v, aiMatrix4x4t& out);
|
static aiMatrix4x4t& Translation( const aiVector3t<TReal>& v,
|
||||||
|
aiMatrix4x4t& out);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** @brief Returns a scaling matrix
|
/** @brief Returns a scaling matrix
|
||||||
|
@ -252,7 +253,7 @@ public:
|
||||||
* Journal of Graphics Tools, 4(4):1-4, 1999
|
* Journal of Graphics Tools, 4(4):1-4, 1999
|
||||||
*/
|
*/
|
||||||
static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from,
|
static aiMatrix4x4t& FromToMatrix(const aiVector3t<TReal>& from,
|
||||||
const aiVector3t<TReal>& to, aiMatrix4x4t& out);
|
const aiVector3t<TReal>& to, aiMatrix4x4t& out);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TReal a1, a2, a3, a4;
|
TReal a1, a2, a3, a4;
|
||||||
|
|
|
@ -8,7 +8,6 @@ import os
|
||||||
import ctypes
|
import ctypes
|
||||||
from ctypes import POINTER
|
from ctypes import POINTER
|
||||||
import operator
|
import operator
|
||||||
import sys
|
|
||||||
|
|
||||||
try: import numpy
|
try: import numpy
|
||||||
except: numpy = None
|
except: numpy = None
|
||||||
|
@ -41,8 +40,6 @@ elif os.name=='nt':
|
||||||
if 'assimp' in dir_candidate.lower():
|
if 'assimp' in dir_candidate.lower():
|
||||||
additional_dirs.append(dir_candidate)
|
additional_dirs.append(dir_candidate)
|
||||||
|
|
||||||
additional_dirs += sys.path
|
|
||||||
|
|
||||||
#print(additional_dirs)
|
#print(additional_dirs)
|
||||||
def vec2tuple(x):
|
def vec2tuple(x):
|
||||||
""" Converts a VECTOR3D to a Tuple """
|
""" Converts a VECTOR3D to a Tuple """
|
||||||
|
|
|
@ -9,7 +9,5 @@ setup(name='pyassimp',
|
||||||
url='https://github.com/assimp/assimp',
|
url='https://github.com/assimp/assimp',
|
||||||
packages=['pyassimp'],
|
packages=['pyassimp'],
|
||||||
data_files=[('share/pyassimp', ['README.md']),
|
data_files=[('share/pyassimp', ['README.md']),
|
||||||
('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')]),
|
('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')])], requires=['numpy']
|
||||||
('lib/', [f for f in os.listdir('../../lib') if os.path.isfile(f)])],
|
|
||||||
requires=['numpy']
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|

|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.26228.9
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTexturedDirectx11", "SimpleTexturedDirectx11\SimpleTexturedDirectx11.vcxproj", "{E3B160B5-E71F-4F3F-9310-B8F156F736D8}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.Build.0 = Release|x64
|
||||||
|
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,102 @@
|
||||||
|
#ifndef MESH_H
|
||||||
|
#define MESH_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <d3d11_1.h>
|
||||||
|
#include <DirectXMath.h>
|
||||||
|
using namespace DirectX;
|
||||||
|
|
||||||
|
struct VERTEX {
|
||||||
|
FLOAT X, Y, Z;
|
||||||
|
XMFLOAT2 texcoord;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Texture {
|
||||||
|
string type;
|
||||||
|
string path;
|
||||||
|
ID3D11ShaderResourceView *texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Mesh {
|
||||||
|
public:
|
||||||
|
vector<VERTEX> vertices;
|
||||||
|
vector<UINT> indices;
|
||||||
|
vector<Texture> textures;
|
||||||
|
ID3D11Device *dev;
|
||||||
|
|
||||||
|
Mesh(ID3D11Device *dev, vector<VERTEX> vertices, vector<UINT> indices, vector<Texture> textures)
|
||||||
|
{
|
||||||
|
this->vertices = vertices;
|
||||||
|
this->indices = indices;
|
||||||
|
this->textures = textures;
|
||||||
|
|
||||||
|
this->dev = dev;
|
||||||
|
|
||||||
|
this->setupMesh(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(ID3D11DeviceContext *devcon)
|
||||||
|
{
|
||||||
|
UINT stride = sizeof(VERTEX);
|
||||||
|
UINT offset = 0;
|
||||||
|
|
||||||
|
devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
|
||||||
|
devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
|
||||||
|
|
||||||
|
devcon->PSSetShaderResources(0, 1, &textures[0].texture);
|
||||||
|
|
||||||
|
devcon->DrawIndexed(indices.size(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Close()
|
||||||
|
{
|
||||||
|
VertexBuffer->Release();
|
||||||
|
IndexBuffer->Release();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
/* Render data */
|
||||||
|
ID3D11Buffer *VertexBuffer, *IndexBuffer;
|
||||||
|
|
||||||
|
/* Functions */
|
||||||
|
// Initializes all the buffer objects/arrays
|
||||||
|
bool setupMesh(ID3D11Device *dev)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
D3D11_BUFFER_DESC vbd;
|
||||||
|
vbd.Usage = D3D11_USAGE_IMMUTABLE;
|
||||||
|
vbd.ByteWidth = sizeof(VERTEX) * vertices.size();
|
||||||
|
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||||
|
vbd.CPUAccessFlags = 0;
|
||||||
|
vbd.MiscFlags = 0;
|
||||||
|
|
||||||
|
D3D11_SUBRESOURCE_DATA initData;
|
||||||
|
initData.pSysMem = &vertices[0];
|
||||||
|
|
||||||
|
hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
D3D11_BUFFER_DESC ibd;
|
||||||
|
ibd.Usage = D3D11_USAGE_IMMUTABLE;
|
||||||
|
ibd.ByteWidth = sizeof(UINT) * indices.size();
|
||||||
|
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||||
|
ibd.CPUAccessFlags = 0;
|
||||||
|
ibd.MiscFlags = 0;
|
||||||
|
|
||||||
|
initData.pSysMem = &indices[0];
|
||||||
|
|
||||||
|
hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,205 @@
|
||||||
|
#include "ModelLoader.h"
|
||||||
|
|
||||||
|
ModelLoader::ModelLoader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModelLoader::~ModelLoader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename)
|
||||||
|
{
|
||||||
|
Assimp::Importer importer;
|
||||||
|
|
||||||
|
const aiScene* pScene = importer.ReadFile(filename,
|
||||||
|
aiProcess_Triangulate |
|
||||||
|
aiProcess_ConvertToLeftHanded);
|
||||||
|
|
||||||
|
if (pScene == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this->directory = filename.substr(0, filename.find_last_of('/'));
|
||||||
|
|
||||||
|
this->dev = dev;
|
||||||
|
this->hwnd = hwnd;
|
||||||
|
|
||||||
|
processNode(pScene->mRootNode, pScene);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModelLoader::Draw(ID3D11DeviceContext * devcon)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < meshes.size(); i++)
|
||||||
|
{
|
||||||
|
meshes[i].Draw(devcon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string textype;
|
||||||
|
|
||||||
|
Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene)
|
||||||
|
{
|
||||||
|
// Data to fill
|
||||||
|
vector<VERTEX> vertices;
|
||||||
|
vector<UINT> indices;
|
||||||
|
vector<Texture> textures;
|
||||||
|
|
||||||
|
if (mesh->mMaterialIndex >= 0)
|
||||||
|
{
|
||||||
|
aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
|
||||||
|
|
||||||
|
if (textype.empty()) textype = determineTextureType(scene, mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk through each of the mesh's vertices
|
||||||
|
for (UINT i = 0; i < mesh->mNumVertices; i++)
|
||||||
|
{
|
||||||
|
VERTEX vertex;
|
||||||
|
|
||||||
|
vertex.X = mesh->mVertices[i].x;
|
||||||
|
vertex.Y = mesh->mVertices[i].y;
|
||||||
|
vertex.Z = mesh->mVertices[i].z;
|
||||||
|
|
||||||
|
if (mesh->mTextureCoords[0])
|
||||||
|
{
|
||||||
|
vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x;
|
||||||
|
vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertices.push_back(vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UINT i = 0; i < mesh->mNumFaces; i++)
|
||||||
|
{
|
||||||
|
aiFace face = mesh->mFaces[i];
|
||||||
|
|
||||||
|
for (UINT j = 0; j < face.mNumIndices; j++)
|
||||||
|
indices.push_back(face.mIndices[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh->mMaterialIndex >= 0)
|
||||||
|
{
|
||||||
|
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
||||||
|
|
||||||
|
vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene);
|
||||||
|
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Mesh(dev, vertices, indices, textures);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene)
|
||||||
|
{
|
||||||
|
vector<Texture> textures;
|
||||||
|
for (UINT i = 0; i < mat->GetTextureCount(type); i++)
|
||||||
|
{
|
||||||
|
aiString str;
|
||||||
|
mat->GetTexture(type, i, &str);
|
||||||
|
// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
|
||||||
|
bool skip = false;
|
||||||
|
for (UINT j = 0; j < textures_loaded.size(); j++)
|
||||||
|
{
|
||||||
|
if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0)
|
||||||
|
{
|
||||||
|
textures.push_back(textures_loaded[j]);
|
||||||
|
skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!skip)
|
||||||
|
{ // If texture hasn't been loaded already, load it
|
||||||
|
HRESULT hr;
|
||||||
|
Texture texture;
|
||||||
|
if (textype == "embedded compressed texture")
|
||||||
|
{
|
||||||
|
int textureindex = getTextureIndex(&str);
|
||||||
|
texture.texture = getTextureFromModel(scene, textureindex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string filename = string(str.C_Str());
|
||||||
|
filename = directory + '/' + filename;
|
||||||
|
wstring filenamews = wstring(filename.begin(), filename.end());
|
||||||
|
hr = CreateWICTextureFromFile(dev, devcon, filenamews.c_str(), nullptr, &texture.texture);
|
||||||
|
if (FAILED(hr))
|
||||||
|
MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
|
||||||
|
}
|
||||||
|
texture.type = typeName;
|
||||||
|
texture.path = str.C_Str();
|
||||||
|
textures.push_back(texture);
|
||||||
|
this->textures_loaded.push_back(texture); // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return textures;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModelLoader::Close()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < meshes.size(); i++)
|
||||||
|
{
|
||||||
|
meshes[i].Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModelLoader::processNode(aiNode * node, const aiScene * scene)
|
||||||
|
{
|
||||||
|
for (UINT i = 0; i < node->mNumMeshes; i++)
|
||||||
|
{
|
||||||
|
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||||
|
meshes.push_back(this->processMesh(mesh, scene));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UINT i = 0; i < node->mNumChildren; i++)
|
||||||
|
{
|
||||||
|
this->processNode(node->mChildren[i], scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat)
|
||||||
|
{
|
||||||
|
aiString textypeStr;
|
||||||
|
mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
|
||||||
|
string textypeteststr = textypeStr.C_Str();
|
||||||
|
if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5")
|
||||||
|
{
|
||||||
|
if (scene->mTextures[0]->mHeight == 0)
|
||||||
|
{
|
||||||
|
return "embedded compressed texture";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "embedded non-compressed texture";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (textypeteststr.find('.') != string::npos)
|
||||||
|
{
|
||||||
|
return "textures are on disk";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModelLoader::getTextureIndex(aiString * str)
|
||||||
|
{
|
||||||
|
string tistr;
|
||||||
|
tistr = str->C_Str();
|
||||||
|
tistr = tistr.substr(1);
|
||||||
|
return stoi(tistr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
ID3D11ShaderResourceView *texture;
|
||||||
|
|
||||||
|
int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth);
|
||||||
|
|
||||||
|
hr = CreateWICTextureFromMemory(dev, devcon, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture);
|
||||||
|
if (FAILED(hr))
|
||||||
|
MessageBox(hwnd, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef MODEL_LOADER_H
|
||||||
|
#define MODEL_LOADER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <d3d11_1.h>
|
||||||
|
#include <DirectXMath.h>
|
||||||
|
|
||||||
|
#include <assimp\Importer.hpp>
|
||||||
|
#include <assimp\scene.h>
|
||||||
|
#include <assimp\postprocess.h>
|
||||||
|
|
||||||
|
#include "Mesh.h"
|
||||||
|
#include "TextureLoader.h"
|
||||||
|
|
||||||
|
using namespace DirectX;
|
||||||
|
|
||||||
|
class ModelLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ModelLoader();
|
||||||
|
~ModelLoader();
|
||||||
|
|
||||||
|
bool Load(HWND hwnd, ID3D11Device* dev, ID3D11DeviceContext* devcon, std::string filename);
|
||||||
|
void Draw(ID3D11DeviceContext* devcon);
|
||||||
|
|
||||||
|
void Close();
|
||||||
|
private:
|
||||||
|
ID3D11Device *dev;
|
||||||
|
ID3D11DeviceContext *devcon;
|
||||||
|
std::vector<Mesh> meshes;
|
||||||
|
string directory;
|
||||||
|
vector<Texture> textures_loaded;
|
||||||
|
HWND hwnd;
|
||||||
|
|
||||||
|
void processNode(aiNode* node, const aiScene* scene);
|
||||||
|
Mesh processMesh(aiMesh* mesh, const aiScene* scene);
|
||||||
|
vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName, const aiScene* scene);
|
||||||
|
string determineTextureType(const aiScene* scene, aiMaterial* mat);
|
||||||
|
int getTextureIndex(aiString* str);
|
||||||
|
ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !MODEL_LOADER_H
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
Texture2D diffTexture;
|
||||||
|
SamplerState SampleType;
|
||||||
|
|
||||||
|
float4 main(float4 pos : SV_POSITION, float2 texcoord : TEXCOORD) : SV_TARGET
|
||||||
|
{
|
||||||
|
float4 textureColor = diffTexture.Sample(SampleType, texcoord);
|
||||||
|
|
||||||
|
return textureColor;
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{E3B160B5-E71F-4F3F-9310-B8F156F736D8}</ProjectGuid>
|
||||||
|
<RootNamespace>SimpleTexturedDirectx11</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<IncludePath>$(IncludePath);E:\OpenGL VS Files\include</IncludePath>
|
||||||
|
<LibraryPath>$(LibraryPath);E:\OpenGL VS Files\lib</LibraryPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>assimp-vc140-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="main.cpp" />
|
||||||
|
<ClCompile Include="ModelLoader.cpp" />
|
||||||
|
<ClCompile Include="TextureLoader.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<FxCompile Include="PixelShader.hlsl">
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Pixel</ShaderType>
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Pixel</ShaderType>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="VertexShader.hlsl">
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType>
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Vertex</ShaderType>
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
|
||||||
|
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Vertex</ShaderType>
|
||||||
|
</FxCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Mesh.h" />
|
||||||
|
<ClInclude Include="ModelLoader.h" />
|
||||||
|
<ClInclude Include="TextureLoader.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Shaders">
|
||||||
|
<UniqueIdentifier>{b6a86d3e-70a5-4d1e-ba05-c20902300206}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="ModelLoader.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="TextureLoader.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<FxCompile Include="VertexShader.hlsl">
|
||||||
|
<Filter>Shaders</Filter>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="PixelShader.hlsl">
|
||||||
|
<Filter>Shaders</Filter>
|
||||||
|
</FxCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="ModelLoader.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Mesh.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="TextureLoader.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,691 @@
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
// File: WICTextureLoader.cpp
|
||||||
|
//
|
||||||
|
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
|
||||||
|
// (auto-generating mipmaps if possible)
|
||||||
|
//
|
||||||
|
// Note: Assumes application has already called CoInitializeEx
|
||||||
|
//
|
||||||
|
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
|
||||||
|
// auto-gen mipmap support.
|
||||||
|
//
|
||||||
|
// Note these functions are useful for images created as simple 2D textures. For
|
||||||
|
// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
|
||||||
|
// For a full-featured DDS file reader, writer, and texture processing pipeline see
|
||||||
|
// the 'Texconv' sample and the 'DirectXTex' library.
|
||||||
|
//
|
||||||
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||||
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||||
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||||
|
// PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
//
|
||||||
|
// http://go.microsoft.com/fwlink/?LinkId=248926
|
||||||
|
// http://go.microsoft.com/fwlink/?LinkId=248929
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// We could load multi-frame images (TIFF/GIF) into a texture array.
|
||||||
|
// For now, we just load the first frame (note: DirectXTex supports multi-frame images)
|
||||||
|
|
||||||
|
#include <dxgiformat.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4005)
|
||||||
|
#include <wincodec.h>
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "TextureLoader.h"
|
||||||
|
|
||||||
|
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(DXGI_1_2_FORMATS)
|
||||||
|
#define DXGI_1_2_FORMATS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
template<class T> class ScopedObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ScopedObject(T *p = 0) : _pointer(p) {}
|
||||||
|
~ScopedObject()
|
||||||
|
{
|
||||||
|
if (_pointer)
|
||||||
|
{
|
||||||
|
_pointer->Release();
|
||||||
|
_pointer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNull() const { return (!_pointer); }
|
||||||
|
|
||||||
|
T& operator*() { return *_pointer; }
|
||||||
|
T* operator->() { return _pointer; }
|
||||||
|
T** operator&() { return &_pointer; }
|
||||||
|
|
||||||
|
void Reset(T *p = 0) { if (_pointer) { _pointer->Release(); } _pointer = p; }
|
||||||
|
|
||||||
|
T* Get() const { return _pointer; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ScopedObject(const ScopedObject&);
|
||||||
|
ScopedObject& operator=(const ScopedObject&);
|
||||||
|
|
||||||
|
T* _pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
// WIC Pixel Format Translation Data
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
struct WICTranslate
|
||||||
|
{
|
||||||
|
GUID wic;
|
||||||
|
DXGI_FORMAT format;
|
||||||
|
};
|
||||||
|
|
||||||
|
static WICTranslate g_WICFormats[] =
|
||||||
|
{
|
||||||
|
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT },
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT },
|
||||||
|
{ GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM },
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM },
|
||||||
|
{ GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1
|
||||||
|
{ GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1
|
||||||
|
{ GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM },
|
||||||
|
{ GUID_WICPixelFormat32bppRGBE, DXGI_FORMAT_R9G9B9E5_SHAREDEXP },
|
||||||
|
|
||||||
|
#ifdef DXGI_1_2_FORMATS
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM },
|
||||||
|
{ GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM },
|
||||||
|
|
||||||
|
#endif // DXGI_1_2_FORMATS
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT },
|
||||||
|
{ GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT },
|
||||||
|
{ GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM },
|
||||||
|
{ GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM },
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM },
|
||||||
|
|
||||||
|
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
|
||||||
|
{ GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT },
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
// WIC Pixel Format nearest conversion table
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct WICConvert
|
||||||
|
{
|
||||||
|
GUID source;
|
||||||
|
GUID target;
|
||||||
|
};
|
||||||
|
|
||||||
|
static WICConvert g_WICConvert[] =
|
||||||
|
{
|
||||||
|
// Note target GUID in this conversion table must be one of those directly supported formats (above).
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||||
|
{ GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT
|
||||||
|
|
||||||
|
#ifdef DXGI_1_2_FORMATS
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat16bppBGRA5551, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat16bppBGR565, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
|
||||||
|
#endif // DXGI_1_2_FORMATS
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
{ GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat96bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||||
|
{ GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||||
|
{ GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||||
|
{ GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||||
|
{ GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
|
||||||
|
|
||||||
|
{ GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
|
||||||
|
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
|
||||||
|
{ GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
|
||||||
|
{ GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// We don't support n-channel formats
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
static IWICImagingFactory* _GetWIC()
|
||||||
|
{
|
||||||
|
static IWICImagingFactory* s_Factory = nullptr;
|
||||||
|
|
||||||
|
if (s_Factory)
|
||||||
|
return s_Factory;
|
||||||
|
|
||||||
|
HRESULT hr = CoCreateInstance(
|
||||||
|
CLSID_WICImagingFactory,
|
||||||
|
nullptr,
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
__uuidof(IWICImagingFactory),
|
||||||
|
(LPVOID*)&s_Factory
|
||||||
|
);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
s_Factory = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_Factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static DXGI_FORMAT _WICToDXGI(const GUID& guid)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < _countof(g_WICFormats); ++i)
|
||||||
|
{
|
||||||
|
if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0)
|
||||||
|
return g_WICFormats[i].format;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DXGI_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static size_t _WICBitsPerPixel(REFGUID targetGuid)
|
||||||
|
{
|
||||||
|
IWICImagingFactory* pWIC = _GetWIC();
|
||||||
|
if (!pWIC)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ScopedObject<IWICComponentInfo> cinfo;
|
||||||
|
if (FAILED(pWIC->CreateComponentInfo(targetGuid, &cinfo)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
WICComponentType type;
|
||||||
|
if (FAILED(cinfo->GetComponentType(&type)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (type != WICPixelFormat)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ScopedObject<IWICPixelFormatInfo> pfinfo;
|
||||||
|
if (FAILED(cinfo->QueryInterface(__uuidof(IWICPixelFormatInfo), reinterpret_cast<void**>(&pfinfo))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
UINT bpp;
|
||||||
|
if (FAILED(pfinfo->GetBitsPerPixel(&bpp)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return bpp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static HRESULT CreateTextureFromWIC(_In_ ID3D11Device* d3dDevice,
|
||||||
|
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||||
|
_In_ IWICBitmapFrameDecode *frame,
|
||||||
|
_Out_opt_ ID3D11Resource** texture,
|
||||||
|
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||||
|
_In_ size_t maxsize)
|
||||||
|
{
|
||||||
|
UINT width, height;
|
||||||
|
HRESULT hr = frame->GetSize(&width, &height);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
assert(width > 0 && height > 0);
|
||||||
|
|
||||||
|
if (!maxsize)
|
||||||
|
{
|
||||||
|
// This is a bit conservative because the hardware could support larger textures than
|
||||||
|
// the Feature Level defined minimums, but doing it this way is much easier and more
|
||||||
|
// performant for WIC than the 'fail and retry' model used by DDSTextureLoader
|
||||||
|
|
||||||
|
switch (d3dDevice->GetFeatureLevel())
|
||||||
|
{
|
||||||
|
case D3D_FEATURE_LEVEL_9_1:
|
||||||
|
case D3D_FEATURE_LEVEL_9_2:
|
||||||
|
maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D3D_FEATURE_LEVEL_9_3:
|
||||||
|
maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case D3D_FEATURE_LEVEL_10_0:
|
||||||
|
case D3D_FEATURE_LEVEL_10_1:
|
||||||
|
maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(maxsize > 0);
|
||||||
|
|
||||||
|
UINT twidth, theight;
|
||||||
|
if (width > maxsize || height > maxsize)
|
||||||
|
{
|
||||||
|
float ar = static_cast<float>(height) / static_cast<float>(width);
|
||||||
|
if (width > height)
|
||||||
|
{
|
||||||
|
twidth = static_cast<UINT>(maxsize);
|
||||||
|
theight = static_cast<UINT>(static_cast<float>(maxsize) * ar);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
theight = static_cast<UINT>(maxsize);
|
||||||
|
twidth = static_cast<UINT>(static_cast<float>(maxsize) / ar);
|
||||||
|
}
|
||||||
|
assert(twidth <= maxsize && theight <= maxsize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
twidth = width;
|
||||||
|
theight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine format
|
||||||
|
WICPixelFormatGUID pixelFormat;
|
||||||
|
hr = frame->GetPixelFormat(&pixelFormat);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
WICPixelFormatGUID convertGUID;
|
||||||
|
memcpy(&convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID));
|
||||||
|
|
||||||
|
size_t bpp = 0;
|
||||||
|
|
||||||
|
DXGI_FORMAT format = _WICToDXGI(pixelFormat);
|
||||||
|
if (format == DXGI_FORMAT_UNKNOWN)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < _countof(g_WICConvert); ++i)
|
||||||
|
{
|
||||||
|
if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0)
|
||||||
|
{
|
||||||
|
memcpy(&convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID));
|
||||||
|
|
||||||
|
format = _WICToDXGI(g_WICConvert[i].target);
|
||||||
|
assert(format != DXGI_FORMAT_UNKNOWN);
|
||||||
|
bpp = _WICBitsPerPixel(convertGUID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format == DXGI_FORMAT_UNKNOWN)
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bpp = _WICBitsPerPixel(pixelFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bpp)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
// Verify our target format is supported by the current device
|
||||||
|
// (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support)
|
||||||
|
UINT support = 0;
|
||||||
|
hr = d3dDevice->CheckFormatSupport(format, &support);
|
||||||
|
if (FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D))
|
||||||
|
{
|
||||||
|
// Fallback to RGBA 32-bit format which is supported by all devices
|
||||||
|
memcpy(&convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID));
|
||||||
|
format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
bpp = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate temporary memory for image
|
||||||
|
size_t rowPitch = (twidth * bpp + 7) / 8;
|
||||||
|
size_t imageSize = rowPitch * theight;
|
||||||
|
|
||||||
|
std::unique_ptr<uint8_t[]> temp(new uint8_t[imageSize]);
|
||||||
|
|
||||||
|
// Load image data
|
||||||
|
if (memcmp(&convertGUID, &pixelFormat, sizeof(GUID)) == 0
|
||||||
|
&& twidth == width
|
||||||
|
&& theight == height)
|
||||||
|
{
|
||||||
|
// No format conversion or resize needed
|
||||||
|
hr = frame->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
else if (twidth != width || theight != height)
|
||||||
|
{
|
||||||
|
// Resize
|
||||||
|
IWICImagingFactory* pWIC = _GetWIC();
|
||||||
|
if (!pWIC)
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
|
ScopedObject<IWICBitmapScaler> scaler;
|
||||||
|
hr = pWIC->CreateBitmapScaler(&scaler);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = scaler->Initialize(frame, twidth, theight, WICBitmapInterpolationModeFant);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
WICPixelFormatGUID pfScaler;
|
||||||
|
hr = scaler->GetPixelFormat(&pfScaler);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (memcmp(&convertGUID, &pfScaler, sizeof(GUID)) == 0)
|
||||||
|
{
|
||||||
|
// No format conversion needed
|
||||||
|
hr = scaler->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScopedObject<IWICFormatConverter> FC;
|
||||||
|
hr = pWIC->CreateFormatConverter(&FC);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = FC->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Format conversion but no resize
|
||||||
|
IWICImagingFactory* pWIC = _GetWIC();
|
||||||
|
if (!pWIC)
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
|
ScopedObject<IWICFormatConverter> FC;
|
||||||
|
hr = pWIC->CreateFormatConverter(&FC);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = FC->CopyPixels(0, static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize), temp.get());
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if format is supported for auto-gen mipmaps (varies by feature level)
|
||||||
|
bool autogen = false;
|
||||||
|
if (d3dContext != 0 && textureView != 0) // Must have context and shader-view to auto generate mipmaps
|
||||||
|
{
|
||||||
|
UINT fmtSupport = 0;
|
||||||
|
hr = d3dDevice->CheckFormatSupport(format, &fmtSupport);
|
||||||
|
if (SUCCEEDED(hr) && (fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN))
|
||||||
|
{
|
||||||
|
autogen = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create texture
|
||||||
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
|
desc.Width = twidth;
|
||||||
|
desc.Height = theight;
|
||||||
|
desc.MipLevels = (autogen) ? 0 : 1;
|
||||||
|
desc.ArraySize = 1;
|
||||||
|
desc.Format = format;
|
||||||
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.SampleDesc.Quality = 0;
|
||||||
|
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
desc.BindFlags = (autogen) ? (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) : (D3D11_BIND_SHADER_RESOURCE);
|
||||||
|
desc.CPUAccessFlags = 0;
|
||||||
|
desc.MiscFlags = (autogen) ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0;
|
||||||
|
|
||||||
|
D3D11_SUBRESOURCE_DATA initData;
|
||||||
|
initData.pSysMem = temp.get();
|
||||||
|
initData.SysMemPitch = static_cast<UINT>(rowPitch);
|
||||||
|
initData.SysMemSlicePitch = static_cast<UINT>(imageSize);
|
||||||
|
|
||||||
|
ID3D11Texture2D* tex = nullptr;
|
||||||
|
hr = d3dDevice->CreateTexture2D(&desc, (autogen) ? nullptr : &initData, &tex);
|
||||||
|
if (SUCCEEDED(hr) && tex != 0)
|
||||||
|
{
|
||||||
|
if (textureView != 0)
|
||||||
|
{
|
||||||
|
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
|
||||||
|
memset(&SRVDesc, 0, sizeof(SRVDesc));
|
||||||
|
SRVDesc.Format = format;
|
||||||
|
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1;
|
||||||
|
|
||||||
|
hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
tex->Release();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autogen)
|
||||||
|
{
|
||||||
|
assert(d3dContext != 0);
|
||||||
|
d3dContext->UpdateSubresource(tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize));
|
||||||
|
d3dContext->GenerateMips(*textureView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture != 0)
|
||||||
|
{
|
||||||
|
*texture = tex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(_DEBUG) || defined(PROFILE)
|
||||||
|
tex->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||||
|
sizeof("WICTextureLoader") - 1,
|
||||||
|
"WICTextureLoader"
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
tex->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice,
|
||||||
|
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||||
|
_In_bytecount_(wicDataSize) const uint8_t* wicData,
|
||||||
|
_In_ size_t wicDataSize,
|
||||||
|
_Out_opt_ ID3D11Resource** texture,
|
||||||
|
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||||
|
_In_ size_t maxsize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!d3dDevice || !wicData || (!texture && !textureView))
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wicDataSize)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _M_AMD64
|
||||||
|
if (wicDataSize > 0xFFFFFFFF)
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IWICImagingFactory* pWIC = _GetWIC();
|
||||||
|
if (!pWIC)
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
|
// Create input stream for memory
|
||||||
|
ScopedObject<IWICStream> stream;
|
||||||
|
HRESULT hr = pWIC->CreateStream(&stream);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = stream->InitializeFromMemory(const_cast<uint8_t*>(wicData), static_cast<DWORD>(wicDataSize));
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
// Initialize WIC
|
||||||
|
ScopedObject<IWICBitmapDecoder> decoder;
|
||||||
|
hr = pWIC->CreateDecoderFromStream(stream.Get(), 0, WICDecodeMetadataCacheOnDemand, &decoder);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
ScopedObject<IWICBitmapFrameDecode> frame;
|
||||||
|
hr = decoder->GetFrame(0, &frame);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
#if defined(_DEBUG) || defined(PROFILE)
|
||||||
|
if (texture != 0 && *texture != 0)
|
||||||
|
{
|
||||||
|
(*texture)->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||||
|
sizeof("WICTextureLoader") - 1,
|
||||||
|
"WICTextureLoader"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textureView != 0 && *textureView != 0)
|
||||||
|
{
|
||||||
|
(*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||||
|
sizeof("WICTextureLoader") - 1,
|
||||||
|
"WICTextureLoader"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice,
|
||||||
|
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||||
|
_In_z_ const wchar_t* fileName,
|
||||||
|
_Out_opt_ ID3D11Resource** texture,
|
||||||
|
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||||
|
_In_ size_t maxsize)
|
||||||
|
{
|
||||||
|
if (!d3dDevice || !fileName || (!texture && !textureView))
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
IWICImagingFactory* pWIC = _GetWIC();
|
||||||
|
if (!pWIC)
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
|
// Initialize WIC
|
||||||
|
ScopedObject<IWICBitmapDecoder> decoder;
|
||||||
|
HRESULT hr = pWIC->CreateDecoderFromFilename(fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
ScopedObject<IWICBitmapFrameDecode> frame;
|
||||||
|
hr = decoder->GetFrame(0, &frame);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
#if defined(_DEBUG) || defined(PROFILE)
|
||||||
|
if (texture != 0 || textureView != 0)
|
||||||
|
{
|
||||||
|
CHAR strFileA[MAX_PATH];
|
||||||
|
WideCharToMultiByte(CP_ACP,
|
||||||
|
WC_NO_BEST_FIT_CHARS,
|
||||||
|
fileName,
|
||||||
|
-1,
|
||||||
|
strFileA,
|
||||||
|
MAX_PATH,
|
||||||
|
nullptr,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
const CHAR* pstrName = strrchr(strFileA, '\\');
|
||||||
|
if (!pstrName)
|
||||||
|
{
|
||||||
|
pstrName = strFileA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pstrName++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture != 0 && *texture != 0)
|
||||||
|
{
|
||||||
|
(*texture)->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||||
|
static_cast<UINT>(strnlen_s(pstrName, MAX_PATH)),
|
||||||
|
pstrName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textureView != 0 && *textureView != 0)
|
||||||
|
{
|
||||||
|
(*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName,
|
||||||
|
static_cast<UINT>(strnlen_s(pstrName, MAX_PATH)),
|
||||||
|
pstrName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
// File: WICTextureLoader.h
|
||||||
|
//
|
||||||
|
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
|
||||||
|
// (auto-generating mipmaps if possible)
|
||||||
|
//
|
||||||
|
// Note: Assumes application has already called CoInitializeEx
|
||||||
|
//
|
||||||
|
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
|
||||||
|
// auto-gen mipmap support.
|
||||||
|
//
|
||||||
|
// Note these functions are useful for images created as simple 2D textures. For
|
||||||
|
// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
|
||||||
|
// For a full-featured DDS file reader, writer, and texture processing pipeline see
|
||||||
|
// the 'Texconv' sample and the 'DirectXTex' library.
|
||||||
|
//
|
||||||
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||||
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||||
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||||
|
// PARTICULAR PURPOSE.
|
||||||
|
//
|
||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
//
|
||||||
|
// http://go.microsoft.com/fwlink/?LinkId=248926
|
||||||
|
// http://go.microsoft.com/fwlink/?LinkId=248929
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <d3d11.h>
|
||||||
|
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4005)
|
||||||
|
#include <stdint.h>
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice,
|
||||||
|
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||||
|
_In_bytecount_(wicDataSize) const uint8_t* wicData,
|
||||||
|
_In_ size_t wicDataSize,
|
||||||
|
_Out_opt_ ID3D11Resource** texture,
|
||||||
|
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||||
|
_In_ size_t maxsize = 0
|
||||||
|
);
|
||||||
|
|
||||||
|
HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice,
|
||||||
|
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||||
|
_In_z_ const wchar_t* szFileName,
|
||||||
|
_Out_opt_ ID3D11Resource** texture,
|
||||||
|
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||||
|
_In_ size_t maxsize = 0
|
||||||
|
);
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
cbuffer ConstantBuffer : register(b0)
|
||||||
|
{
|
||||||
|
matrix World;
|
||||||
|
matrix View;
|
||||||
|
matrix Projection;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VOut {
|
||||||
|
float4 pos : SV_POSITION;
|
||||||
|
float2 texcoord : TEXCOORD;
|
||||||
|
};
|
||||||
|
|
||||||
|
VOut main(float4 pos : POSITION, float2 texcoord : TEXCOORD)
|
||||||
|
{
|
||||||
|
VOut output;
|
||||||
|
|
||||||
|
output.pos = mul(pos, World);
|
||||||
|
output.pos = mul(output.pos, View);
|
||||||
|
output.pos = mul(output.pos, Projection);
|
||||||
|
output.texcoord = texcoord;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
|
@ -0,0 +1,518 @@
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Simple Assimp Directx11 Sample
|
||||||
|
// This is a very basic sample and only reads diffuse texture
|
||||||
|
// but this can load both embedded textures in fbx and non-embedded textures
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Replace ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx") this with your
|
||||||
|
// model name (line 480)
|
||||||
|
// If your model isn't a fbx with embedded textures make sure your model's
|
||||||
|
// textures are in same directory as your model
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Written by IAS. :)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <windowsx.h>
|
||||||
|
#include <d3d11_1.h>
|
||||||
|
#include <dxgi1_2.h>
|
||||||
|
#include <DirectXMath.h>
|
||||||
|
#include <d3dcompiler.h>
|
||||||
|
#include "ModelLoader.h"
|
||||||
|
|
||||||
|
#pragma comment (lib, "d3d11.lib")
|
||||||
|
#pragma comment (lib, "Dxgi.lib")
|
||||||
|
#pragma comment(lib,"d3dcompiler.lib")
|
||||||
|
#pragma comment (lib, "dxguid.lib")
|
||||||
|
|
||||||
|
using namespace DirectX;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Structs
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
struct ConstantBuffer {
|
||||||
|
XMMATRIX mWorld;
|
||||||
|
XMMATRIX mView;
|
||||||
|
XMMATRIX mProjection;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Window Variables
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
#define SCREEN_WIDTH 800
|
||||||
|
#define SCREEN_HEIGHT 600
|
||||||
|
|
||||||
|
const char g_szClassName[] = "directxWindowClass";
|
||||||
|
|
||||||
|
|
||||||
|
UINT width, height;
|
||||||
|
HWND hwnd;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// DirectX Variables
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
|
||||||
|
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||||
|
ID3D11Device *dev;
|
||||||
|
ID3D11Device1 *dev1;
|
||||||
|
ID3D11DeviceContext *devcon;
|
||||||
|
ID3D11DeviceContext1 *devcon1;
|
||||||
|
IDXGISwapChain *swapchain;
|
||||||
|
IDXGISwapChain1 *swapchain1;
|
||||||
|
ID3D11RenderTargetView *backbuffer;
|
||||||
|
ID3D11VertexShader *pVS;
|
||||||
|
ID3D11PixelShader *pPS;
|
||||||
|
ID3D11InputLayout *pLayout;
|
||||||
|
ID3D11Buffer *pConstantBuffer;
|
||||||
|
ID3D11Texture2D *g_pDepthStencil;
|
||||||
|
ID3D11DepthStencilView *g_pDepthStencilView;
|
||||||
|
ID3D11SamplerState *TexSamplerState;
|
||||||
|
|
||||||
|
XMMATRIX m_World;
|
||||||
|
XMMATRIX m_View;
|
||||||
|
XMMATRIX m_Projection;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Function identifiers
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
void InitD3D(HINSTANCE hinstance, HWND hWnd);
|
||||||
|
void CleanD3D(void);
|
||||||
|
void RenderFrame(void);
|
||||||
|
|
||||||
|
void InitPipeline();
|
||||||
|
void InitGraphics();
|
||||||
|
|
||||||
|
HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob);
|
||||||
|
void Throwanerror(LPCSTR errormessage);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Our Model
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
ModelLoader *ourModel;
|
||||||
|
|
||||||
|
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_CLOSE:
|
||||||
|
DestroyWindow(hwnd);
|
||||||
|
break;
|
||||||
|
case WM_DESTROY:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
|
LPSTR lpCmdLine, int nCmdShow)
|
||||||
|
{
|
||||||
|
WNDCLASSEX wc;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
wc.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wc.style = 0;
|
||||||
|
wc.lpfnWndProc = WndProc;
|
||||||
|
wc.cbClsExtra = 0;
|
||||||
|
wc.cbWndExtra = 0;
|
||||||
|
wc.hInstance = hInstance;
|
||||||
|
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
wc.hbrBackground = NULL;
|
||||||
|
wc.lpszMenuName = NULL;
|
||||||
|
wc.lpszClassName = g_szClassName;
|
||||||
|
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
|
||||||
|
if (!RegisterClassEx(&wc))
|
||||||
|
{
|
||||||
|
MessageBox(NULL, "Window Registration Failed!", "Error!",
|
||||||
|
MB_ICONEXCLAMATION | MB_OK);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RECT wr = { 0,0, SCREEN_WIDTH, SCREEN_HEIGHT };
|
||||||
|
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
|
||||||
|
|
||||||
|
hwnd = CreateWindowEx(
|
||||||
|
WS_EX_CLIENTEDGE,
|
||||||
|
g_szClassName,
|
||||||
|
" Simple Textured Directx11 Sample ",
|
||||||
|
WS_OVERLAPPEDWINDOW,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top,
|
||||||
|
NULL, NULL, hInstance, NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hwnd == NULL)
|
||||||
|
{
|
||||||
|
MessageBox(NULL, "Window Creation Failed!", "Error!",
|
||||||
|
MB_ICONEXCLAMATION | MB_OK);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowWindow(hwnd, nCmdShow);
|
||||||
|
UpdateWindow(hwnd);
|
||||||
|
|
||||||
|
width = wr.right - wr.left;
|
||||||
|
height = wr.bottom - wr.top;
|
||||||
|
|
||||||
|
InitD3D(hInstance, hwnd);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
|
||||||
|
if (msg.message == WM_QUIT)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
CleanD3D();
|
||||||
|
|
||||||
|
return msg.wParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitD3D(HINSTANCE hinstance, HWND hWnd)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
UINT createDeviceFlags = 0;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
D3D_DRIVER_TYPE driverTypes[] =
|
||||||
|
{
|
||||||
|
D3D_DRIVER_TYPE_HARDWARE,
|
||||||
|
D3D_DRIVER_TYPE_WARP,
|
||||||
|
D3D_DRIVER_TYPE_REFERENCE,
|
||||||
|
};
|
||||||
|
UINT numDriverTypes = ARRAYSIZE(driverTypes);
|
||||||
|
|
||||||
|
D3D_FEATURE_LEVEL featureLevels[] =
|
||||||
|
{
|
||||||
|
D3D_FEATURE_LEVEL_11_1,
|
||||||
|
D3D_FEATURE_LEVEL_11_0,
|
||||||
|
D3D_FEATURE_LEVEL_10_1,
|
||||||
|
D3D_FEATURE_LEVEL_10_0,
|
||||||
|
};
|
||||||
|
UINT numFeatureLevels = ARRAYSIZE(featureLevels);
|
||||||
|
|
||||||
|
for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
|
||||||
|
{
|
||||||
|
g_driverType = driverTypes[driverTypeIndex];
|
||||||
|
hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
|
||||||
|
D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon);
|
||||||
|
|
||||||
|
if (hr == E_INVALIDARG)
|
||||||
|
{
|
||||||
|
// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
|
||||||
|
hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1,
|
||||||
|
D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (FAILED(hr))
|
||||||
|
Throwanerror("Directx Device Creation Failed!");
|
||||||
|
|
||||||
|
UINT m4xMsaaQuality;
|
||||||
|
dev->CheckMultisampleQualityLevels(
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
|
||||||
|
|
||||||
|
|
||||||
|
// Obtain DXGI factory from device (since we used nullptr for pAdapter above)
|
||||||
|
IDXGIFactory1* dxgiFactory = nullptr;
|
||||||
|
{
|
||||||
|
IDXGIDevice* dxgiDevice = nullptr;
|
||||||
|
hr = dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
IDXGIAdapter* adapter = nullptr;
|
||||||
|
hr = dxgiDevice->GetAdapter(&adapter);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory));
|
||||||
|
adapter->Release();
|
||||||
|
}
|
||||||
|
dxgiDevice->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FAILED(hr))
|
||||||
|
Throwanerror("DXGI Factory couldn't be obtained!");
|
||||||
|
|
||||||
|
// Create swap chain
|
||||||
|
IDXGIFactory2* dxgiFactory2 = nullptr;
|
||||||
|
hr = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
|
||||||
|
if (dxgiFactory2)
|
||||||
|
{
|
||||||
|
// DirectX 11.1 or later
|
||||||
|
hr = dev->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void**>(&dev1));
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
(void)devcon->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&devcon1));
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_SWAP_CHAIN_DESC1 sd;
|
||||||
|
ZeroMemory(&sd, sizeof(sd));
|
||||||
|
sd.Width = SCREEN_WIDTH;
|
||||||
|
sd.Height = SCREEN_HEIGHT;
|
||||||
|
sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
sd.SampleDesc.Count = 4;
|
||||||
|
sd.SampleDesc.Quality = m4xMsaaQuality - 1;
|
||||||
|
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
sd.BufferCount = 1;
|
||||||
|
|
||||||
|
hr = dxgiFactory2->CreateSwapChainForHwnd(dev, hWnd, &sd, nullptr, nullptr, &swapchain1);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = swapchain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&swapchain));
|
||||||
|
}
|
||||||
|
|
||||||
|
dxgiFactory2->Release();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// DirectX 11.0 systems
|
||||||
|
DXGI_SWAP_CHAIN_DESC sd;
|
||||||
|
ZeroMemory(&sd, sizeof(sd));
|
||||||
|
sd.BufferCount = 1;
|
||||||
|
sd.BufferDesc.Width = SCREEN_WIDTH;
|
||||||
|
sd.BufferDesc.Height = SCREEN_HEIGHT;
|
||||||
|
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
sd.BufferDesc.RefreshRate.Numerator = 60;
|
||||||
|
sd.BufferDesc.RefreshRate.Denominator = 1;
|
||||||
|
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
sd.OutputWindow = hWnd;
|
||||||
|
sd.SampleDesc.Count = 1;
|
||||||
|
sd.SampleDesc.Quality = m4xMsaaQuality - 1;
|
||||||
|
sd.Windowed = TRUE;
|
||||||
|
|
||||||
|
hr = dxgiFactory->CreateSwapChain(dev, &sd, &swapchain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut
|
||||||
|
dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
|
||||||
|
|
||||||
|
dxgiFactory->Release();
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
Throwanerror("Swapchain Creation Failed!");
|
||||||
|
|
||||||
|
ID3D11Texture2D *pBackBuffer;
|
||||||
|
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
|
||||||
|
|
||||||
|
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
|
||||||
|
pBackBuffer->Release();
|
||||||
|
|
||||||
|
D3D11_TEXTURE2D_DESC descDepth;
|
||||||
|
ZeroMemory(&descDepth, sizeof(descDepth));
|
||||||
|
descDepth.Width = SCREEN_WIDTH;
|
||||||
|
descDepth.Height = SCREEN_HEIGHT;
|
||||||
|
descDepth.MipLevels = 1;
|
||||||
|
descDepth.ArraySize = 1;
|
||||||
|
descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
descDepth.SampleDesc.Count = 4;
|
||||||
|
descDepth.SampleDesc.Quality = m4xMsaaQuality - 1;
|
||||||
|
descDepth.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
|
||||||
|
descDepth.CPUAccessFlags = 0;
|
||||||
|
descDepth.MiscFlags = 0;
|
||||||
|
hr = dev->CreateTexture2D(&descDepth, nullptr, &g_pDepthStencil);
|
||||||
|
if (FAILED(hr))
|
||||||
|
Throwanerror("Depth Stencil Texture couldn't be created!");
|
||||||
|
|
||||||
|
// Create the depth stencil view
|
||||||
|
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
|
||||||
|
ZeroMemory(&descDSV, sizeof(descDSV));
|
||||||
|
descDSV.Format = descDepth.Format;
|
||||||
|
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||||
|
descDSV.Texture2D.MipSlice = 0;
|
||||||
|
hr = dev->CreateDepthStencilView(g_pDepthStencil, 0, &g_pDepthStencilView);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
Throwanerror("Depth Stencil View couldn't be created!");
|
||||||
|
}
|
||||||
|
|
||||||
|
devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
|
||||||
|
|
||||||
|
D3D11_RASTERIZER_DESC rasterDesc;
|
||||||
|
ID3D11RasterizerState *rasterState;
|
||||||
|
rasterDesc.AntialiasedLineEnable = false;
|
||||||
|
rasterDesc.CullMode = D3D11_CULL_BACK;
|
||||||
|
rasterDesc.DepthBias = 0;
|
||||||
|
rasterDesc.DepthBiasClamp = 0.0f;
|
||||||
|
rasterDesc.DepthClipEnable = true;
|
||||||
|
rasterDesc.FillMode = D3D11_FILL_SOLID;
|
||||||
|
rasterDesc.FrontCounterClockwise = false;
|
||||||
|
rasterDesc.MultisampleEnable = false;
|
||||||
|
rasterDesc.ScissorEnable = false;
|
||||||
|
rasterDesc.SlopeScaledDepthBias = 0.0f;
|
||||||
|
|
||||||
|
dev->CreateRasterizerState(&rasterDesc, &rasterState);
|
||||||
|
devcon->RSSetState(rasterState);
|
||||||
|
|
||||||
|
D3D11_VIEWPORT viewport;
|
||||||
|
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
|
||||||
|
|
||||||
|
viewport.TopLeftX = 0;
|
||||||
|
viewport.TopLeftY = 0;
|
||||||
|
viewport.MinDepth = 0.0f;
|
||||||
|
viewport.MaxDepth = 1.0f;
|
||||||
|
viewport.Width = SCREEN_WIDTH;
|
||||||
|
viewport.Height = SCREEN_HEIGHT;
|
||||||
|
|
||||||
|
devcon->RSSetViewports(1, &viewport);
|
||||||
|
|
||||||
|
InitPipeline();
|
||||||
|
InitGraphics();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanD3D(void)
|
||||||
|
{
|
||||||
|
swapchain->SetFullscreenState(FALSE, NULL);
|
||||||
|
|
||||||
|
ourModel->Close();
|
||||||
|
g_pDepthStencil->Release();
|
||||||
|
g_pDepthStencilView->Release();
|
||||||
|
pLayout->Release();
|
||||||
|
pVS->Release();
|
||||||
|
pPS->Release();
|
||||||
|
pConstantBuffer->Release();
|
||||||
|
swapchain->Release();
|
||||||
|
backbuffer->Release();
|
||||||
|
dev->Release();
|
||||||
|
devcon->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderFrame(void)
|
||||||
|
{
|
||||||
|
static float t = 0.0f;
|
||||||
|
static ULONGLONG timeStart = 0;
|
||||||
|
ULONGLONG timeCur = GetTickCount64();
|
||||||
|
if (timeStart == 0)
|
||||||
|
timeStart = timeCur;
|
||||||
|
t = (timeCur - timeStart) / 1000.0f;
|
||||||
|
|
||||||
|
float clearColor[4] = { 0.0f, 0.2f, 0.4f, 1.0f };
|
||||||
|
devcon->ClearRenderTargetView(backbuffer, clearColor);
|
||||||
|
devcon->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
|
||||||
|
|
||||||
|
devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
|
|
||||||
|
m_World = XMMatrixRotationY(-t);
|
||||||
|
|
||||||
|
ConstantBuffer cb;
|
||||||
|
cb.mWorld = XMMatrixTranspose(m_World);
|
||||||
|
cb.mView = XMMatrixTranspose(m_View);
|
||||||
|
cb.mProjection = XMMatrixTranspose(m_Projection);
|
||||||
|
devcon->UpdateSubresource(pConstantBuffer, 0, nullptr, &cb, 0, 0);
|
||||||
|
|
||||||
|
devcon->VSSetShader(pVS, 0, 0);
|
||||||
|
devcon->VSSetConstantBuffers(0, 1, &pConstantBuffer);
|
||||||
|
devcon->PSSetShader(pPS, 0, 0);
|
||||||
|
devcon->PSSetSamplers(0, 1, &TexSamplerState);
|
||||||
|
ourModel->Draw(devcon);
|
||||||
|
|
||||||
|
swapchain->Present(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitPipeline()
|
||||||
|
{
|
||||||
|
ID3DBlob *VS, *PS;
|
||||||
|
CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS);
|
||||||
|
CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS);
|
||||||
|
|
||||||
|
dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
|
||||||
|
dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
|
||||||
|
|
||||||
|
D3D11_INPUT_ELEMENT_DESC ied[] =
|
||||||
|
{
|
||||||
|
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||||
|
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
|
||||||
|
devcon->IASetInputLayout(pLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitGraphics()
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
m_Projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.01f, 1000.0f);
|
||||||
|
|
||||||
|
D3D11_BUFFER_DESC bd;
|
||||||
|
ZeroMemory(&bd, sizeof(bd));
|
||||||
|
|
||||||
|
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
bd.ByteWidth = sizeof(ConstantBuffer);
|
||||||
|
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||||
|
bd.CPUAccessFlags = 0;
|
||||||
|
|
||||||
|
hr = dev->CreateBuffer(&bd, nullptr, &pConstantBuffer);
|
||||||
|
if (FAILED(hr))
|
||||||
|
Throwanerror("Constant buffer couldn't be created");
|
||||||
|
|
||||||
|
D3D11_SAMPLER_DESC sampDesc;
|
||||||
|
ZeroMemory(&sampDesc, sizeof(sampDesc));
|
||||||
|
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||||
|
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||||
|
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||||
|
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||||
|
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||||
|
sampDesc.MinLOD = 0;
|
||||||
|
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||||
|
|
||||||
|
hr = dev->CreateSamplerState(&sampDesc, &TexSamplerState);
|
||||||
|
if (FAILED(hr))
|
||||||
|
Throwanerror("Texture sampler state couldn't be created");
|
||||||
|
|
||||||
|
XMVECTOR Eye = XMVectorSet(0.0f, 5.0f, -300.0f, 0.0f);
|
||||||
|
XMVECTOR At = XMVectorSet(0.0f, 100.0f, 0.0f, 0.0f);
|
||||||
|
XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
|
||||||
|
m_View = XMMatrixLookAtLH(Eye, At, Up);
|
||||||
|
|
||||||
|
ourModel = new ModelLoader;
|
||||||
|
if (!ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx"))
|
||||||
|
Throwanerror("Model couldn't be loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob)
|
||||||
|
{
|
||||||
|
UINT compileFlags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
compileFlags |= D3DCOMPILE_DEBUG;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ID3DBlob* pErrorBlob = NULL;
|
||||||
|
|
||||||
|
HRESULT result = D3DCompileFromFile(pFileName, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntryPoint, pShaderModel, compileFlags, 0, ppBytecodeBlob, &pErrorBlob);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
if (pErrorBlob != NULL)
|
||||||
|
OutputDebugStringA((LPCSTR)pErrorBlob->GetBufferPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pErrorBlob != NULL)
|
||||||
|
pErrorBlob->Release();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Throwanerror(LPCSTR errormessage)
|
||||||
|
{
|
||||||
|
MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK);
|
||||||
|
}
|
|
@ -51,13 +51,23 @@ class utObjTools : public ::testing::Test {
|
||||||
|
|
||||||
class TestObjFileParser : public ObjFileParser {
|
class TestObjFileParser : public ObjFileParser {
|
||||||
public:
|
public:
|
||||||
TestObjFileParser() : ObjFileParser(){}
|
TestObjFileParser() : ObjFileParser(){
|
||||||
~TestObjFileParser() {}
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
~TestObjFileParser() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
void testCopyNextWord( char *pBuffer, size_t length ) {
|
void testCopyNextWord( char *pBuffer, size_t length ) {
|
||||||
copyNextWord( pBuffer, length );
|
copyNextWord( pBuffer, length );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t testGetNumComponentsInDataDefinition() {
|
||||||
|
return getNumComponentsInDataDefinition();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F( utObjTools, skipDataLine_OneLine_Success ) {
|
TEST_F( utObjTools, skipDataLine_OneLine_Success ) {
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
std::string data( "v -0.5 -0.5 0.5\nend" );
|
std::string data( "v -0.5 -0.5 0.5\nend" );
|
||||||
|
@ -71,7 +81,7 @@ TEST_F( utObjTools, skipDataLine_OneLine_Success ) {
|
||||||
|
|
||||||
TEST_F( utObjTools, skipDataLine_TwoLines_Success ) {
|
TEST_F( utObjTools, skipDataLine_TwoLines_Success ) {
|
||||||
TestObjFileParser test_parser;
|
TestObjFileParser test_parser;
|
||||||
std::string data( "vn -2.061493116917992e-15 -0.9009688496589661 \\n-0.4338837265968323" );
|
std::string data( "vn -2.061493116917992e-15 -0.9009688496589661 \\\n-0.4338837265968323" );
|
||||||
std::vector<char> buffer;
|
std::vector<char> buffer;
|
||||||
buffer.resize( data.size() );
|
buffer.resize( data.size() );
|
||||||
::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() );
|
::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() );
|
||||||
|
@ -91,3 +101,17 @@ TEST_F( utObjTools, skipDataLine_TwoLines_Success ) {
|
||||||
test_parser.testCopyNextWord( data_buffer, Size );
|
test_parser.testCopyNextWord( data_buffer, Size );
|
||||||
EXPECT_EQ( data_buffer[ 0 ], '-' );
|
EXPECT_EQ( data_buffer[ 0 ], '-' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F( utObjTools, countComponents_TwoLines_Success ) {
|
||||||
|
TestObjFileParser test_parser;
|
||||||
|
std::string data( "-2.061493116917992e-15 -0.9009688496589661 \\\n-0.4338837265968323" );
|
||||||
|
std::vector<char> buffer;
|
||||||
|
buffer.resize( data.size() );
|
||||||
|
::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() );
|
||||||
|
test_parser.setBuffer( buffer );
|
||||||
|
static const size_t Size = 4096UL;
|
||||||
|
char data_buffer[ Size ];
|
||||||
|
|
||||||
|
size_t numComps = test_parser.testGetNumComponentsInDataDefinition();
|
||||||
|
EXPECT_EQ( 3U, numComps );
|
||||||
|
}
|
||||||
|
|
|
@ -52,8 +52,9 @@ class utPMXImporter : public AbstractImportExportBase {
|
||||||
public:
|
public:
|
||||||
virtual bool importerTest() {
|
virtual bool importerTest() {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/../models-nonbsd/MMD/Alicia_blade.pmx", 0 );
|
/*const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/../models-nonbsd/MMD/Alicia_blade.pmx", 0 );
|
||||||
return nullptr != scene;
|
return nullptr != scene;*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "SceneAnimator.h"
|
#include "SceneAnimator.h"
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
|
||||||
|
#include <commdlg.h>
|
||||||
|
|
||||||
namespace AssimpView {
|
namespace AssimpView {
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
|
|
@ -41,6 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "assimp_view.h"
|
#include "assimp_view.h"
|
||||||
#include "richedit.h"
|
#include "richedit.h"
|
||||||
|
#include <commoncontrols.h>
|
||||||
|
#include <commdlg.h>
|
||||||
|
|
||||||
namespace AssimpView {
|
namespace AssimpView {
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
|
#include <commdlg.h>
|
||||||
|
#include <timeapi.h>
|
||||||
|
|
||||||
namespace AssimpView {
|
namespace AssimpView {
|
||||||
|
|
||||||
|
|
|
@ -72,20 +72,26 @@ struct SceneAnimNode
|
||||||
size_t mChannelIndex;
|
size_t mChannelIndex;
|
||||||
|
|
||||||
//! Default construction
|
//! Default construction
|
||||||
SceneAnimNode() {
|
SceneAnimNode()
|
||||||
mChannelIndex = -1; mParent = NULL;
|
: mName()
|
||||||
|
, mParent(NULL)
|
||||||
|
, mChannelIndex(-1) {
|
||||||
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Construction from a given name
|
//! Construction from a given name
|
||||||
SceneAnimNode( const std::string& pName)
|
SceneAnimNode( const std::string& pName)
|
||||||
: mName( pName) {
|
: mName( pName)
|
||||||
mChannelIndex = -1; mParent = NULL;
|
, mParent(NULL)
|
||||||
|
, mChannelIndex( -1 ) {
|
||||||
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Destruct all children recursively
|
//! Destruct all children recursively
|
||||||
~SceneAnimNode() {
|
~SceneAnimNode() {
|
||||||
for( std::vector<SceneAnimNode*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it)
|
for (std::vector<SceneAnimNode*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) {
|
||||||
delete *it;
|
delete *it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
#include "assimp_view.h"
|
#include "assimp_view.h"
|
||||||
|
#include <timeapi.h>
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue