Merge branch 'master' into export_3mf
commit
9ca7b00280
15
.travis.sh
15
.travis.sh
|
@ -43,9 +43,24 @@ if [ $ANDROID ]; then
|
|||
ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
|
||||
fi
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
if [ $ANALYZE = "ON" ] ; then
|
||||
if [ "$CC" = "clang" ]; then
|
||||
scan-build cmake -G "Unix Makefiles" -DBUILD_SHARED_LIBS=OFF -DASSIMP_BUILD_TESTS=OFF
|
||||
scan-build --status-bugs make -j2
|
||||
else
|
||||
cppcheck --version
|
||||
generate \
|
||||
&& cppcheck --error-exitcode=1 -j2 -Iinclude -Icode code 2> cppcheck.txt
|
||||
if [ -s cppcheck.txt ]; then
|
||||
cat cppcheck.txt
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
generate \
|
||||
&& make -j4 \
|
||||
&& sudo make install \
|
||||
&& sudo ldconfig \
|
||||
&& (cd test/unit; ../../bin/unit)
|
||||
fi
|
||||
fi
|
||||
|
|
18
.travis.yml
18
.travis.yml
|
@ -4,7 +4,7 @@ language: cpp
|
|||
cache: ccache
|
||||
|
||||
before_install:
|
||||
- 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 ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake cppcheck && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi
|
||||
- 'if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
if brew ls --versions cmake > /dev/null; then
|
||||
echo cmake already installed.;
|
||||
|
@ -34,11 +34,8 @@ env:
|
|||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: DISABLE_EXPORTERS=YES ENABLE_COVERALLS=ON
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: SHARED_BUILD=ON
|
||||
compiler: clang
|
||||
env: ANALYZE=ON
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: ASAN=ON
|
||||
|
@ -48,6 +45,15 @@ matrix:
|
|||
- os: linux
|
||||
compiler: clang
|
||||
env: SHARED_BUILD=ON
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: ANALYZE=ON
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: DISABLE_EXPORTERS=YES ENABLE_COVERALLS=ON
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: SHARED_BUILD=ON
|
||||
|
||||
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
|
||||
|
|
|
@ -183,8 +183,11 @@ SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
|
|||
|
||||
IF( UNIX )
|
||||
# Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux
|
||||
IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
|
||||
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
|
||||
IF( ${OPERATING_SYSTEM} MATCHES "Android")
|
||||
ELSE()
|
||||
IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
|
||||
#ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Use GNUInstallDirs for Unix predefined directories
|
||||
|
|
|
@ -310,7 +310,7 @@ foreach (GCOV_FILE ${GCOV_FILES})
|
|||
message("MD5: ${GCOV_SRC_PATH} = ${GCOV_CONTENTS_MD5}")
|
||||
|
||||
# Loads the gcov file as a list of lines.
|
||||
# (We first open the file and replace all occurences of [] with _
|
||||
# (We first open the file and replace all occurrences of [] with _
|
||||
# because CMake will fail to parse a line containing unmatched brackets...
|
||||
# also the \ to escaped \n in macros screws up things.)
|
||||
# https://public.kitware.com/Bug/view.php?id=15369
|
||||
|
@ -329,7 +329,7 @@ foreach (GCOV_FILE ${GCOV_FILES})
|
|||
# Instead of trying to parse the source from the
|
||||
# gcov file, simply read the file contents from the source file.
|
||||
# (Parsing it from the gcov is hard because C-code uses ; in many places
|
||||
# which also happens to be the same as the CMake list delimeter).
|
||||
# which also happens to be the same as the CMake list delimiter).
|
||||
file(READ ${GCOV_SRC_PATH} GCOV_FILE_SOURCE)
|
||||
|
||||
string(REPLACE "\\" "\\\\" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
|
||||
|
|
|
@ -249,7 +249,7 @@ private:
|
|||
|
||||
/// \fn size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A)
|
||||
/// Return converted texture ID which related to specified source textures ID's. If converted texture does not exist then it will be created and ID on new
|
||||
/// converted texture will be returned. Convertion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it
|
||||
/// converted texture will be returned. Conversion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it
|
||||
/// to converted textures list.
|
||||
/// Any of source ID's can be absent(empty string) or even one ID only specified. But at least one ID must be specified.
|
||||
/// \param [in] pID_R - ID of source "red" texture.
|
||||
|
@ -378,7 +378,7 @@ private:
|
|||
void XML_CheckNode_MustHaveChildren();
|
||||
|
||||
/// \fn bool XML_CheckNode_NameEqual(const std::string& pNodeName)
|
||||
/// Chek if current node name is equal to pNodeName.
|
||||
/// Check if current node name is equal to pNodeName.
|
||||
/// \param [in] pNodeName - name for checking.
|
||||
/// return true if current node name is equal to pNodeName, else - false.
|
||||
bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }
|
||||
|
|
|
@ -137,7 +137,7 @@ struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement
|
|||
{
|
||||
/****************** Variables ******************/
|
||||
|
||||
std::string ObjectID;///< ID of object for instanciation.
|
||||
std::string ObjectID;///< ID of object for instantiation.
|
||||
/// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to
|
||||
/// create an instance of the object in the current constellation.
|
||||
aiVector3D Delta;
|
||||
|
|
|
@ -281,8 +281,11 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string&
|
|||
{
|
||||
if(!pID.empty())
|
||||
{
|
||||
for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++)
|
||||
converted_texture.Data[idx_target] = src_texture[pSrcTexNum]->Data.at(idx_src);
|
||||
for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++) {
|
||||
CAMFImporter_NodeElement_Texture* tex = src_texture[pSrcTexNum];
|
||||
ai_assert(tex);
|
||||
converted_texture.Data[idx_target] = tex->Data.at(idx_src);
|
||||
}
|
||||
}
|
||||
};// auto CopyTextureData = [&](const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void
|
||||
|
||||
|
|
|
@ -1021,6 +1021,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
|
|||
|
||||
// convert bones, if existing
|
||||
if (!mesh.mBones.empty()) {
|
||||
ai_assert(avOutputBones);
|
||||
// check whether there is a vertex weight for this vertex index
|
||||
if (iIndex2 < mesh.mBoneVertices.size()) {
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v)
|
|||
t += Write<float>(stream,v.x);
|
||||
t += Write<float>(stream,v.y);
|
||||
t += Write<float>(stream,v.z);
|
||||
ai_assert(t == 16);
|
||||
return 16;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace Assimp {
|
|||
offset += Copy(&data[offset], header.size);
|
||||
offset += Copy(&data[offset], header.reserved1);
|
||||
offset += Copy(&data[offset], header.reserved2);
|
||||
offset += Copy(&data[offset], header.offset);
|
||||
Copy(&data[offset], header.offset);
|
||||
|
||||
file->Write(data, Header::header_size, 1);
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ namespace Assimp {
|
|||
offset += Copy(&data[offset], dib.x_resolution);
|
||||
offset += Copy(&data[offset], dib.y_resolution);
|
||||
offset += Copy(&data[offset], dib.nb_colors);
|
||||
offset += Copy(&data[offset], dib.nb_important_colors);
|
||||
Copy(&data[offset], dib.nb_important_colors);
|
||||
|
||||
file->Write(data, DIB::dib_size, 1);
|
||||
}
|
||||
|
|
|
@ -92,6 +92,12 @@ struct Error : DeadlyImportError {
|
|||
* descendents. It serves as base class for all data structure fields. */
|
||||
// -------------------------------------------------------------------------------
|
||||
struct ElemBase {
|
||||
ElemBase()
|
||||
: dna_type(nullptr)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
virtual ~ElemBase() {
|
||||
// empty
|
||||
}
|
||||
|
|
|
@ -59,7 +59,9 @@ template <> void Structure :: Convert<Object> (
|
|||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
|
||||
int temp = 0;
|
||||
ReadField<ErrorPolicy_Fail>(temp,"type",db);
|
||||
dest.type = static_cast<Assimp::Blender::Object::Type>(temp);
|
||||
ReadFieldArray2<ErrorPolicy_Warn>(dest.obmat,"obmat",db);
|
||||
ReadFieldArray2<ErrorPolicy_Warn>(dest.parentinv,"parentinv",db);
|
||||
ReadFieldArray<ErrorPolicy_Warn>(dest.parsubstr,"parsubstr",db);
|
||||
|
@ -100,14 +102,21 @@ template <> void Structure :: Convert<MTex> (
|
|||
) const
|
||||
{
|
||||
|
||||
ReadField<ErrorPolicy_Igno>((short&)dest.mapto,"mapto",db);
|
||||
ReadField<ErrorPolicy_Igno>((int&)dest.blendtype,"blendtype",db);
|
||||
int temp_short = 0;
|
||||
ReadField<ErrorPolicy_Igno>(temp_short,"mapto",db);
|
||||
dest.mapto = static_cast<Assimp::Blender::MTex::MapType>(temp_short);
|
||||
int temp = 0;
|
||||
ReadField<ErrorPolicy_Igno>(temp,"blendtype",db);
|
||||
dest.blendtype = static_cast<Assimp::Blender::MTex::BlendType>(temp);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.object,"*object",db);
|
||||
ReadFieldPtr<ErrorPolicy_Igno>(dest.tex,"*tex",db);
|
||||
ReadFieldArray<ErrorPolicy_Igno>(dest.uvname,"uvname",db);
|
||||
ReadField<ErrorPolicy_Igno>((int&)dest.projx,"projx",db);
|
||||
ReadField<ErrorPolicy_Igno>((int&)dest.projy,"projy",db);
|
||||
ReadField<ErrorPolicy_Igno>((int&)dest.projz,"projz",db);
|
||||
ReadField<ErrorPolicy_Igno>(temp,"projx",db);
|
||||
dest.projx = static_cast<Assimp::Blender::MTex::Projection>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(temp,"projy",db);
|
||||
dest.projy = static_cast<Assimp::Blender::MTex::Projection>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(temp,"projz",db);
|
||||
dest.projx = static_cast<Assimp::Blender::MTex::Projection>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db);
|
||||
ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db);
|
||||
ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db);
|
||||
|
@ -190,7 +199,9 @@ template <> void Structure :: Convert<Lamp> (
|
|||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
|
||||
int temp = 0;
|
||||
ReadField<ErrorPolicy_Fail>(temp,"type",db);
|
||||
dest.type = static_cast<Assimp::Blender::Lamp::Type>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.totex,"totex",db);
|
||||
|
@ -204,7 +215,8 @@ template <> void Structure :: Convert<Lamp> (
|
|||
ReadField<ErrorPolicy_Igno>(dest.spotblend,"spotblend",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.att1,"att1",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db);
|
||||
ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db);
|
||||
ReadField<ErrorPolicy_Igno>(temp,"falloff_type",db);
|
||||
dest.falloff_type = static_cast<Assimp::Blender::Lamp::FalloffType>(temp);
|
||||
ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.area_size,"area_size",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.area_sizey,"area_sizey",db);
|
||||
|
@ -693,8 +705,12 @@ template <> void Structure :: Convert<Tex> (
|
|||
const FileDatabase& db
|
||||
) const
|
||||
{
|
||||
ReadField<ErrorPolicy_Igno>((short&)dest.imaflag,"imaflag",db);
|
||||
ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
|
||||
short temp_short = 0;
|
||||
ReadField<ErrorPolicy_Igno>(temp_short,"imaflag",db);
|
||||
dest.imaflag = static_cast<Assimp::Blender::Tex::ImageFlags>(temp_short);
|
||||
int temp = 0;
|
||||
ReadField<ErrorPolicy_Fail>(temp,"type",db);
|
||||
dest.type = static_cast<Assimp::Blender::Tex::Type>(temp);
|
||||
ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db);
|
||||
|
||||
db.reader->IncPtr(size);
|
||||
|
@ -708,8 +724,11 @@ template <> void Structure :: Convert<Camera> (
|
|||
{
|
||||
|
||||
ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
|
||||
ReadField<ErrorPolicy_Warn>((int&)dest.type,"type",db);
|
||||
ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db);
|
||||
int temp = 0;
|
||||
ReadField<ErrorPolicy_Warn>(temp,"type",db);
|
||||
dest.type = static_cast<Assimp::Blender::Camera::Type>(temp);
|
||||
ReadField<ErrorPolicy_Warn>(temp,"flag",db);
|
||||
dest.flag = static_cast<Assimp::Blender::Camera::Type>(temp);
|
||||
ReadField<ErrorPolicy_Warn>(dest.lens,"lens",db);
|
||||
ReadField<ErrorPolicy_Warn>(dest.sensor_x,"sensor_x",db);
|
||||
ReadField<ErrorPolicy_Igno>(dest.clipsta,"clipsta",db);
|
||||
|
|
|
@ -225,6 +225,14 @@ struct TFace : ElemBase {
|
|||
|
||||
// -------------------------------------------------------------------------------
|
||||
struct MTFace : ElemBase {
|
||||
MTFace()
|
||||
: flag(0)
|
||||
, mode(0)
|
||||
, tile(0)
|
||||
, unwrap(0)
|
||||
{
|
||||
}
|
||||
|
||||
float uv[4][2] FAIL;
|
||||
char flag;
|
||||
short mode;
|
||||
|
|
|
@ -141,6 +141,9 @@ void ColladaExporter::WriteFile()
|
|||
WriteControllerLibrary();
|
||||
|
||||
WriteSceneLibrary();
|
||||
|
||||
// customized, Writes the animation library
|
||||
WriteAnimationsLibrary();
|
||||
|
||||
// useless Collada fu at the end, just in case we haven't had enough indirections, yet.
|
||||
mOutput << startstr << "<scene>" << endstr;
|
||||
|
@ -1129,6 +1132,7 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
|
|||
case FloatType_Color: floatsPerElement = 3; break;
|
||||
case FloatType_Mat4x4: floatsPerElement = 16; break;
|
||||
case FloatType_Weight: floatsPerElement = 1; break;
|
||||
case FloatType_Time: floatsPerElement = 1; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -1205,7 +1209,13 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
|
|||
case FloatType_Weight:
|
||||
mOutput << startstr << "<param name=\"WEIGHT\" type=\"float\" />" << endstr;
|
||||
break;
|
||||
}
|
||||
|
||||
// customized, add animation related
|
||||
case FloatType_Time:
|
||||
mOutput << startstr << "<param name=\"TIME\" type=\"float\" />" << endstr;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
PopTag();
|
||||
mOutput << startstr << "</accessor>" << endstr;
|
||||
|
@ -1235,7 +1245,172 @@ void ColladaExporter::WriteSceneLibrary()
|
|||
PopTag();
|
||||
mOutput << startstr << "</library_visual_scenes>" << endstr;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
|
||||
{
|
||||
const aiAnimation * anim = mScene->mAnimations[pIndex];
|
||||
|
||||
if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 )
|
||||
return;
|
||||
|
||||
const std::string animation_name_escaped = XMLEscape( anim->mName.C_Str() );
|
||||
std::string idstr = anim->mName.C_Str();
|
||||
std::string ending = std::string( "AnimId" ) + to_string(pIndex);
|
||||
if (idstr.length() >= ending.length()) {
|
||||
if (0 != idstr.compare (idstr.length() - ending.length(), ending.length(), ending)) {
|
||||
idstr = idstr + ending;
|
||||
}
|
||||
} else {
|
||||
idstr = idstr + ending;
|
||||
}
|
||||
|
||||
const std::string idstrEscaped = XMLEscape(idstr);
|
||||
|
||||
mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
|
||||
PushTag();
|
||||
|
||||
for (size_t a = 0; a < anim->mNumChannels; ++a) {
|
||||
const aiNodeAnim * nodeAnim = anim->mChannels[a];
|
||||
|
||||
// sanity check
|
||||
if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
|
||||
|
||||
{
|
||||
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input");
|
||||
|
||||
std::vector<ai_real> frames;
|
||||
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
|
||||
frames.push_back(nodeAnim->mPositionKeys[i].mTime);
|
||||
}
|
||||
|
||||
WriteFloatArray( node_idstr , FloatType_Time, (const ai_real*) frames.data(), frames.size());
|
||||
frames.clear();
|
||||
}
|
||||
|
||||
{
|
||||
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output");
|
||||
|
||||
std::vector<ai_real> keyframes;
|
||||
keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
|
||||
for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
|
||||
|
||||
aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue;
|
||||
aiMatrix4x4 ScalingM; // identity
|
||||
ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z;
|
||||
|
||||
aiQuaternion RotationQ = nodeAnim->mRotationKeys[i].mValue;
|
||||
aiMatrix4x4 s = aiMatrix4x4( RotationQ.GetMatrix() );
|
||||
aiMatrix4x4 RotationM(s.a1, s.a2, s.a3, 0, s.b1, s.b2, s.b3, 0, s.c1, s.c2, s.c3, 0, 0, 0, 0, 1);
|
||||
|
||||
aiVector3D Translation = nodeAnim->mPositionKeys[i].mValue;
|
||||
aiMatrix4x4 TranslationM; // identity
|
||||
TranslationM[0][3] = Translation.x; TranslationM[1][3] = Translation.y; TranslationM[2][3] = Translation.z;
|
||||
|
||||
// Combine the above transformations
|
||||
aiMatrix4x4 mat = TranslationM * RotationM * ScalingM;
|
||||
|
||||
for( size_t j = 0; j < 4; ++j) {
|
||||
keyframes.insert(keyframes.end(), mat[j], mat[j] + 4);
|
||||
}
|
||||
}
|
||||
|
||||
WriteFloatArray( node_idstr, FloatType_Mat4x4, (const ai_real*) keyframes.data(), keyframes.size() / 16);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
for ( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
|
||||
if ( nodeAnim->mPreState == aiAnimBehaviour_DEFAULT
|
||||
|| nodeAnim->mPreState == aiAnimBehaviour_LINEAR
|
||||
|| nodeAnim->mPreState == aiAnimBehaviour_REPEAT
|
||||
) {
|
||||
names.push_back( "LINEAR" );
|
||||
} else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) {
|
||||
names.push_back( "STEP" );
|
||||
}
|
||||
}
|
||||
|
||||
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-interpolation");
|
||||
std::string arrayId = node_idstr + "-array";
|
||||
|
||||
mOutput << startstr << "<source id=\"" << XMLEscape(node_idstr) << "\">" << endstr;
|
||||
PushTag();
|
||||
|
||||
// source array
|
||||
mOutput << startstr << "<Name_array id=\"" << XMLEscape(arrayId) << "\" count=\"" << names.size() << "\"> ";
|
||||
for( size_t a = 0; a < names.size(); ++a ) {
|
||||
mOutput << names[a] << " ";
|
||||
}
|
||||
mOutput << "</Name_array>" << endstr;
|
||||
|
||||
mOutput << startstr << "<technique_common>" << endstr;
|
||||
PushTag();
|
||||
|
||||
mOutput << startstr << "<accessor source=\"#" << XMLEscape(arrayId) << "\" count=\"" << names.size() << "\" stride=\"" << 1 << "\">" << endstr;
|
||||
PushTag();
|
||||
|
||||
mOutput << startstr << "<param name=\"INTERPOLATION\" type=\"name\"></param>" << endstr;
|
||||
|
||||
PopTag();
|
||||
mOutput << startstr << "</accessor>" << endstr;
|
||||
|
||||
PopTag();
|
||||
mOutput << startstr << "</technique_common>" << endstr;
|
||||
|
||||
PopTag();
|
||||
mOutput << startstr << "</source>" << endstr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (size_t a = 0; a < anim->mNumChannels; ++a) {
|
||||
const aiNodeAnim * nodeAnim = anim->mChannels[a];
|
||||
|
||||
{
|
||||
// samplers
|
||||
const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-sampler");
|
||||
mOutput << startstr << "<sampler id=\"" << XMLEscape(node_idstr) << "\">" << endstr;
|
||||
PushTag();
|
||||
|
||||
mOutput << startstr << "<input semantic=\"INPUT\" source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-input") ) << "\"/>" << endstr;
|
||||
mOutput << startstr << "<input semantic=\"OUTPUT\" source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-output") ) << "\"/>" << endstr;
|
||||
mOutput << startstr << "<input semantic=\"INTERPOLATION\" source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-interpolation") ) << "\"/>" << endstr;
|
||||
|
||||
PopTag();
|
||||
mOutput << startstr << "</sampler>" << endstr;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t a = 0; a < anim->mNumChannels; ++a) {
|
||||
const aiNodeAnim * nodeAnim = anim->mChannels[a];
|
||||
|
||||
{
|
||||
// channels
|
||||
mOutput << startstr << "<channel source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-sampler") ) << "\" target=\"" << XMLEscape(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr;
|
||||
}
|
||||
}
|
||||
|
||||
PopTag();
|
||||
mOutput << startstr << "</animation>" << endstr;
|
||||
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ColladaExporter::WriteAnimationsLibrary()
|
||||
{
|
||||
const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str());
|
||||
|
||||
if ( mScene->mNumAnimations > 0 ) {
|
||||
mOutput << startstr << "<library_animations>" << endstr;
|
||||
PushTag();
|
||||
|
||||
// start recursive write at the root node
|
||||
for( size_t a = 0; a < mScene->mNumAnimations; ++a)
|
||||
WriteAnimationLibrary( a );
|
||||
|
||||
PopTag();
|
||||
mOutput << startstr << "</library_animations>" << endstr;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Helper to find a bone by name in the scene
|
||||
aiBone* findBone( const aiScene* scene, const char * name) {
|
||||
|
@ -1251,6 +1426,59 @@ aiBone* findBone( const aiScene* scene, const char * name) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiNode * findBoneNode( const aiNode* aNode, const aiBone* bone)
|
||||
{
|
||||
if ( aNode && bone && aNode->mName == bone->mName ) {
|
||||
return aNode;
|
||||
}
|
||||
|
||||
if ( aNode && bone ) {
|
||||
for (unsigned int i=0; i < aNode->mNumChildren; ++i) {
|
||||
aiNode * aChild = aNode->mChildren[i];
|
||||
const aiNode * foundFromChild = 0;
|
||||
if ( aChild ) {
|
||||
foundFromChild = findBoneNode( aChild, bone );
|
||||
if ( foundFromChild ) return foundFromChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh)
|
||||
{
|
||||
std::set<const aiNode*> topParentBoneNodes;
|
||||
if ( mesh && mesh->mNumBones > 0 ) {
|
||||
for (unsigned int i=0; i < mesh->mNumBones; ++i) {
|
||||
aiBone * bone = mesh->mBones[i];
|
||||
|
||||
const aiNode * node = findBoneNode( scene->mRootNode, bone);
|
||||
if ( node ) {
|
||||
while ( node->mParent && findBone(scene, node->mParent->mName.C_Str() ) != 0 ) {
|
||||
node = node->mParent;
|
||||
}
|
||||
topParentBoneNodes.insert( node );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !topParentBoneNodes.empty() ) {
|
||||
const aiNode * parentBoneNode = *topParentBoneNodes.begin();
|
||||
if ( topParentBoneNodes.size() == 1 ) {
|
||||
return parentBoneNode;
|
||||
} else {
|
||||
for (auto it : topParentBoneNodes) {
|
||||
if ( it->mParent ) return it->mParent;
|
||||
}
|
||||
return parentBoneNode;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Recursively writes the given node
|
||||
void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
|
||||
|
@ -1278,12 +1506,22 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
|
|||
}
|
||||
|
||||
const std::string node_name_escaped = XMLEscape(pNode->mName.data);
|
||||
/* // customized, Note! the id field is crucial for inter-xml look up, it cannot be replaced with sid ?!
|
||||
mOutput << startstr
|
||||
<< "<node ";
|
||||
if(is_skeleton_root)
|
||||
mOutput << "id=\"" << "skeleton_root" << "\" "; // For now, only support one skeleton in a scene.
|
||||
mOutput << (is_joint ? "s" : "") << "id=\"" << node_name_escaped;
|
||||
mOutput << "\" name=\"" << node_name_escaped
|
||||
*/
|
||||
mOutput << startstr << "<node ";
|
||||
if(is_skeleton_root) {
|
||||
mOutput << "id=\"" << node_name_escaped << "\" " << (is_joint ? "sid=\"" + node_name_escaped +"\"" : "") ; // For now, only support one skeleton in a scene.
|
||||
mFoundSkeletonRootNodeID = node_name_escaped;
|
||||
} else {
|
||||
mOutput << "id=\"" << node_name_escaped << "\" " << (is_joint ? "sid=\"" + node_name_escaped +"\"": "") ;
|
||||
}
|
||||
|
||||
mOutput << " name=\"" << node_name_escaped
|
||||
<< "\" type=\"" << node_type
|
||||
<< "\">" << endstr;
|
||||
PushTag();
|
||||
|
@ -1291,7 +1529,11 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
|
|||
// write transformation - we can directly put the matrix there
|
||||
// TODO: (thom) decompose into scale - rot - quad to allow addressing it by animations afterwards
|
||||
const aiMatrix4x4& mat = pNode->mTransformation;
|
||||
mOutput << startstr << "<matrix sid=\"transform\">";
|
||||
|
||||
// customized, sid should be 'matrix' to match with loader code.
|
||||
//mOutput << startstr << "<matrix sid=\"transform\">";
|
||||
mOutput << startstr << "<matrix sid=\"matrix\">";
|
||||
|
||||
mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " ";
|
||||
mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " ";
|
||||
mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " ";
|
||||
|
@ -1319,7 +1561,7 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
|
|||
for( size_t a = 0; a < pNode->mNumMeshes; ++a )
|
||||
{
|
||||
const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]];
|
||||
// do not instanciate mesh if empty. I wonder how this could happen
|
||||
// do not instantiate mesh if empty. I wonder how this could happen
|
||||
if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
|
||||
continue;
|
||||
|
||||
|
@ -1335,7 +1577,13 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
|
|||
<< endstr;
|
||||
PushTag();
|
||||
|
||||
mOutput << startstr << "<skeleton>#skeleton_root</skeleton>" << endstr;
|
||||
// note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node.
|
||||
// use the first bone to find skeleton root
|
||||
const aiNode * skeletonRootBoneNode = findSkeletonRootNode( pScene, mesh );
|
||||
if ( skeletonRootBoneNode ) {
|
||||
mFoundSkeletonRootNodeID = XMLEscape( skeletonRootBoneNode->mName.C_Str() );
|
||||
}
|
||||
mOutput << startstr << "<skeleton>#" << mFoundSkeletonRootNodeID << "</skeleton>" << endstr;
|
||||
}
|
||||
mOutput << startstr << "<bind_material>" << endstr;
|
||||
PushTag();
|
||||
|
|
|
@ -114,7 +114,9 @@ protected:
|
|||
/// Writes the given mesh
|
||||
void WriteGeometry( size_t pIndex);
|
||||
|
||||
enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight };
|
||||
//enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight };
|
||||
// customized to add animation related type
|
||||
enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight, FloatType_Time };
|
||||
|
||||
/// Writes a float array of the given type
|
||||
void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount);
|
||||
|
@ -122,6 +124,11 @@ protected:
|
|||
/// Writes the scene library
|
||||
void WriteSceneLibrary();
|
||||
|
||||
// customized, Writes the animation library
|
||||
void WriteAnimationsLibrary();
|
||||
void WriteAnimationLibrary( size_t pIndex);
|
||||
std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call.
|
||||
|
||||
/// Recursively writes the given node
|
||||
void WriteNode( const aiScene* scene, aiNode* pNode);
|
||||
|
||||
|
|
|
@ -302,7 +302,7 @@ struct Accessor
|
|||
size_t mOffset; // in number of values
|
||||
size_t mStride; // Stride in number of values
|
||||
std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
|
||||
size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on.
|
||||
size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on.
|
||||
// For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
|
||||
std::string mSource; // URL of the source array
|
||||
mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
|
||||
|
|
|
@ -1619,7 +1619,7 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
|
|||
mat.AddProperty( &effect.mRefractIndex, 1, AI_MATKEY_REFRACTI);
|
||||
|
||||
// transparency, a very hard one. seemingly not all files are following the
|
||||
// specification here (1.0 transparency => completly opaque)...
|
||||
// specification here (1.0 transparency => completely opaque)...
|
||||
// therefore, we let the opportunity for the user to manually invert
|
||||
// the transparency if necessary and we add preliminary support for RGB_ZERO mode
|
||||
if(effect.mTransparency >= 0.f && effect.mTransparency <= 1.f) {
|
||||
|
|
|
@ -224,7 +224,7 @@ void ColladaParser::ReadStructure()
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Reads asset informations such as coordinate system informations and legal blah
|
||||
// Reads asset information such as coordinate system information and legal blah
|
||||
void ColladaParser::ReadAssetInfo()
|
||||
{
|
||||
if( mReader->isEmptyElement())
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace Assimp
|
|||
/** Reads the structure of the file */
|
||||
void ReadStructure();
|
||||
|
||||
/** Reads asset informations such as coordinate system informations and legal blah */
|
||||
/** Reads asset information such as coordinate system information and legal blah */
|
||||
void ReadAssetInfo();
|
||||
|
||||
/** Reads the animation library */
|
||||
|
|
|
@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/ai_assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef __unix__
|
||||
#include <sys/param.h>
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -422,7 +422,6 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -566,7 +566,6 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
|||
|
||||
if ( !name_carrier ) {
|
||||
nodes_chain.push_back( new aiNode( original_name ) );
|
||||
name_carrier = nodes_chain.back();
|
||||
}
|
||||
|
||||
//setup metadata on newest node
|
||||
|
@ -645,7 +644,6 @@ void Converter::ConvertCameras( const Model& model )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Converter::ConvertLight( const Model& model, const Light& light )
|
||||
{
|
||||
lights.push_back( new aiLight() );
|
||||
|
@ -783,7 +781,6 @@ const char* Converter::NameTransformationComp( TransformationComp comp )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char* Converter::NameTransformationCompProperty( TransformationComp comp )
|
||||
{
|
||||
switch ( comp )
|
||||
|
@ -2239,9 +2236,17 @@ void Converter::ConvertAnimations()
|
|||
}
|
||||
}
|
||||
|
||||
void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name ) {
|
||||
if ( node_names.find( fixed_name ) == node_names.end() ) {
|
||||
FBXImporter::LogError( "Cannot rename node " + fixed_name + ", not existing.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( node_names.find( new_name ) != node_names.end() ) {
|
||||
FBXImporter::LogError( "Cannot rename node " + fixed_name + " to " + new_name +", name already existing." );
|
||||
return;
|
||||
}
|
||||
|
||||
void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name )
|
||||
{
|
||||
ai_assert( node_names.find( fixed_name ) != node_names.end() );
|
||||
ai_assert( node_names.find( new_name ) == node_names.end() );
|
||||
|
||||
|
|
|
@ -45,13 +45,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "FIReader.hpp"
|
||||
#include "StringUtils.h"
|
||||
|
||||
// Workaround for issue #1361
|
||||
// https://github.com/assimp/assimp/issues/1361
|
||||
#ifdef __ANDROID__
|
||||
#define _GLIBCXX_USE_C99 1
|
||||
# define _GLIBCXX_USE_C99 1
|
||||
#endif
|
||||
|
||||
#include "FIReader.hpp"
|
||||
#include "Exceptional.h"
|
||||
#include <assimp/IOStream.hpp>
|
||||
#include <assimp/types.h>
|
||||
|
@ -485,7 +487,9 @@ struct FIFloatDecoder: public FIDecoder {
|
|||
value.reserve(numFloats);
|
||||
for (size_t i = 0; i < numFloats; ++i) {
|
||||
int v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
|
||||
value.push_back(*(float*)&v);
|
||||
float f;
|
||||
memcpy(&f, &v, 4);
|
||||
value.push_back(f);
|
||||
data += 4;
|
||||
}
|
||||
return FIFloatValue::create(std::move(value));
|
||||
|
@ -503,7 +507,9 @@ struct FIDoubleDecoder: public FIDecoder {
|
|||
for (size_t i = 0; i < numDoubles; ++i) {
|
||||
long long b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7];
|
||||
long long v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
|
||||
value.push_back(*(double*)&v);
|
||||
double f;
|
||||
memcpy(&f, &v, 8);
|
||||
value.push_back(f);
|
||||
data += 8;
|
||||
}
|
||||
return FIDoubleValue::create(std::move(value));
|
||||
|
@ -685,7 +691,7 @@ public:
|
|||
if (intValue) {
|
||||
return intValue->value.size() == 1 ? intValue->value.front() : 0;
|
||||
}
|
||||
return stoi(attr->value->toString());
|
||||
return atoi(attr->value->toString().c_str());
|
||||
}
|
||||
|
||||
virtual int getAttributeValueAsInt(int idx) const /*override*/ {
|
||||
|
@ -696,7 +702,7 @@ public:
|
|||
if (intValue) {
|
||||
return intValue->value.size() == 1 ? intValue->value.front() : 0;
|
||||
}
|
||||
return stoi(attributes[idx].value->toString());
|
||||
return atoi(attributes[idx].value->toString().c_str());
|
||||
}
|
||||
|
||||
virtual float getAttributeValueAsFloat(const char* name) const /*override*/ {
|
||||
|
@ -708,7 +714,7 @@ public:
|
|||
if (floatValue) {
|
||||
return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
|
||||
}
|
||||
return stof(attr->value->toString());
|
||||
return atof(attr->value->toString().c_str());
|
||||
}
|
||||
|
||||
virtual float getAttributeValueAsFloat(int idx) const /*override*/ {
|
||||
|
@ -719,7 +725,7 @@ public:
|
|||
if (floatValue) {
|
||||
return floatValue->value.size() == 1 ? floatValue->value.front() : 0;
|
||||
}
|
||||
return stof(attributes[idx].value->toString());
|
||||
return atof(attributes[idx].value->toString().c_str());
|
||||
}
|
||||
|
||||
virtual const char* getNodeName() const /*override*/ {
|
||||
|
@ -984,13 +990,13 @@ private:
|
|||
if (index < 32) {
|
||||
FIDecoder *decoder = defaultDecoder[index];
|
||||
if (!decoder) {
|
||||
throw DeadlyImportError("Invalid encoding algorithm index " + std::to_string(index));
|
||||
throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index));
|
||||
}
|
||||
return decoder->decode(dataP, len);
|
||||
}
|
||||
else {
|
||||
if (index - 32 >= vocabulary.encodingAlgorithmTable.size()) {
|
||||
throw DeadlyImportError("Invalid encoding algorithm index " + std::to_string(index));
|
||||
throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index));
|
||||
}
|
||||
std::string uri = vocabulary.encodingAlgorithmTable[index - 32];
|
||||
auto it = decoderMap.find(uri);
|
||||
|
@ -1014,12 +1020,12 @@ private:
|
|||
alphabet = "0123456789-:TZ ";
|
||||
break;
|
||||
default:
|
||||
throw DeadlyImportError("Invalid restricted alphabet index " + std::to_string(index));
|
||||
throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (index - 16 >= vocabulary.restrictedAlphabetTable.size()) {
|
||||
throw DeadlyImportError("Invalid restricted alphabet index " + std::to_string(index));
|
||||
throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index));
|
||||
}
|
||||
alphabet = vocabulary.restrictedAlphabetTable[index - 16];
|
||||
}
|
||||
|
@ -1027,7 +1033,7 @@ private:
|
|||
utf8::utf8to32(alphabet.begin(), alphabet.end(), back_inserter(alphabetUTF32));
|
||||
std::string::size_type alphabetLength = alphabetUTF32.size();
|
||||
if (alphabetLength < 2) {
|
||||
throw DeadlyImportError("Invalid restricted alphabet length " + std::to_string(alphabetLength));
|
||||
throw DeadlyImportError("Invalid restricted alphabet length " + to_string(alphabetLength));
|
||||
}
|
||||
std::string::size_type bitsPerCharacter = 1;
|
||||
while ((1ull << bitsPerCharacter) <= alphabetLength) {
|
||||
|
|
|
@ -46,11 +46,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef INCLUDED_AI_FI_READER_H
|
||||
#define INCLUDED_AI_FI_READER_H
|
||||
|
||||
#include <irrXML.h>
|
||||
#include <memory>
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
//#include <wchar.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <cerrno>
|
||||
#include <cwchar>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
//#include <stdio.h>
|
||||
//#include <cstdint>
|
||||
#include <irrXML.h>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
@ -154,7 +160,7 @@ class IOStream;
|
|||
|
||||
class FIReader: public irr::io::IIrrXMLReader<char, irr::io::IXMLBase> {
|
||||
public:
|
||||
|
||||
virtual ~FIReader();
|
||||
virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(int idx) const = 0;
|
||||
|
||||
virtual std::shared_ptr<const FIValue> getAttributeEncodedValue(const char *name) const = 0;
|
||||
|
@ -167,6 +173,13 @@ public:
|
|||
|
||||
};// class IFIReader
|
||||
|
||||
inline
|
||||
FIReader::~FIReader() {
|
||||
// empty
|
||||
}
|
||||
|
||||
}// namespace Assimp
|
||||
|
||||
#endif // #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#endif // INCLUDED_AI_FI_READER_H
|
||||
|
|
|
@ -56,98 +56,138 @@ using namespace Assimp;
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
FindDegeneratesProcess::FindDegeneratesProcess()
|
||||
: configRemoveDegenerates (false)
|
||||
{}
|
||||
: mConfigRemoveDegenerates( false )
|
||||
, mConfigCheckAreaOfTriangle( false ){
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
FindDegeneratesProcess::~FindDegeneratesProcess()
|
||||
{
|
||||
FindDegeneratesProcess::~FindDegeneratesProcess() {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the processing step is present in the given flag field.
|
||||
bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const
|
||||
{
|
||||
bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const {
|
||||
return 0 != (pFlags & aiProcess_FindDegenerates);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup import configuration
|
||||
void FindDegeneratesProcess::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
void FindDegeneratesProcess::SetupProperties(const Importer* pImp) {
|
||||
// Get the current value of AI_CONFIG_PP_FD_REMOVE
|
||||
configRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0));
|
||||
mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0));
|
||||
mConfigCheckAreaOfTriangle = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA) );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported data.
|
||||
void FindDegeneratesProcess::Execute( aiScene* pScene)
|
||||
{
|
||||
void FindDegeneratesProcess::Execute( aiScene* pScene) {
|
||||
DefaultLogger::get()->debug("FindDegeneratesProcess begin");
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i){
|
||||
ExecuteOnMesh( pScene->mMeshes[i]);
|
||||
ExecuteOnMesh( pScene->mMeshes[ i ] );
|
||||
}
|
||||
DefaultLogger::get()->debug("FindDegeneratesProcess finished");
|
||||
}
|
||||
|
||||
static ai_real heron( ai_real a, ai_real b, ai_real c ) {
|
||||
ai_real s = (a + b + c) / 2;
|
||||
ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), 0.5 );
|
||||
return area;
|
||||
}
|
||||
|
||||
static ai_real distance3D( const aiVector3D &vA, aiVector3D &vB ) {
|
||||
const ai_real lx = ( vB.x - vA.x );
|
||||
const ai_real ly = ( vB.y - vA.y );
|
||||
const ai_real lz = ( vB.z - vA.z );
|
||||
ai_real a = lx*lx + ly*ly + lz*lz;
|
||||
ai_real d = pow( a, 0.5 );
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
|
||||
ai_real area = 0;
|
||||
|
||||
aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] );
|
||||
aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] );
|
||||
aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] );
|
||||
|
||||
ai_real a( distance3D( vA, vB ) );
|
||||
ai_real b( distance3D( vB, vC ) );
|
||||
ai_real c( distance3D( vC, vA ) );
|
||||
area = heron( a, b, c );
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Executes the post processing step on the given imported mesh
|
||||
void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh)
|
||||
{
|
||||
void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
|
||||
mesh->mPrimitiveTypes = 0;
|
||||
|
||||
std::vector<bool> remove_me;
|
||||
if (configRemoveDegenerates)
|
||||
remove_me.resize(mesh->mNumFaces,false);
|
||||
if (mConfigRemoveDegenerates) {
|
||||
remove_me.resize( mesh->mNumFaces, false );
|
||||
}
|
||||
|
||||
unsigned int deg = 0, limit;
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
|
||||
{
|
||||
for ( unsigned int a = 0; a < mesh->mNumFaces; ++a ) {
|
||||
aiFace& face = mesh->mFaces[a];
|
||||
bool first = true;
|
||||
|
||||
// check whether the face contains degenerated entries
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i) {
|
||||
// Polygons with more than 4 points are allowed to have double points, that is
|
||||
// simulating polygons with holes just with concave polygons. However,
|
||||
// double points may not come directly after another.
|
||||
limit = face.mNumIndices;
|
||||
if (face.mNumIndices > 4)
|
||||
limit = std::min(limit,i+2);
|
||||
if (face.mNumIndices > 4) {
|
||||
limit = std::min( limit, i+2 );
|
||||
}
|
||||
|
||||
for (unsigned int t = i+1; t < limit; ++t)
|
||||
{
|
||||
if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]])
|
||||
{
|
||||
for (unsigned int t = i+1; t < limit; ++t) {
|
||||
if (mesh->mVertices[face.mIndices[ i ] ] == mesh->mVertices[ face.mIndices[ t ] ]) {
|
||||
// we have found a matching vertex position
|
||||
// remove the corresponding index from the array
|
||||
--face.mNumIndices;--limit;
|
||||
for (unsigned int m = t; m < face.mNumIndices; ++m)
|
||||
{
|
||||
face.mIndices[m] = face.mIndices[m+1];
|
||||
--face.mNumIndices;
|
||||
--limit;
|
||||
for (unsigned int m = t; m < face.mNumIndices; ++m) {
|
||||
face.mIndices[ m ] = face.mIndices[ m+1 ];
|
||||
}
|
||||
--t;
|
||||
|
||||
// NOTE: we set the removed vertex index to an unique value
|
||||
// to make sure the developer gets notified when his
|
||||
// application attemps to access this data.
|
||||
face.mIndices[face.mNumIndices] = 0xdeadbeef;
|
||||
face.mIndices[ face.mNumIndices ] = 0xdeadbeef;
|
||||
|
||||
if(first)
|
||||
{
|
||||
if(first) {
|
||||
++deg;
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (configRemoveDegenerates) {
|
||||
remove_me[a] = true;
|
||||
if ( mConfigRemoveDegenerates ) {
|
||||
remove_me[ a ] = true;
|
||||
goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( mConfigCheckAreaOfTriangle ) {
|
||||
if ( face.mNumIndices == 3 ) {
|
||||
ai_real area = calculateAreaOfTriangle( face, mesh );
|
||||
if ( area < 1e-6 ) {
|
||||
if ( mConfigRemoveDegenerates ) {
|
||||
remove_me[ a ] = true;
|
||||
goto evil_jump_outside;
|
||||
}
|
||||
|
||||
// todo: check for index which is corrupt.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We need to update the primitive flags array of the mesh.
|
||||
|
@ -171,7 +211,7 @@ evil_jump_outside:
|
|||
}
|
||||
|
||||
// If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import
|
||||
if (configRemoveDegenerates && deg) {
|
||||
if (mConfigRemoveDegenerates && deg) {
|
||||
unsigned int n = 0;
|
||||
for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
|
||||
{
|
||||
|
|
|
@ -54,15 +54,11 @@ namespace Assimp {
|
|||
// ---------------------------------------------------------------------------
|
||||
/** FindDegeneratesProcess: Searches a mesh for degenerated triangles.
|
||||
*/
|
||||
class ASSIMP_API FindDegeneratesProcess : public BaseProcess
|
||||
{
|
||||
class ASSIMP_API FindDegeneratesProcess : public BaseProcess {
|
||||
public:
|
||||
|
||||
FindDegeneratesProcess();
|
||||
~FindDegeneratesProcess();
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Check whether step is active
|
||||
bool IsActive( unsigned int pFlags) const;
|
||||
|
@ -79,28 +75,53 @@ public:
|
|||
// Execute step on a given mesh
|
||||
void ExecuteOnMesh( aiMesh* mesh);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/// @brief Enable the instant removal of degenerated primitives
|
||||
/// @param enabled true for enabled.
|
||||
void EnableInstantRemoval(bool enabled);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Enable the instant removal of degenerated primitives
|
||||
* @param d hm ... difficult to guess what this means, hu!?
|
||||
*/
|
||||
void EnableInstantRemoval(bool d) {
|
||||
configRemoveDegenerates = d;
|
||||
}
|
||||
/// @brief Check whether instant removal is currently enabled
|
||||
/// @return The instant removal state.
|
||||
bool IsInstantRemoval() const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Check whether instant removal is currently enabled
|
||||
* @return ...
|
||||
*/
|
||||
bool IsInstantRemoval() const {
|
||||
return configRemoveDegenerates;
|
||||
}
|
||||
/// @brief Enable the area check for triangles.
|
||||
/// @param enabled true for enabled.
|
||||
void EnableAreaCheck( bool enabled );
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/// @brief Check whether the area check is enabled.
|
||||
/// @return The area check state.
|
||||
bool isAreaCheckEnabled() const;
|
||||
|
||||
private:
|
||||
|
||||
//! Configuration option: remove degenerates faces immediately
|
||||
bool configRemoveDegenerates;
|
||||
bool mConfigRemoveDegenerates;
|
||||
//! Configuration option: check for area
|
||||
bool mConfigCheckAreaOfTriangle;
|
||||
};
|
||||
|
||||
inline
|
||||
void FindDegeneratesProcess::EnableInstantRemoval(bool enabled) {
|
||||
mConfigRemoveDegenerates = enabled;
|
||||
}
|
||||
|
||||
inline
|
||||
bool FindDegeneratesProcess::IsInstantRemoval() const {
|
||||
return mConfigRemoveDegenerates;
|
||||
}
|
||||
|
||||
inline
|
||||
void FindDegeneratesProcess::EnableAreaCheck( bool enabled ) {
|
||||
mConfigCheckAreaOfTriangle = enabled;
|
||||
}
|
||||
|
||||
inline
|
||||
bool FindDegeneratesProcess::isAreaCheckEnabled() const {
|
||||
return mConfigCheckAreaOfTriangle;
|
||||
}
|
||||
|
||||
} // Namespace Assimp
|
||||
|
||||
#endif // !! AI_FINDDEGENERATESPROCESS_H_INC
|
||||
|
|
|
@ -1499,7 +1499,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
|
|||
|
||||
|
||||
IfcVector3 wall_extrusion;
|
||||
bool do_connections = false, first = true;
|
||||
bool first = true;
|
||||
|
||||
try {
|
||||
|
||||
|
@ -1527,7 +1527,6 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
|
|||
if (first) {
|
||||
first = false;
|
||||
if (dot > 0.f) {
|
||||
do_connections = true;
|
||||
wall_extrusion = t.extrusionDir;
|
||||
if (is_extruded_side) {
|
||||
wall_extrusion = - wall_extrusion;
|
||||
|
@ -1607,44 +1606,6 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
|
|||
old_verts.swap(curmesh.verts);
|
||||
old_vertcnt.swap(curmesh.vertcnt);
|
||||
|
||||
|
||||
// add connection geometry to close the adjacent 'holes' for the openings
|
||||
// this should only be done from one side of the wall or the polygons
|
||||
// would be emitted twice.
|
||||
if (false && do_connections) {
|
||||
|
||||
std::vector<IfcVector3> tmpvec;
|
||||
for(ClipperLib::Polygon& opening : holes_union) {
|
||||
|
||||
ai_assert(ClipperLib::Orientation(opening));
|
||||
|
||||
tmpvec.clear();
|
||||
|
||||
for(ClipperLib::IntPoint& point : opening) {
|
||||
|
||||
tmpvec.push_back( minv * IfcVector3(
|
||||
vmin.x + from_int64(point.X) * vmax.x,
|
||||
vmin.y + from_int64(point.Y) * vmax.y,
|
||||
coord));
|
||||
}
|
||||
|
||||
for(size_t i = 0, size = tmpvec.size(); i < size; ++i) {
|
||||
const size_t next = (i+1)%size;
|
||||
|
||||
curmesh.vertcnt.push_back(4);
|
||||
|
||||
const IfcVector3& in_world = tmpvec[i];
|
||||
const IfcVector3& next_world = tmpvec[next];
|
||||
|
||||
// Assumptions: no 'partial' openings, wall thickness roughly the same across the wall
|
||||
curmesh.verts.push_back(in_world);
|
||||
curmesh.verts.push_back(in_world+wall_extrusion);
|
||||
curmesh.verts.push_back(next_world+wall_extrusion);
|
||||
curmesh.verts.push_back(next_world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector< std::vector<p2t::Point*> > contours;
|
||||
for(ClipperLib::ExPolygon& clip : clipped) {
|
||||
|
||||
|
|
|
@ -394,7 +394,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
|
|||
angles[1] %= 360;
|
||||
angles[2] %= 360;
|
||||
|
||||
if ( bool(angles[0]*angles[1]) && bool(angles[1]*angles[2]) )
|
||||
if ( (angles[0]*angles[1]) != 0 && (angles[1]*angles[2]) != 0 )
|
||||
{
|
||||
FindSuitableMultiple(angles[0]);
|
||||
FindSuitableMultiple(angles[1]);
|
||||
|
|
|
@ -274,10 +274,6 @@ aiReturn Importer::UnregisterLoader(BaseImporter* pImp)
|
|||
|
||||
if (it != pimpl->mImporter.end()) {
|
||||
pimpl->mImporter.erase(it);
|
||||
|
||||
std::set<std::string> st;
|
||||
pImp->GetExtensionList(st);
|
||||
|
||||
DefaultLogger::get()->info("Unregistering custom importer: ");
|
||||
return AI_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -223,6 +223,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
|
|||
iMaxRefTris = std::max(iMaxRefTris,*piCur);
|
||||
}
|
||||
}
|
||||
ai_assert(iMaxRefTris > 0);
|
||||
unsigned int* piCandidates = new unsigned int[iMaxRefTris*3];
|
||||
unsigned int iCacheMisses = 0;
|
||||
|
||||
|
|
|
@ -446,8 +446,6 @@ void AnimResolver::GetKeys(std::vector<aiVectorKey>& out,
|
|||
|
||||
// Iterate through all three arrays at once - it's tricky, but
|
||||
// rather interesting to implement.
|
||||
double lasttime = std::min(envl_x->keys[0].time,std::min(envl_y->keys[0].time,envl_z->keys[0].time));
|
||||
|
||||
cur_x = envl_x->keys.begin();
|
||||
cur_y = envl_y->keys.begin();
|
||||
cur_z = envl_z->keys.begin();
|
||||
|
@ -503,7 +501,7 @@ void AnimResolver::GetKeys(std::vector<aiVectorKey>& out,
|
|||
InterpolateTrack(out,fill,(end_y ? (*cur_x) : (*cur_y)).time);
|
||||
}
|
||||
}
|
||||
lasttime = fill.mTime;
|
||||
double lasttime = fill.mTime;
|
||||
out.push_back(fill);
|
||||
|
||||
if (lasttime >= (*cur_x).time) {
|
||||
|
|
|
@ -483,7 +483,7 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte
|
|||
const LWO::VColorChannel& vc = layer.mVColorChannels[i];
|
||||
|
||||
if (surf.mVCMap == vc.name) {
|
||||
// The vertex color map is explicitely requested by the surface so we need to take special care of it
|
||||
// The vertex color map is explicitly requested by the surface so we need to take special care of it
|
||||
for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) {
|
||||
out[a+1] = out[a];
|
||||
}
|
||||
|
|
|
@ -471,7 +471,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
|
|||
// Determine the exact location of a LWO file
|
||||
std::string LWSImporter::FindLWOFile(const std::string& in)
|
||||
{
|
||||
// insert missing directory seperator if necessary
|
||||
// insert missing directory separator if necessary
|
||||
std::string tmp;
|
||||
if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/')
|
||||
{
|
||||
|
|
|
@ -274,11 +274,9 @@ void MD2Importer::InternReadFile( const std::string& pFile,
|
|||
aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
|
||||
pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
|
||||
|
||||
// navigate to the begin of the frame data
|
||||
BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*)
|
||||
m_pcHeader + m_pcHeader->offsetFrames);
|
||||
|
||||
pcFrame += configFrameID;
|
||||
// navigate to the begin of the current frame data
|
||||
BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*)
|
||||
m_pcHeader + m_pcHeader->offsetFrames + (m_pcHeader->frameSize * configFrameID));
|
||||
|
||||
// navigate to the begin of the triangle data
|
||||
MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*)
|
||||
|
|
|
@ -665,7 +665,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
|
|||
if (0.0f != pcMatIn->Power)
|
||||
{
|
||||
iShadingMode = (int)aiShadingMode_Phong;
|
||||
pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS);
|
||||
// pcMatIn is packed, we can't form pointers to its members
|
||||
float power = pcMatIn->Power;
|
||||
pcMatOut->AddProperty<float>(&power,1,AI_MATKEY_SHININESS);
|
||||
}
|
||||
pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
|
||||
}
|
||||
|
|
|
@ -243,8 +243,6 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
if( !file.get())
|
||||
throw DeadlyImportError( "Failed to open NFF file " + pFile + ".");
|
||||
|
||||
unsigned int m = (unsigned int)file->FileSize();
|
||||
|
||||
// allocate storage and copy the contents of the file to a memory buffer
|
||||
// (terminate it with zero)
|
||||
std::vector<char> mBuffer2;
|
||||
|
@ -469,7 +467,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
for (unsigned int a = 0; a < numIdx;++a)
|
||||
{
|
||||
SkipSpaces(sz,&sz);
|
||||
m = ::strtoul10(sz,&sz);
|
||||
unsigned int m = ::strtoul10(sz,&sz);
|
||||
if (m >= (unsigned int)tempPositions.size())
|
||||
{
|
||||
DefaultLogger::get()->error("NFF2: Vertex index overflow");
|
||||
|
@ -635,7 +633,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
for (std::vector<unsigned int>::const_iterator it = tempIdx.begin(), end = tempIdx.end();
|
||||
it != end;++it)
|
||||
{
|
||||
m = *it;
|
||||
unsigned int m = *it;
|
||||
|
||||
// copy colors -vertex color specifications override polygon color specifications
|
||||
if (hasColor)
|
||||
|
@ -735,7 +733,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
sz = &line[1];out = currentMesh;
|
||||
}
|
||||
SkipSpaces(sz,&sz);
|
||||
m = strtoul10(sz);
|
||||
unsigned int m = strtoul10(sz);
|
||||
|
||||
// ---- flip the face order
|
||||
out->vertices.resize(out->vertices.size()+m);
|
||||
|
@ -1081,7 +1079,9 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
// generate the camera
|
||||
if (hasCam)
|
||||
{
|
||||
aiNode* nd = *ppcChildren = new aiNode();
|
||||
ai_assert(ppcChildren);
|
||||
aiNode* nd = new aiNode();
|
||||
*ppcChildren = nd;
|
||||
nd->mName.Set("<NFF_Camera>");
|
||||
nd->mParent = root;
|
||||
|
||||
|
@ -1105,13 +1105,15 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
// generate light sources
|
||||
if (!lights.empty())
|
||||
{
|
||||
ai_assert(ppcChildren);
|
||||
pScene->mNumLights = (unsigned int)lights.size();
|
||||
pScene->mLights = new aiLight*[pScene->mNumLights];
|
||||
for (unsigned int i = 0; i < pScene->mNumLights;++i,++ppcChildren)
|
||||
{
|
||||
const Light& l = lights[i];
|
||||
|
||||
aiNode* nd = *ppcChildren = new aiNode();
|
||||
aiNode* nd = new aiNode();
|
||||
*ppcChildren = nd;
|
||||
nd->mParent = root;
|
||||
|
||||
nd->mName.length = ::ai_snprintf(nd->mName.data,1024,"<NFF_Light%u>",i);
|
||||
|
@ -1128,7 +1130,8 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
if (!pScene->mNumMeshes)throw DeadlyImportError("NFF: No meshes loaded");
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes];
|
||||
for (it = meshes.begin(), m = 0; it != end;++it)
|
||||
unsigned int m = 0;
|
||||
for (it = meshes.begin(); it != end;++it)
|
||||
{
|
||||
if ((*it).faces.empty())continue;
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ std::string ObjExporter :: GetMaterialLibName()
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::string ObjExporter::GetMaterialLibFileName() {
|
||||
// Remove existing .obj file extention so that the final material file name will be fileName.mtl and not fileName.obj.mtl
|
||||
// Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl
|
||||
size_t lastdot = filename.find_last_of('.');
|
||||
if (lastdot != std::string::npos)
|
||||
return filename.substr(0, lastdot) + MaterialExt;
|
||||
|
@ -258,7 +258,6 @@ void ObjExporter::WriteMaterialFile()
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjExporter::WriteGeometryFile(bool noMtl) {
|
||||
WriteHeader(mOutput);
|
||||
if (!noMtl)
|
||||
|
@ -280,8 +279,10 @@ void ObjExporter::WriteGeometryFile(bool noMtl) {
|
|||
mOutput << "# " << vp.size() << " vertex positions and colors" << endl;
|
||||
size_t colIdx = 0;
|
||||
for ( const aiVector3D& v : vp ) {
|
||||
mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl;
|
||||
colIdx++;
|
||||
if ( colIdx < vc.size() ) {
|
||||
mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl;
|
||||
}
|
||||
++colIdx;
|
||||
}
|
||||
}
|
||||
mOutput << endl;
|
||||
|
|
|
@ -258,7 +258,7 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste
|
|||
ReadTechnique(Trim(techniqueName), ss, material);
|
||||
}
|
||||
|
||||
// Read informations from a custom material
|
||||
// Read information from a custom material
|
||||
/** @todo This "set $x y" does not seem to be a official Ogre material system feature.
|
||||
Materials can inherit other materials and override texture units by using the (unique)
|
||||
parent texture unit name in your cloned material.
|
||||
|
|
|
@ -652,6 +652,8 @@ static void setMatrix( aiNode *node, DataArrayList *transformData ) {
|
|||
i++;
|
||||
}
|
||||
|
||||
ai_assert(i == 16);
|
||||
|
||||
node->mTransformation.a1 = m[ 0 ];
|
||||
node->mTransformation.a2 = m[ 4 ];
|
||||
node->mTransformation.a3 = m[ 8 ];
|
||||
|
|
|
@ -233,10 +233,12 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list<aiNode*>& no
|
|||
|
||||
nd->mNumChildren = static_cast<unsigned int>(child_nodes.size());
|
||||
|
||||
aiNode** tmp = nd->mChildren;
|
||||
for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) {
|
||||
aiNode* node = *tmp++ = *it;
|
||||
node->mParent = nd;
|
||||
if (nd->mChildren) {
|
||||
aiNode** tmp = nd->mChildren;
|
||||
for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) {
|
||||
aiNode* node = *tmp++ = *it;
|
||||
node->mParent = nd;
|
||||
}
|
||||
}
|
||||
|
||||
nodes_out += static_cast<unsigned int>(child_nodes.size());
|
||||
|
|
|
@ -671,7 +671,6 @@ bool PLY::ElementInstanceList::ParseInstanceList(
|
|||
PLYImporter* loader)
|
||||
{
|
||||
ai_assert(NULL != pcElement);
|
||||
const char* pCur = (const char*)&buffer[0];
|
||||
|
||||
// parse all elements
|
||||
if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty())
|
||||
|
@ -683,11 +682,11 @@ bool PLY::ElementInstanceList::ParseInstanceList(
|
|||
PLY::DOM::SkipComments(buffer);
|
||||
PLY::DOM::SkipLine(buffer);
|
||||
streamBuffer.getNextLine(buffer);
|
||||
pCur = (buffer.empty()) ? NULL : (const char*)&buffer[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* pCur = (const char*)&buffer[0];
|
||||
// be sure to have enough storage
|
||||
for (unsigned int i = 0; i < pcElement->NumOccur; ++i)
|
||||
{
|
||||
|
|
|
@ -260,7 +260,7 @@ void RAWImporter::InternReadFile( const std::string& pFile,
|
|||
node = *cc = new aiNode();
|
||||
node->mParent = pScene->mRootNode;
|
||||
}
|
||||
else node = *cc;++cc;
|
||||
else node = *cc;
|
||||
node->mName.Set(outGroup.name);
|
||||
|
||||
// add all meshes
|
||||
|
|
|
@ -145,6 +145,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
|
|||
if (!abReferenced[i]) {
|
||||
++unreferencedRemoved;
|
||||
delete pScene->mMaterials[i];
|
||||
pScene->mMaterials[i] = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -158,6 +159,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
|
|||
me = 0;
|
||||
aiMappingTable[i] = aiMappingTable[a];
|
||||
delete pScene->mMaterials[i];
|
||||
pScene->mMaterials[i] = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -169,6 +171,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
|
|||
// If the new material count differs from the original,
|
||||
// we need to rebuild the material list and remap mesh material indexes.
|
||||
if (iNewNum != pScene->mNumMaterials) {
|
||||
ai_assert(iNewNum > 0);
|
||||
aiMaterial** ppcMaterials = new aiMaterial*[iNewNum];
|
||||
::memset(ppcMaterials,0,sizeof(void*)*iNewNum);
|
||||
for (unsigned int p = 0; p < pScene->mNumMaterials;++p)
|
||||
|
|
|
@ -902,6 +902,7 @@ void SIBImporter::InternReadFile(const std::string& pFile,
|
|||
// Add nodes for each object.
|
||||
for (size_t n=0;n<sib.objs.size();n++)
|
||||
{
|
||||
ai_assert(root->mChildren);
|
||||
SIBObject& obj = sib.objs[n];
|
||||
aiNode* node = new aiNode;
|
||||
root->mChildren[childIdx++] = node;
|
||||
|
@ -926,6 +927,7 @@ void SIBImporter::InternReadFile(const std::string& pFile,
|
|||
// (no transformation as the light is already in world space)
|
||||
for (size_t n=0;n<sib.lights.size();n++)
|
||||
{
|
||||
ai_assert(root->mChildren);
|
||||
aiLight* light = sib.lights[n];
|
||||
if ( nullptr != light ) {
|
||||
aiNode* node = new aiNode;
|
||||
|
|
|
@ -334,7 +334,7 @@ bool STEP::StringToUTF8(std::string& s)
|
|||
size_t j = basei, jend = s.size()-3;
|
||||
|
||||
for (; j < jend; ++j) {
|
||||
if (s[j] == '\\' && s[j] == 'X' && s[j] == '0' && s[j] == '\\') {
|
||||
if (s[j] == '\\' && s[j+1] == 'X' && s[j+2] == '0' && s[j+3] == '\\') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,9 @@ static bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
|
|||
return false;
|
||||
}
|
||||
|
||||
const uint32_t faceCount = *reinterpret_cast<const uint32_t*>(buffer + 80);
|
||||
const char *facecount_pos = buffer + 80;
|
||||
uint32_t faceCount( 0 );
|
||||
::memcpy( &faceCount, facecount_pos, sizeof( uint32_t ) );
|
||||
const uint32_t expectedBinaryFileSize = faceCount * 50 + 84;
|
||||
|
||||
return expectedBinaryFileSize == fileSize;
|
||||
|
@ -200,17 +202,11 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
|||
if (IsBinarySTL(mBuffer, fileSize)) {
|
||||
bMatClr = LoadBinaryFile();
|
||||
} else if (IsAsciiSTL(mBuffer, fileSize)) {
|
||||
LoadASCIIFile();
|
||||
LoadASCIIFile( pScene->mRootNode );
|
||||
} else {
|
||||
throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + ".");
|
||||
}
|
||||
|
||||
// add all created meshes to the single node
|
||||
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
|
||||
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
|
||||
pScene->mRootNode->mMeshes[i] = i;
|
||||
|
||||
// create a single default material, using a white diffuse color for consistency with
|
||||
// other geometric types (e.g., PLY).
|
||||
aiMaterial* pcMat = new aiMaterial();
|
||||
|
@ -231,11 +227,12 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
|
|||
pScene->mMaterials = new aiMaterial*[1];
|
||||
pScene->mMaterials[0] = pcMat;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Read an ASCII STL file
|
||||
void STLImporter::LoadASCIIFile()
|
||||
{
|
||||
void STLImporter::LoadASCIIFile( aiNode *root ) {
|
||||
std::vector<aiMesh*> meshes;
|
||||
std::vector<aiNode*> nodes;
|
||||
const char* sz = mBuffer;
|
||||
const char* bufferEnd = mBuffer + fileSize;
|
||||
std::vector<aiVector3D> positionBuffer;
|
||||
|
@ -247,12 +244,15 @@ void STLImporter::LoadASCIIFile()
|
|||
positionBuffer.reserve(sizeEstimate);
|
||||
normalBuffer.reserve(sizeEstimate);
|
||||
|
||||
while (IsAsciiSTL(sz, static_cast<unsigned int>(bufferEnd - sz)))
|
||||
{
|
||||
while (IsAsciiSTL(sz, static_cast<unsigned int>(bufferEnd - sz))) {
|
||||
std::vector<unsigned int> meshIndices;
|
||||
aiMesh* pMesh = new aiMesh();
|
||||
pMesh->mMaterialIndex = 0;
|
||||
meshIndices.push_back( meshes.size() );
|
||||
meshes.push_back(pMesh);
|
||||
|
||||
aiNode *node = new aiNode;
|
||||
node->mParent = root;
|
||||
nodes.push_back( node );
|
||||
SkipSpaces(&sz);
|
||||
ai_assert(!IsLineEnd(sz));
|
||||
|
||||
|
@ -265,20 +265,21 @@ void STLImporter::LoadASCIIFile()
|
|||
|
||||
size_t temp;
|
||||
// setup the name of the node
|
||||
if ((temp = (size_t)(sz-szMe))) {
|
||||
if ((temp = (size_t)(sz-szMe))) {
|
||||
if (temp >= MAXLEN) {
|
||||
throw DeadlyImportError( "STL: Node name too long" );
|
||||
}
|
||||
|
||||
pScene->mRootNode->mName.length = temp;
|
||||
memcpy(pScene->mRootNode->mName.data,szMe,temp);
|
||||
pScene->mRootNode->mName.data[temp] = '\0';
|
||||
std::string name( szMe, temp );
|
||||
node->mName.Set( name.c_str() );
|
||||
//pScene->mRootNode->mName.length = temp;
|
||||
//memcpy(pScene->mRootNode->mName.data,szMe,temp);
|
||||
//pScene->mRootNode->mName.data[temp] = '\0';
|
||||
} else {
|
||||
pScene->mRootNode->mName.Set("<STL_ASCII>");
|
||||
}
|
||||
else pScene->mRootNode->mName.Set("<STL_ASCII>");
|
||||
|
||||
unsigned int faceVertexCounter = 3;
|
||||
for ( ;; )
|
||||
{
|
||||
for ( ;; ) {
|
||||
// go to the next token
|
||||
if(!SkipSpacesAndLineEnd(&sz))
|
||||
{
|
||||
|
@ -300,9 +301,7 @@ void STLImporter::LoadASCIIFile()
|
|||
SkipSpaces(&sz);
|
||||
if (strncmp(sz,"normal",6)) {
|
||||
DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (sz[6] == '\0') {
|
||||
throw DeadlyImportError("STL: unexpected EOF while parsing facet");
|
||||
}
|
||||
|
@ -316,16 +315,11 @@ void STLImporter::LoadASCIIFile()
|
|||
normalBuffer.push_back(*vn);
|
||||
normalBuffer.push_back(*vn);
|
||||
}
|
||||
}
|
||||
// vertex 1.50000 1.50000 0.00000
|
||||
else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6)))
|
||||
{
|
||||
} else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) { // vertex 1.50000 1.50000 0.00000
|
||||
if (faceVertexCounter >= 3) {
|
||||
DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found");
|
||||
++sz;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (sz[6] == '\0') {
|
||||
throw DeadlyImportError("STL: unexpected EOF while parsing facet");
|
||||
}
|
||||
|
@ -340,17 +334,14 @@ void STLImporter::LoadASCIIFile()
|
|||
sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->z );
|
||||
faceVertexCounter++;
|
||||
}
|
||||
}
|
||||
else if (!::strncmp(sz,"endsolid",8)) {
|
||||
} else if (!::strncmp(sz,"endsolid",8)) {
|
||||
do {
|
||||
++sz;
|
||||
} while (!::IsLineEnd(*sz));
|
||||
SkipSpacesAndLineEnd(&sz);
|
||||
// finished!
|
||||
break;
|
||||
}
|
||||
// else skip the whole identifier
|
||||
else {
|
||||
} else { // else skip the whole identifier
|
||||
do {
|
||||
++sz;
|
||||
} while (!::IsSpaceOrNewLine(*sz));
|
||||
|
@ -380,13 +371,22 @@ void STLImporter::LoadASCIIFile()
|
|||
|
||||
// now copy faces
|
||||
addFacesToMesh(pMesh);
|
||||
|
||||
// assign the meshes to the current node
|
||||
pushMeshesToNode( meshIndices, node );
|
||||
}
|
||||
|
||||
// now add the loaded meshes
|
||||
pScene->mNumMeshes = (unsigned int)meshes.size();
|
||||
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
||||
for (size_t i = 0; i < meshes.size(); i++)
|
||||
{
|
||||
pScene->mMeshes[i] = meshes[i];
|
||||
for (size_t i = 0; i < meshes.size(); i++) {
|
||||
pScene->mMeshes[ i ] = meshes[i];
|
||||
}
|
||||
|
||||
root->mNumChildren = nodes.size();
|
||||
root->mChildren = new aiNode*[ root->mNumChildren ];
|
||||
for ( size_t i=0; i<nodes.size(); ++i ) {
|
||||
root->mChildren[ i ] = nodes[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,4 +513,18 @@ bool STLImporter::LoadBinaryFile()
|
|||
return false;
|
||||
}
|
||||
|
||||
void STLImporter::pushMeshesToNode( std::vector<unsigned int> &meshIndices, aiNode *node ) {
|
||||
ai_assert( nullptr != node );
|
||||
if ( meshIndices.empty() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
node->mNumMeshes = static_cast<unsigned int>( meshIndices.size() );
|
||||
node->mMeshes = new unsigned int[ meshIndices.size() ];
|
||||
for ( size_t i=0; i<meshIndices.size(); ++i ) {
|
||||
node->mMeshes[ i ] = meshIndices[ i ];
|
||||
}
|
||||
meshIndices.clear();
|
||||
}
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_STL_IMPORTER
|
||||
|
|
|
@ -48,53 +48,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "BaseImporter.h"
|
||||
#include <assimp/types.h>
|
||||
|
||||
namespace Assimp {
|
||||
// Forward declarations
|
||||
struct aiNode;
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Importer class for the sterolithography STL file format
|
||||
*/
|
||||
class STLImporter : public BaseImporter
|
||||
{
|
||||
/**
|
||||
* @brief Importer class for the sterolithography STL file format.
|
||||
*/
|
||||
class STLImporter : public BaseImporter {
|
||||
public:
|
||||
/**
|
||||
* @brief STLImporter, the class default constructor.
|
||||
*/
|
||||
STLImporter();
|
||||
|
||||
/**
|
||||
* @brief The class destructor.
|
||||
*/
|
||||
~STLImporter();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the class can handle the format of the given file.
|
||||
* See BaseImporter::CanRead() for details.
|
||||
/**
|
||||
* @brief Returns whether the class can handle the format of the given file.
|
||||
* See BaseImporter::CanRead() for details.
|
||||
*/
|
||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
|
||||
bool checkSig) const;
|
||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Return importer meta information.
|
||||
* See #BaseImporter::GetInfo for the details
|
||||
/**
|
||||
* @brief Return importer meta information.
|
||||
* See #BaseImporter::GetInfo for the details
|
||||
*/
|
||||
const aiImporterDesc* GetInfo () const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Imports the given file into the given scene structure.
|
||||
/**
|
||||
* @brief Imports the given file into the given scene structure.
|
||||
* See BaseImporter::InternReadFile() for details
|
||||
*/
|
||||
void InternReadFile( const std::string& pFile, aiScene* pScene,
|
||||
IOSystem* pIOHandler);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads a binary .stl file
|
||||
/**
|
||||
* @brief Loads a binary .stl file
|
||||
* @return true if the default vertex color must be used as material color
|
||||
*/
|
||||
*/
|
||||
bool LoadBinaryFile();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads a ASCII text .stl file
|
||||
*/
|
||||
void LoadASCIIFile();
|
||||
/**
|
||||
* @brief Loads a ASCII text .stl file
|
||||
*/
|
||||
void LoadASCIIFile( aiNode *root );
|
||||
|
||||
void pushMeshesToNode( std::vector<unsigned int> &meshIndices, aiNode *node );
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -40,10 +40,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
/** @file Defines a helper class to evaluate subdivision surfaces.*/
|
||||
#pragma once
|
||||
#ifndef AI_SUBDISIVION_H_INC
|
||||
#define AI_SUBDISIVION_H_INC
|
||||
|
||||
#include <cstddef>
|
||||
#include <assimp/types.h>
|
||||
|
||||
struct aiMesh;
|
||||
|
||||
namespace Assimp {
|
||||
|
@ -52,8 +55,7 @@ namespace Assimp {
|
|||
/** Helper class to evaluate subdivision surfaces. Different algorithms
|
||||
* are provided for choice. */
|
||||
// ------------------------------------------------------------------------------
|
||||
class Subdivider
|
||||
{
|
||||
class ASSIMP_API Subdivider {
|
||||
public:
|
||||
|
||||
/** Enumerates all supported subvidision algorithms */
|
||||
|
@ -61,12 +63,7 @@ public:
|
|||
CATMULL_CLARKE = 0x1
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Subdivider() {
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~Subdivider();
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
/** Create a subdivider of a specific type
|
||||
|
@ -119,9 +116,13 @@ public:
|
|||
unsigned int num,
|
||||
bool discard_input = false) = 0;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
inline
|
||||
Subdivider::~Subdivider() {
|
||||
// empty
|
||||
}
|
||||
|
||||
} // end namespace Assimp
|
||||
|
||||
|
||||
|
|
|
@ -141,9 +141,6 @@ void TerragenImporter::InternReadFile( const std::string& pFile,
|
|||
throw DeadlyImportError( "TER: Magic string \'TERRAIN\' not found" );
|
||||
|
||||
unsigned int x = 0,y = 0,mode = 0;
|
||||
float rad = 6370.f;
|
||||
(void)rad;
|
||||
|
||||
|
||||
aiNode* root = pScene->mRootNode = new aiNode();
|
||||
root->mName.Set("<TERRAGEN.TERRAIN>");
|
||||
|
@ -187,7 +184,7 @@ void TerragenImporter::InternReadFile( const std::string& pFile,
|
|||
// mapping == 1: earth radius
|
||||
else if (!::strncmp(head,AI_TERR_CHUNK_CRAD,4))
|
||||
{
|
||||
rad = reader.GetF4();
|
||||
reader.GetF4();
|
||||
}
|
||||
// mapping mode
|
||||
else if (!::strncmp(head,AI_TERR_CHUNK_CRVM,4))
|
||||
|
|
|
@ -317,7 +317,7 @@ void TextureTransformStep::Execute( aiScene* pScene)
|
|||
info.lockedPos = AI_TT_UV_IDX_LOCK_TBD;
|
||||
}
|
||||
|
||||
// Get all coresponding meshes
|
||||
// Get all corresponding meshes
|
||||
for (unsigned int n = 0; n < pScene->mNumMeshes;++n) {
|
||||
aiMesh* mesh = pScene->mMeshes[n];
|
||||
if (mesh->mMaterialIndex != i || !mesh->mTextureCoords[0])
|
||||
|
|
|
@ -334,28 +334,28 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
|||
case 1:
|
||||
if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT))
|
||||
{
|
||||
ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimtiveTypes "
|
||||
ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimitiveTypes "
|
||||
"does not report the POINT flag",i);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_LINE))
|
||||
{
|
||||
ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimtiveTypes "
|
||||
ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimitiveTypes "
|
||||
"does not report the LINE flag",i);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE))
|
||||
{
|
||||
ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimtiveTypes "
|
||||
ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimitiveTypes "
|
||||
"does not report the TRIANGLE flag",i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON))
|
||||
{
|
||||
this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimtiveTypes "
|
||||
this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimitiveTypes "
|
||||
"does not report the POLYGON flag",i);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -91,7 +91,7 @@ protected:
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
/** Report a validation warning. This won't throw an exception,
|
||||
* control will return to the callera.
|
||||
* control will return to the caller.
|
||||
* @param msg Format string for sprintf().*/
|
||||
void ReportWarning(const char* msg,...);
|
||||
|
||||
|
|
|
@ -240,8 +240,12 @@ list<SAttribute> attr_list;
|
|||
if((rotate_angle != 0) && (rotate_axis.Length() > 0))
|
||||
attr_list.push_back({"rotation", Rotation2String(rotate_axis, rotate_angle)});
|
||||
|
||||
if(!scale.Equal({1, 1, 1})) attr_list.push_back({"scale", Vector2String(scale)});
|
||||
if(translate.Length() > 0) attr_list.push_back({"translation", Vector2String(translate)});
|
||||
if(!scale.Equal({1.0,1.0,1.0})) {
|
||||
attr_list.push_back({"scale", Vector2String(scale)});
|
||||
}
|
||||
if(translate.Length() > 0) {
|
||||
attr_list.push_back({"translation", Vector2String(translate)});
|
||||
}
|
||||
}
|
||||
|
||||
// Begin node if need.
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace Assimp
|
|||
///
|
||||
/// Pay attention that X3D is format for interactive graphic and simulations for web browsers. aiScene can not contain all features of the X3D format.
|
||||
/// Also, aiScene contain rasterized-like data. For example, X3D can describe circle all cylinder with one tag, but aiScene contain result of tesselation:
|
||||
/// vertices, faces etc. Yes, you can use algorithm for detecting figures or shapes, but thats not good idea at all.
|
||||
/// vertices, faces etc. Yes, you can use algorithm for detecting figures or shapes, but that's not a good idea at all.
|
||||
///
|
||||
/// Supported nodes:
|
||||
/// Core component:
|
||||
|
@ -96,7 +96,7 @@ private:
|
|||
aiMatrix4x4 Matrix_GlobalToCurrent(const aiNode& pNode) const;
|
||||
|
||||
/// \fn void AttrHelper_CommaToPoint(std::string& pStringWithComma)
|
||||
/// Convert commas in string to points. Thats need because "std::to_string" result depend on locale (regional settings).
|
||||
/// Convert commas in string to points. That's needed because "std::to_string" result depends on locale (regional settings).
|
||||
/// \param [in, out] pStringWithComma - reference to string, which must be modified.
|
||||
void AttrHelper_CommaToPoint(std::string& pStringWithComma) { for(char& c: pStringWithComma) { if(c == ',') c = '.'; } }
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@ namespace Assimp {
|
|||
/// Ignored attributes: "creaseAngle", "convex", "solid".
|
||||
///
|
||||
/// Texture coordinates generating: only for Sphere, Cone, Cylinder. In all other case used PLANE mapping.
|
||||
/// It's better that Assimp main code has powerfull texture coordinates generator. Then is not needed to
|
||||
/// It's better that Assimp main code has powerful texture coordinates generator. Then is not needed to
|
||||
/// duplicate this code in every importer.
|
||||
///
|
||||
/// Lighting limitations.
|
||||
|
@ -401,10 +401,10 @@ private:
|
|||
/************** Functions: XML set *************/
|
||||
/***********************************************/
|
||||
|
||||
/// Chek if current node is empty: <node />. If not then exception will throwed.
|
||||
/// Check if current node is empty: <node />. If not then exception will throwed.
|
||||
void XML_CheckNode_MustBeEmpty();
|
||||
|
||||
/// Chek if current node name is equal to pNodeName.
|
||||
/// Check if current node name is equal to pNodeName.
|
||||
/// \param [in] pNodeName - name for checking.
|
||||
/// return true if current node name is equal to pNodeName, else - false.
|
||||
bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }
|
||||
|
|
|
@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "X3DImporter.hpp"
|
||||
|
||||
// Header files, Assimp.
|
||||
#include <assimp/ai_assert.h>
|
||||
#include "StandardShapes.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
|
@ -357,6 +358,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
|
|||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
ai_assert(*pMesh);
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
|
@ -389,6 +391,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
|
|||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
ai_assert(*pMesh);
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
|
@ -446,6 +449,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
|
|||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
ai_assert(*pMesh);
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
|
@ -475,6 +479,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
|
|||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
ai_assert(*pMesh);
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
|
@ -550,6 +555,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
|
|||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
ai_assert(*pMesh);
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
|
@ -584,6 +590,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
|
|||
// copy additional information from children
|
||||
for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
|
||||
{
|
||||
ai_assert(*pMesh);
|
||||
if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
|
||||
MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA)
|
||||
|
|
|
@ -65,14 +65,11 @@ struct Node;
|
|||
/** The XFileImporter is a worker class capable of importing a scene from a
|
||||
* DirectX file .x
|
||||
*/
|
||||
class XFileImporter : public BaseImporter
|
||||
{
|
||||
class XFileImporter : public BaseImporter {
|
||||
public:
|
||||
XFileImporter();
|
||||
~XFileImporter();
|
||||
|
||||
|
||||
public:
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the class can handle the format of the given file.
|
||||
* See BaseImporter::CanRead() for details. */
|
||||
|
|
|
@ -360,7 +360,7 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma
|
|||
// The same but more human.
|
||||
inline ai_real fast_atof(const char* c)
|
||||
{
|
||||
ai_real ret;
|
||||
ai_real ret(0.0);
|
||||
fast_atoreal_move<ai_real>(c, ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -368,7 +368,7 @@ inline ai_real fast_atof(const char* c)
|
|||
|
||||
inline ai_real fast_atof( const char* c, const char** cout)
|
||||
{
|
||||
ai_real ret;
|
||||
ai_real ret(0.0);
|
||||
*cout = fast_atoreal_move<ai_real>(c, ret);
|
||||
|
||||
return ret;
|
||||
|
@ -376,7 +376,7 @@ inline ai_real fast_atof( const char* c, const char** cout)
|
|||
|
||||
inline ai_real fast_atof( const char** inout)
|
||||
{
|
||||
ai_real ret;
|
||||
ai_real ret(0.0);
|
||||
*inout = fast_atoreal_move<ai_real>(*inout, ret);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -88,6 +88,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#include "StringUtils.h"
|
||||
|
||||
namespace glTF2
|
||||
{
|
||||
#ifdef ASSIMP_API
|
||||
|
@ -190,15 +192,31 @@ namespace glTF2
|
|||
#include "./../include/assimp/Compiler/pushpack1.h"
|
||||
#endif
|
||||
|
||||
//! For binary .glb files
|
||||
//! 12-byte header (+ the JSON + a "body" data section)
|
||||
struct GLB_Header
|
||||
{
|
||||
uint8_t magic[4]; //!< Magic number: "glTF"
|
||||
uint32_t version; //!< Version number (always 2 as of the last update)
|
||||
uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes
|
||||
} PACK_STRUCT;
|
||||
|
||||
struct GLB_Chunk
|
||||
{
|
||||
uint32_t chunkLength;
|
||||
uint32_t chunkType;
|
||||
} PACK_STRUCT;
|
||||
|
||||
#ifdef ASSIMP_API
|
||||
#include "./../include/assimp/Compiler/poppack1.h"
|
||||
#endif
|
||||
|
||||
|
||||
//! Values for the GLB_Header::sceneFormat field
|
||||
enum SceneFormat
|
||||
//! Values for the GLB_Chunk::chunkType field
|
||||
enum ChunkType
|
||||
{
|
||||
SceneFormat_JSON = 0
|
||||
ChunkType_JSON = 0x4E4F534A,
|
||||
ChunkType_BIN = 0x004E4942
|
||||
};
|
||||
|
||||
//! Values for the mesh primitive modes
|
||||
|
@ -239,7 +257,7 @@ namespace glTF2
|
|||
case ComponentType_UNSIGNED_BYTE:
|
||||
return 1;
|
||||
default:
|
||||
throw DeadlyImportError("GLTF: Unsupported Component Type " + std::to_string(t));
|
||||
throw DeadlyImportError("GLTF: Unsupported Component Type " + to_string(t));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,7 +436,6 @@ namespace glTF2
|
|||
{
|
||||
Ref<BufferView> bufferView; //!< The ID of the bufferView. (required)
|
||||
unsigned int byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required)
|
||||
unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0)
|
||||
ComponentType componentType; //!< The datatype of components in the attribute. (required)
|
||||
unsigned int count; //!< The number of attributes referenced by this accessor. (required)
|
||||
AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
|
||||
|
@ -609,6 +626,7 @@ namespace glTF2
|
|||
Ref<Buffer> buffer; //! The ID of the buffer. (required)
|
||||
size_t byteOffset; //! The offset into the buffer in bytes. (required)
|
||||
size_t byteLength; //! The length of the bufferView in bytes. (default: 0)
|
||||
unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0)
|
||||
|
||||
BufferViewTarget target; //! The target that the WebGL buffer should be bound to.
|
||||
|
||||
|
@ -971,6 +989,8 @@ namespace glTF2
|
|||
Ref<T> Create(const std::string& id)
|
||||
{ return Create(id.c_str()); }
|
||||
|
||||
unsigned int Remove(const char* id);
|
||||
|
||||
inline unsigned int Size() const
|
||||
{ return unsigned(mObjs.size()); }
|
||||
|
||||
|
@ -1082,7 +1102,10 @@ namespace glTF2
|
|||
}
|
||||
|
||||
//! Main function
|
||||
void Load(const std::string& file);
|
||||
void Load(const std::string& file, bool isBinary = false);
|
||||
|
||||
//! Enables binary encoding on the asset
|
||||
void SetAsBinary();
|
||||
|
||||
//! Search for an available name, starting from the given strings
|
||||
std::string FindUniqueID(const std::string& str, const char* suffix);
|
||||
|
@ -1091,6 +1114,8 @@ namespace glTF2
|
|||
{ return mBodyBuffer; }
|
||||
|
||||
private:
|
||||
void ReadBinaryHeader(IOStream& stream, std::vector<char>& sceneData);
|
||||
|
||||
void ReadExtensionsUsed(Document& doc);
|
||||
|
||||
IOStream* OpenFile(std::string path, const char* mode, bool absolute = false);
|
||||
|
|
|
@ -193,6 +193,50 @@ inline void LazyDict<T>::DetachFromDocument()
|
|||
mDict = 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
unsigned int LazyDict<T>::Remove(const char* id)
|
||||
{
|
||||
id = T::TranslateId(mAsset, id);
|
||||
|
||||
typename IdDict::iterator it = mObjsById.find(id);
|
||||
|
||||
if (it == mObjsById.end()) {
|
||||
throw DeadlyExportError("GLTF: Object with id \"" + std::string(id) + "\" is not found");
|
||||
}
|
||||
|
||||
const unsigned int index = it->second;
|
||||
|
||||
mAsset.mUsedIds[id] = false;
|
||||
mObjsById.erase(id);
|
||||
mObjsByOIndex.erase(index);
|
||||
mObjs.erase(mObjs.begin() + index);
|
||||
|
||||
//update index of object in mObjs;
|
||||
for (size_t i = index; i < mObjs.size(); ++i) {
|
||||
T *obj = mObjs[i];
|
||||
|
||||
obj->index = i;
|
||||
}
|
||||
|
||||
for (IdDict::iterator it = mObjsById.begin(); it != mObjsById.end(); ++it) {
|
||||
if (it->second <= index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mObjsById[it->first] = it->second - 1;
|
||||
}
|
||||
|
||||
for (Dict::iterator it = mObjsByOIndex.begin(); it != mObjsByOIndex.end(); ++it) {
|
||||
if (it->second <= index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mObjsByOIndex[it->first] = it->second - 1;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Ref<T> LazyDict<T>::Retrieve(unsigned int i)
|
||||
{
|
||||
|
@ -214,11 +258,11 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i)
|
|||
Value &obj = (*mDict)[i];
|
||||
|
||||
if (!obj.IsObject()) {
|
||||
throw DeadlyImportError("GLTF: Object at index \"" + std::to_string(i) + "\" is not a JSON object");
|
||||
throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object");
|
||||
}
|
||||
|
||||
T* inst = new T();
|
||||
inst->id = std::string(mDictId) + "_" + std::to_string(i);
|
||||
inst->id = std::string(mDictId) + "_" + to_string(i);
|
||||
inst->oIndex = i;
|
||||
ReadMember(obj, "name", inst->name);
|
||||
inst->Read(obj, mAsset);
|
||||
|
@ -468,6 +512,7 @@ inline void BufferView::Read(Value& obj, Asset& r)
|
|||
|
||||
byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
|
||||
byteLength = MemberOrDefault(obj, "byteLength", 0u);
|
||||
byteStride = MemberOrDefault(obj, "byteStride", 0u);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -482,7 +527,6 @@ inline void Accessor::Read(Value& obj, Asset& r)
|
|||
}
|
||||
|
||||
byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
|
||||
byteStride = MemberOrDefault(obj, "byteStride", 0u);
|
||||
componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
|
||||
count = MemberOrDefault(obj, "count", 0u);
|
||||
|
||||
|
@ -557,7 +601,7 @@ bool Accessor::ExtractData(T*& outData)
|
|||
const size_t elemSize = GetElementSize();
|
||||
const size_t totalSize = elemSize * count;
|
||||
|
||||
const size_t stride = byteStride ? byteStride : elemSize;
|
||||
const size_t stride = bufferView && bufferView->byteStride ? bufferView->byteStride : elemSize;
|
||||
|
||||
const size_t targetElemSize = sizeof(T);
|
||||
ai_assert(elemSize <= targetElemSize);
|
||||
|
@ -597,7 +641,7 @@ inline Accessor::Indexer::Indexer(Accessor& acc)
|
|||
: accessor(acc)
|
||||
, data(acc.GetPointer())
|
||||
, elemSize(acc.GetElementSize())
|
||||
, stride(acc.byteStride ? acc.byteStride : elemSize)
|
||||
, stride(acc.bufferView && acc.bufferView->byteStride ? acc.bufferView->byteStride : elemSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -993,7 +1037,72 @@ inline void AssetMetadata::Read(Document& doc)
|
|||
// Asset methods implementation
|
||||
//
|
||||
|
||||
inline void Asset::Load(const std::string& pFile)
|
||||
inline void Asset::ReadBinaryHeader(IOStream& stream, std::vector<char>& sceneData)
|
||||
{
|
||||
GLB_Header header;
|
||||
if (stream.Read(&header, sizeof(header), 1) != 1) {
|
||||
throw DeadlyImportError("GLTF: Unable to read the file header");
|
||||
}
|
||||
|
||||
if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) {
|
||||
throw DeadlyImportError("GLTF: Invalid binary glTF file");
|
||||
}
|
||||
|
||||
AI_SWAP4(header.version);
|
||||
asset.version = to_string(header.version);
|
||||
if (header.version != 2) {
|
||||
throw DeadlyImportError("GLTF: Unsupported binary glTF version");
|
||||
}
|
||||
|
||||
GLB_Chunk chunk;
|
||||
if (stream.Read(&chunk, sizeof(chunk), 1) != 1) {
|
||||
throw DeadlyImportError("GLTF: Unable to read JSON chunk");
|
||||
}
|
||||
|
||||
AI_SWAP4(chunk.chunkLength);
|
||||
AI_SWAP4(chunk.chunkType);
|
||||
|
||||
if (chunk.chunkType != ChunkType_JSON) {
|
||||
throw DeadlyImportError("GLTF: JSON chunk missing");
|
||||
}
|
||||
|
||||
// read the scene data
|
||||
|
||||
mSceneLength = chunk.chunkLength;
|
||||
sceneData.resize(mSceneLength + 1);
|
||||
sceneData[mSceneLength] = '\0';
|
||||
|
||||
if (stream.Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
|
||||
throw DeadlyImportError("GLTF: Could not read the file contents");
|
||||
}
|
||||
|
||||
uint32_t padding = ((chunk.chunkLength + 3) & ~3) - chunk.chunkLength;
|
||||
if (padding > 0) {
|
||||
stream.Seek(padding, aiOrigin_CUR);
|
||||
}
|
||||
|
||||
AI_SWAP4(header.length);
|
||||
mBodyOffset = 12 + 8 + chunk.chunkLength + padding + 8;
|
||||
if (header.length >= mBodyOffset) {
|
||||
if (stream.Read(&chunk, sizeof(chunk), 1) != 1) {
|
||||
throw DeadlyImportError("GLTF: Unable to read BIN chunk");
|
||||
}
|
||||
|
||||
AI_SWAP4(chunk.chunkLength);
|
||||
AI_SWAP4(chunk.chunkType);
|
||||
|
||||
if (chunk.chunkType != ChunkType_BIN) {
|
||||
throw DeadlyImportError("GLTF: BIN chunk missing");
|
||||
}
|
||||
|
||||
mBodyLength = chunk.chunkLength;
|
||||
}
|
||||
else {
|
||||
mBodyOffset = mBodyLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Asset::Load(const std::string& pFile, bool isBinary)
|
||||
{
|
||||
mCurrentAssetDir.clear();
|
||||
int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\')));
|
||||
|
@ -1004,16 +1113,25 @@ inline void Asset::Load(const std::string& pFile)
|
|||
throw DeadlyImportError("GLTF: Could not open file for reading");
|
||||
}
|
||||
|
||||
mSceneLength = stream->FileSize();
|
||||
mBodyLength = 0;
|
||||
// is binary? then read the header
|
||||
std::vector<char> sceneData;
|
||||
if (isBinary) {
|
||||
SetAsBinary(); // also creates the body buffer
|
||||
ReadBinaryHeader(*stream, sceneData);
|
||||
}
|
||||
else {
|
||||
mSceneLength = stream->FileSize();
|
||||
mBodyLength = 0;
|
||||
|
||||
// read the scene data
|
||||
|
||||
std::vector<char> sceneData(mSceneLength + 1);
|
||||
sceneData[mSceneLength] = '\0';
|
||||
// read the scene data
|
||||
|
||||
if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
|
||||
throw DeadlyImportError("GLTF: Could not read the file contents");
|
||||
sceneData.resize(mSceneLength + 1);
|
||||
sceneData[mSceneLength] = '\0';
|
||||
|
||||
if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) {
|
||||
throw DeadlyImportError("GLTF: Could not read the file contents");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1066,6 +1184,15 @@ inline void Asset::Load(const std::string& pFile)
|
|||
}
|
||||
}
|
||||
|
||||
inline void Asset::SetAsBinary()
|
||||
{
|
||||
if (!mBodyBuffer) {
|
||||
mBodyBuffer = buffers.Create("binary_glTF");
|
||||
mBodyBuffer->MarkAsSpecial();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void Asset::ReadExtensionsUsed(Document& doc)
|
||||
{
|
||||
Value* extsUsed = FindArray(doc, "extensionsUsed");
|
||||
|
|
|
@ -98,10 +98,6 @@ namespace glTF2 {
|
|||
obj.AddMember("bufferView", a.bufferView->index, w.mAl);
|
||||
obj.AddMember("byteOffset", a.byteOffset, w.mAl);
|
||||
|
||||
if (a.byteStride != 0) {
|
||||
obj.AddMember("byteStride", a.byteStride, w.mAl);
|
||||
}
|
||||
|
||||
obj.AddMember("componentType", int(a.componentType), w.mAl);
|
||||
obj.AddMember("count", a.count, w.mAl);
|
||||
obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);
|
||||
|
@ -168,6 +164,9 @@ namespace glTF2 {
|
|||
obj.AddMember("buffer", bv.buffer->index, w.mAl);
|
||||
obj.AddMember("byteOffset", static_cast<uint64_t>(bv.byteOffset), w.mAl);
|
||||
obj.AddMember("byteLength", static_cast<uint64_t>(bv.byteLength), w.mAl);
|
||||
if (bv.byteStride != 0) {
|
||||
obj.AddMember("byteStride", bv.byteStride, w.mAl);
|
||||
}
|
||||
obj.AddMember("target", int(bv.target), w.mAl);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/material.h>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
// Header files, standart library.
|
||||
// Header files, standard library.
|
||||
#include <memory>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
@ -170,13 +170,13 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
|
|||
bv->buffer = buffer;
|
||||
bv->byteOffset = unsigned(offset);
|
||||
bv->byteLength = length; //! The target that the WebGL buffer should be bound to.
|
||||
bv->byteStride = 0;
|
||||
bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER;
|
||||
|
||||
// accessor
|
||||
Ref<Accessor> acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor"));
|
||||
acc->bufferView = bv;
|
||||
acc->byteOffset = 0;
|
||||
acc->byteStride = 0;
|
||||
acc->componentType = compType;
|
||||
acc->count = count;
|
||||
acc->type = typeOut;
|
||||
|
@ -402,7 +402,7 @@ void glTF2Exporter::ExportMaterials()
|
|||
for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
|
||||
const aiMaterial* mat = mScene->mMaterials[i];
|
||||
|
||||
std::string id = "material_" + std::to_string(i);
|
||||
std::string id = "material_" + to_string(i);
|
||||
|
||||
Ref<Material> m = mAsset->materials.Create(id);
|
||||
|
||||
|
@ -800,9 +800,33 @@ void glTF2Exporter::MergeMeshes()
|
|||
for (unsigned int m = nMeshes - 1; m >= 1; --m) {
|
||||
Ref<Mesh> mesh = node->meshes.at(m);
|
||||
|
||||
firstMesh->primitives.insert(firstMesh->primitives.end(), mesh->primitives.begin(), mesh->primitives.end());
|
||||
//append this mesh's primitives to the first mesh's primitives
|
||||
firstMesh->primitives.insert(
|
||||
firstMesh->primitives.end(),
|
||||
mesh->primitives.begin(),
|
||||
mesh->primitives.end()
|
||||
);
|
||||
|
||||
node->meshes.erase(node->meshes.begin() + m);
|
||||
//remove the mesh from the list of meshes
|
||||
unsigned int removedIndex = mAsset->meshes.Remove(mesh->id.c_str());
|
||||
|
||||
//find the presence of the removed mesh in other nodes
|
||||
for (unsigned int nn = 0; nn < mAsset->nodes.Size(); ++nn) {
|
||||
Ref<Node> node = mAsset->nodes.Get(nn);
|
||||
|
||||
for (unsigned int mm = 0; mm < node->meshes.size(); ++mm) {
|
||||
Ref<Mesh>& meshRef = node->meshes.at(mm);
|
||||
unsigned int meshIndex = meshRef.GetIndex();
|
||||
|
||||
if (meshIndex == removedIndex) {
|
||||
node->meshes.erase(node->meshes.begin() + mm);
|
||||
} else if (meshIndex > removedIndex) {
|
||||
Ref<Mesh> newMeshRef = mAsset->meshes.Get(meshIndex - 1);
|
||||
|
||||
meshRef = newMeshRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//since we were looping backwards, reverse the order of merged primitives to their original order
|
||||
|
|
|
@ -74,7 +74,7 @@ static const aiImporterDesc desc = {
|
|||
"",
|
||||
"",
|
||||
"",
|
||||
aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
|
||||
aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@ -103,13 +103,13 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool
|
|||
{
|
||||
const std::string &extension = GetExtension(pFile);
|
||||
|
||||
if (extension != "gltf") // We currently can't read glTF2 binary files (.glb), yet
|
||||
if (extension != "gltf" && extension != "glb")
|
||||
return false;
|
||||
|
||||
if (checkSig && pIOHandler) {
|
||||
glTF2::Asset asset(pIOHandler);
|
||||
try {
|
||||
asset.Load(pFile);
|
||||
asset.Load(pFile, extension == "glb");
|
||||
std::string version = asset.asset.version;
|
||||
return !version.empty() && version[0] == '2';
|
||||
} catch (...) {
|
||||
|
@ -639,7 +639,7 @@ void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IO
|
|||
|
||||
// read the asset file
|
||||
glTF2::Asset asset(pIOHandler);
|
||||
asset.Load(pFile);
|
||||
asset.Load(pFile, GetExtension(pFile) == "glb");
|
||||
|
||||
//
|
||||
// Copy the data out
|
||||
|
|
|
@ -1282,7 +1282,7 @@ inline void Asset::ReadBinaryHeader(IOStream& stream)
|
|||
}
|
||||
|
||||
AI_SWAP4(header.version);
|
||||
asset.version = std::to_string(header.version);
|
||||
asset.version = to_string(header.version);
|
||||
if (header.version != 1) {
|
||||
throw DeadlyImportError("GLTF: Unsupported binary glTF version");
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/material.h>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
// Header files, standart library.
|
||||
// Header files, standard library.
|
||||
#include <memory>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
|
|
@ -820,6 +820,7 @@ namespace o3dgc
|
|||
for (unsigned n = 0; n < data_symbols; n++)
|
||||
total_count += (symbol_count[n] = (symbol_count[n] + 1) >> 1);
|
||||
}
|
||||
assert(total_count > 0);
|
||||
// compute cumulative distribution, decoder table
|
||||
unsigned k, sum = 0, s = 0;
|
||||
unsigned scale = 0x80000000U / total_count;
|
||||
|
@ -830,6 +831,7 @@ namespace o3dgc
|
|||
sum += symbol_count[k];
|
||||
}
|
||||
else {
|
||||
assert(decoder_table);
|
||||
for (k = 0; k < data_symbols; k++) {
|
||||
distribution[k] = (scale * sum) >> (31 - DM__LengthShift);
|
||||
sum += symbol_count[k];
|
||||
|
|
|
@ -231,7 +231,8 @@ namespace o3dgc
|
|||
float ReadFloat32Bin(unsigned long & position) const
|
||||
{
|
||||
unsigned long value = ReadUInt32Bin(position);
|
||||
float fvalue = *((float *)(&value));
|
||||
float fvalue;
|
||||
memcpy(&fvalue, &value, 4);
|
||||
return fvalue;
|
||||
}
|
||||
unsigned long ReadUInt32Bin(unsigned long & position) const
|
||||
|
@ -261,7 +262,8 @@ namespace o3dgc
|
|||
|
||||
void WriteFloat32ASCII(float value)
|
||||
{
|
||||
unsigned long uiValue = *((unsigned long *)(&value));
|
||||
unsigned long uiValue;
|
||||
memcpy(&uiValue, &value, 4);
|
||||
WriteUInt32ASCII(uiValue);
|
||||
}
|
||||
void WriteUInt32ASCII(unsigned long position, unsigned long value)
|
||||
|
@ -314,7 +316,8 @@ namespace o3dgc
|
|||
float ReadFloat32ASCII(unsigned long & position) const
|
||||
{
|
||||
unsigned long value = ReadUInt32ASCII(position);
|
||||
float fvalue = *((float *)(&value));
|
||||
float fvalue;
|
||||
memcpy(&fvalue, &value, 4);
|
||||
return fvalue;
|
||||
}
|
||||
unsigned long ReadUInt32ASCII(unsigned long & position) const
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
# Copyright (c) 2014, Pavel Rojtberg
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Usage:
|
||||
# 1. place AndroidNdkGdb.cmake somewhere inside ${CMAKE_MODULE_PATH}
|
||||
# 2. inside your project add
|
||||
#
|
||||
# include(AndroidNdkGdb)
|
||||
# android_ndk_gdb_enable()
|
||||
# # for each target
|
||||
# add_library(MyLibrary ...)
|
||||
# android_ndk_gdb_debuggable(MyLibrary)
|
||||
|
||||
|
||||
# add gdbserver and general gdb configuration to project
|
||||
# also create a mininal NDK skeleton so ndk-gdb finds the paths
|
||||
#
|
||||
# the optional parameter defines the path to the android project.
|
||||
# uses PROJECT_SOURCE_DIR by default.
|
||||
macro(android_ndk_gdb_enable)
|
||||
if(ANDROID)
|
||||
# create custom target that depends on the real target so it gets executed afterwards
|
||||
add_custom_target(NDK_GDB ALL)
|
||||
|
||||
if(${ARGC})
|
||||
set(ANDROID_PROJECT_DIR ${ARGV0})
|
||||
else()
|
||||
set(ANDROID_PROJECT_DIR ${PROJECT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
set(NDK_GDB_SOLIB_PATH ${ANDROID_PROJECT_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/)
|
||||
file(MAKE_DIRECTORY ${NDK_GDB_SOLIB_PATH})
|
||||
|
||||
# 1. generate essential Android Makefiles
|
||||
file(MAKE_DIRECTORY ${ANDROID_PROJECT_DIR}/jni)
|
||||
if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Android.mk)
|
||||
file(WRITE ${ANDROID_PROJECT_DIR}/jni/Android.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
|
||||
endif()
|
||||
if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Application.mk)
|
||||
file(WRITE ${ANDROID_PROJECT_DIR}/jni/Application.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
|
||||
endif()
|
||||
|
||||
# 2. generate gdb.setup
|
||||
get_directory_property(PROJECT_INCLUDES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES)
|
||||
string(REGEX REPLACE ";" " " PROJECT_INCLUDES "${PROJECT_INCLUDES}")
|
||||
file(WRITE ${LIBRARY_OUTPUT_PATH}/gdb.setup "set solib-search-path ${NDK_GDB_SOLIB_PATH}\n")
|
||||
file(APPEND ${LIBRARY_OUTPUT_PATH}/gdb.setup "directory ${PROJECT_INCLUDES}\n")
|
||||
|
||||
# 3. copy gdbserver executable
|
||||
file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver DESTINATION ${LIBRARY_OUTPUT_PATH})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# register a target for remote debugging
|
||||
# copies the debug version to NDK_GDB_SOLIB_PATH then strips symbols of original
|
||||
macro(android_ndk_gdb_debuggable TARGET_NAME)
|
||||
if(ANDROID)
|
||||
get_property(TARGET_LOCATION TARGET ${TARGET_NAME} PROPERTY LOCATION)
|
||||
|
||||
# create custom target that depends on the real target so it gets executed afterwards
|
||||
add_dependencies(NDK_GDB ${TARGET_NAME})
|
||||
|
||||
# 4. copy lib to obj
|
||||
add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${TARGET_LOCATION} ${NDK_GDB_SOLIB_PATH})
|
||||
|
||||
# 5. strip symbols
|
||||
add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_STRIP} ${TARGET_LOCATION})
|
||||
endif()
|
||||
endmacro()
|
|
@ -0,0 +1,58 @@
|
|||
# Copyright (c) 2014, Pavel Rojtberg
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
macro(android_ndk_import_module_cpufeatures)
|
||||
if(ANDROID)
|
||||
include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
|
||||
add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
|
||||
target_link_libraries(cpufeatures dl)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(android_ndk_import_module_native_app_glue)
|
||||
if(ANDROID)
|
||||
include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
|
||||
add_library(native_app_glue ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
|
||||
target_link_libraries(native_app_glue log)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(android_ndk_import_module_ndk_helper)
|
||||
if(ANDROID)
|
||||
android_ndk_import_module_cpufeatures()
|
||||
android_ndk_import_module_native_app_glue()
|
||||
|
||||
include_directories(${ANDROID_NDK}/sources/android/ndk_helper)
|
||||
file(GLOB _NDK_HELPER_SRCS ${ANDROID_NDK}/sources/android/ndk_helper/*.cpp ${ANDROID_NDK}/sources/android/ndk_helper/gl3stub.c)
|
||||
add_library(ndk_helper ${_NDK_HELPER_SRCS})
|
||||
target_link_libraries(ndk_helper log android EGL GLESv2 cpufeatures native_app_glue)
|
||||
|
||||
unset(_NDK_HELPER_SRCS)
|
||||
endif()
|
||||
endmacro()
|
|
@ -0,0 +1,240 @@
|
|||
# android-cmake
|
||||
|
||||
CMake is great, and so is Android. This is a collection of CMake scripts that may be useful to the Android NDK community. It is based on experience from porting OpenCV library to Android: http://opencv.org/platforms/android.html
|
||||
|
||||
Main goal is to share these scripts so that devs that use CMake as their build system may easily compile native code for Android.
|
||||
|
||||
## TL;DR
|
||||
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake \
|
||||
-DANDROID_NDK=<ndk_path> \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DANDROID_ABI="armeabi-v7a with NEON" \
|
||||
<source_path>
|
||||
cmake --build .
|
||||
|
||||
One-liner:
|
||||
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_NDK=<ndk_path> -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a with NEON" <source_path> && cmake --build .
|
||||
|
||||
_android-cmake_ will search for your NDK install in the following order:
|
||||
|
||||
1. Value of `ANDROID_NDK` CMake variable;
|
||||
1. Value of `ANDROID_NDK` environment variable;
|
||||
1. Search under paths from `ANDROID_NDK_SEARCH_PATHS` CMake variable;
|
||||
1. Search platform specific locations (home folder, Windows "Program Files", etc).
|
||||
|
||||
So if you have installed the NDK as `~/android-ndk-r10d` then _android-cmake_ will locate it automatically.
|
||||
|
||||
## Getting started
|
||||
|
||||
To build a cmake-based C/C++ project for Android you need:
|
||||
|
||||
* Android NDK (>= r5) http://developer.android.com/tools/sdk/ndk/index.html
|
||||
* CMake (>= v2.6.3, >= v2.8.9 recommended) http://www.cmake.org/download
|
||||
|
||||
The _android-cmake_ is also capable to build with NDK from AOSP or Linaro Android source tree, but you may be required to manually specify path to `libm` binary to link with.
|
||||
|
||||
## Difference from traditional CMake
|
||||
|
||||
Folowing the _ndk-build_ the _android-cmake_ supports **only two build targets**:
|
||||
|
||||
* `-DCMAKE_BUILD_TYPE=Release`
|
||||
* `-DCMAKE_BUILD_TYPE=Debug`
|
||||
|
||||
So don't even try other targets that can be found in CMake documentation and don't forget to explicitly specify `Release` or `Debug` because CMake builds without a build configuration by default.
|
||||
|
||||
## Difference from _ndk-build_
|
||||
|
||||
* Latest GCC available in NDK is used as the default compiler;
|
||||
* `Release` builds with `-O3` instead of `-Os`;
|
||||
* `Release` builds without debug info (without `-g`) (because _ndk-build_ always creates a stripped version but cmake delays this for `install/strip` target);
|
||||
* `-fsigned-char` is added to compiler flags to make `char` signed by default as it is on x86/x86_64;
|
||||
* GCC's stack protector is not used neither in `Debug` nor `Release` configurations;
|
||||
* No builds for multiple platforms (e.g. building for both arm and x86 require to run cmake twice with different parameters);
|
||||
* No file level Neon via `.neon` suffix;
|
||||
|
||||
The following features of _ndk-build_ are not supported by the _android-cmake_ yet:
|
||||
|
||||
* `armeabi-v7a-hard` ABI
|
||||
* `libc++_static`/`libc++_shared` STL runtime
|
||||
|
||||
## Basic options
|
||||
|
||||
Similarly to the NDK build system _android-cmake_ allows to select between several compiler toolchains and target platforms. Most of the options can be set either as cmake arguments: `-D<NAME>=<VALUE>` or as environment variables:
|
||||
|
||||
* **ANDROID_NDK** - path to the Android NDK. If not set then _android-cmake_ will search for the most recent version of supported NDK in commonly used locations;
|
||||
* **ANDROID_ABI** - specifies the target Application Binary Interface (ABI). This option nearly matches to the APP_ABI variable used by ndk-build tool from Android NDK. If not specified then set to `armeabi-v7a`. Possible target names are:
|
||||
* `armeabi` - ARMv5TE based CPU with software floating point operations;
|
||||
* **`armeabi-v7a`** - ARMv7 based devices with hardware FPU instructions (VFPv3_D16);
|
||||
* `armeabi-v7a with NEON` - same as armeabi-v7a, but sets NEON as floating-point unit;
|
||||
* `armeabi-v7a with VFPV3` - same as armeabi-v7a, but sets VFPv3_D32 as floating-point unit;
|
||||
* `armeabi-v6 with VFP` - tuned for ARMv6 processors having VFP;
|
||||
* `x86` - IA-32 instruction set
|
||||
* `mips` - MIPS32 instruction set
|
||||
* `arm64-v8a` - ARMv8 AArch64 instruction set - only for NDK r10 and newer
|
||||
* `x86_64` - Intel64 instruction set (r1) - only for NDK r10 and newer
|
||||
* `mips64` - MIPS64 instruction set (r6) - only for NDK r10 and newer
|
||||
* **ANDROID_NATIVE_API_LEVEL** - level of android API to build for. Can be set either to full name (example: `android-8`) or a numeric value (example: `17`). The default API level depends on the target ABI:
|
||||
* `android-8` for ARM;
|
||||
* `android-9` for x86 and MIPS;
|
||||
* `android-21` for 64-bit ABIs.
|
||||
|
||||
Building for `android-L` is possible only when it is explicitly selected.
|
||||
* **ANDROID_TOOLCHAIN_NAME** - the name of compiler toolchain to be used. This option allows to select between different GCC and Clang versions. The list of possible values depends on the NDK version and will be printed by toolchain file if an invalid value is set. By default _android-cmake_ selects the most recent version of GCC which can build for specified `ANDROID_ABI`.
|
||||
|
||||
Example values are:
|
||||
* `aarch64-linux-android-4.9`
|
||||
* `aarch64-linux-android-clang3.5`
|
||||
* `arm-linux-androideabi-4.8`
|
||||
* `arm-linux-androideabi-4.9`
|
||||
* `arm-linux-androideabi-clang3.5`
|
||||
* `mips64el-linux-android-4.9`
|
||||
* `mipsel-linux-android-4.8`
|
||||
* `x86-4.9`
|
||||
* `x86_64-4.9`
|
||||
* etc.
|
||||
* **ANDROID_STL** - the name of C++ runtime to use. The default is `gnustl_static`.
|
||||
* `none` - do not configure the runtime.
|
||||
* `system` - use the default minimal system C++ runtime library.
|
||||
* Implies `-fno-rtti -fno-exceptions`.
|
||||
* `system_re` - use the default minimal system C++ runtime library.
|
||||
* Implies `-frtti -fexceptions`.
|
||||
* `gabi++_static` - use the GAbi++ runtime as a static library.
|
||||
* Implies `-frtti -fno-exceptions`.
|
||||
* Available for NDK r7 and newer.
|
||||
* `gabi++_shared` - use the GAbi++ runtime as a shared library.
|
||||
* Implies `-frtti -fno-exceptions`.
|
||||
* Available for NDK r7 and newer.
|
||||
* `stlport_static` - use the STLport runtime as a static library.
|
||||
* Implies `-fno-rtti -fno-exceptions` for NDK before r7.
|
||||
* Implies `-frtti -fno-exceptions` for NDK r7 and newer.
|
||||
* `stlport_shared` - use the STLport runtime as a shared library.
|
||||
* Implies `-fno-rtti -fno-exceptions` for NDK before r7.
|
||||
* Implies `-frtti -fno-exceptions` for NDK r7 and newer.
|
||||
* **`gnustl_static`** - use the GNU STL as a static library.
|
||||
* Implies `-frtti -fexceptions`.
|
||||
* `gnustl_shared` - use the GNU STL as a shared library.
|
||||
* Implies `-frtti -fno-exceptions`.
|
||||
* Available for NDK r7b and newer.
|
||||
* Silently degrades to `gnustl_static` if not available.
|
||||
* **NDK_CCACHE** - path to `ccache` executable. If not set then initialized from `NDK_CCACHE` environment variable.
|
||||
|
||||
## Advanced _android-cmake_ options
|
||||
|
||||
Normally _android-cmake_ users are not supposed to touch these variables but they might be useful to workaround some build issues:
|
||||
|
||||
* **ANDROID_FORCE_ARM_BUILD** = `OFF` - generate 32-bit ARM instructions instead of Thumb. Applicable only for arm ABIs and is forced to be `ON` for `armeabi-v6 with VFP`;
|
||||
* **ANDROID_NO_UNDEFINED** = `ON` - show all undefined symbols as linker errors;
|
||||
* **ANDROID_SO_UNDEFINED** = `OFF` - allow undefined symbols in shared libraries;
|
||||
* actually it is turned `ON` by default for NDK older than `r7`
|
||||
* **ANDROID_STL_FORCE_FEATURES** = `ON` - automatically configure rtti and exceptions support based on C++ runtime;
|
||||
* **ANDROID_NDK_LAYOUT** = `RELEASE` - inner layout of Android NDK, should be detected automatically. Possible values are:
|
||||
* `RELEASE` - public releases from Google;
|
||||
* `LINARO` - NDK from Linaro project;
|
||||
* `ANDROID` - NDK from AOSP.
|
||||
* **ANDROID_FUNCTION_LEVEL_LINKING** = `ON` - enables saparate putting each function and data items into separate sections and enable garbage collection of unused input sections at link time (`-fdata-sections -ffunction-sections -Wl,--gc-sections`);
|
||||
* **ANDROID_GOLD_LINKER** = `ON` - use gold linker with GCC 4.6 for NDK r8b and newer (only for ARM and x86);
|
||||
* **ANDROID_NOEXECSTACK** = `ON` - enables or disables stack execution protection code (`-Wl,-z,noexecstack`);
|
||||
* **ANDROID_RELRO** = `ON` - Enables RELRO - a memory corruption mitigation technique (`-Wl,-z,relro -Wl,-z,now`);
|
||||
* **ANDROID_LIBM_PATH** - path to `libm.so` (set to something like `$(TOP)/out/target/product/<product_name>/obj/lib/libm.so`) to workaround unresolved `sincos`.
|
||||
|
||||
## Fine-tuning `CMakeLists.txt` for _android-cmake_
|
||||
|
||||
### Recognizing Android build
|
||||
|
||||
_android-cmake_ defines `ANDROID` CMake variable which can be used to add Android-specific stuff:
|
||||
|
||||
if (ANDROID)
|
||||
message(STATUS "Hello from Android build!")
|
||||
endif()
|
||||
|
||||
The recommended way to identify ARM/MIPS/x86 architecture is examining `CMAKE_SYSTEM_PROCESSOR` which is set to the appropriate value:
|
||||
|
||||
* `armv5te` - for `armeabi` ABI
|
||||
* `armv6` - for `armeabi-v6 with VFP` ABI
|
||||
* `armv7-a` - for `armeabi-v7a`, `armeabi-v7a with VFPV3` and `armeabi-v7a with NEON` ABIs
|
||||
* `aarch64` - for `arm64-v8a` ABI
|
||||
* `i686` - for `x86` ABI
|
||||
* `x86_64` - for `x86_64` ABI
|
||||
* `mips` - for `mips` ABI
|
||||
* `mips64` - for `mips64` ABI
|
||||
|
||||
Other variables that are set by _android-cmake_ and can be used for the fine-grained build configuration are:
|
||||
|
||||
* `NEON` - set if target ABI supports Neon;
|
||||
* `ANDROID_NATIVE_API_LEVEL` - native Android API level we are building for (note: Java part of Andoid application can be built for another API level)
|
||||
* `ANDROID_NDK_RELEASE` - version of the Android NDK
|
||||
* `ANDROID_NDK_HOST_SYSTEM_NAME` - "windows", "linux-x86" or "darwin-x86" depending on the host platform
|
||||
* `ANDROID_RTTI` - set if rtti is enabled by the runtime
|
||||
* `ANDROID_EXCEPTIONS` - set if exceptions are enabled by the runtime
|
||||
|
||||
### Finding packages
|
||||
|
||||
When crosscompiling CMake `find_*` commands are normally expected to find libraries and packages belonging to the same build target. So _android-cmake_ configures CMake to search in Android-specific paths only and ignore your host system locations. So
|
||||
|
||||
find_package(ZLIB)
|
||||
|
||||
will surely find libz.so within the Android NDK.
|
||||
|
||||
However sometimes you need to locate a host package even when cross-compiling. For example you can be searching for your documentation generator. The _android-cmake_ recommends you to use `find_host_package` and `find_host_program` macro defined in the `android.toolchain.cmake`:
|
||||
|
||||
find_host_package(Doxygen)
|
||||
find_host_program(PDFLATEX pdflatex)
|
||||
|
||||
However this will break regular builds so instead of wrapping package search into platform-specific logic you can copy the following snippet into your project (put it after your top-level `project()` command):
|
||||
|
||||
# Search packages for host system instead of packages for target system
|
||||
# in case of cross compilation these macro should be defined by toolchain file
|
||||
if(NOT COMMAND find_host_package)
|
||||
macro(find_host_package)
|
||||
find_package(${ARGN})
|
||||
endmacro()
|
||||
endif()
|
||||
if(NOT COMMAND find_host_program)
|
||||
macro(find_host_program)
|
||||
find_program(${ARGN})
|
||||
endmacro()
|
||||
endif()
|
||||
|
||||
### Compiler flags recycling
|
||||
|
||||
Make sure to do the following in your scripts:
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}")
|
||||
|
||||
The flags will be prepopulated with critical flags, so don't loose them. Also be aware that _android-cmake_ also sets configuration-specific compiler and linker flags.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Building on Windows
|
||||
|
||||
First of all `cygwin` builds are **NOT supported** and will not be supported by _android-cmake_. To build natively on Windows you need a port of make but I recommend http://martine.github.io/ninja/ instead.
|
||||
|
||||
To build with Ninja you need:
|
||||
|
||||
* Ensure you are using CMake newer than 2.8.9;
|
||||
* Download the latest Ninja from https://github.com/martine/ninja/releases;
|
||||
* Put the `ninja.exe` into your PATH (or add path to `ninja.exe` to your PATH environment variable);
|
||||
* Pass `-GNinja` to `cmake` alongside with other arguments (or choose Ninja generator in `cmake-gui`).
|
||||
* Enjoy the fast native multithreaded build :)
|
||||
|
||||
But if you still want to stick to old make then:
|
||||
|
||||
* Get a Windows port of GNU Make:
|
||||
* Android NDK r7 (and newer) already has `make.exe` on board;
|
||||
* `mingw-make` should work as fine;
|
||||
* Download some other port. For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm.
|
||||
* Add path to your `make.exe` to system PATH or always use full path;
|
||||
* Pass `-G"MinGW Makefiles"` and `-DCMAKE_MAKE_PROGRAM="<full/path/to/>make.exe"`
|
||||
* It must be `MinGW Makefiles` and not `Unix Makefiles` even if your `make.exe` is not a MinGW's make.
|
||||
* Run `make.exe` or `cmake --build .` for single-threaded build.
|
||||
|
||||
### Projects with assembler files
|
||||
|
||||
The _android-cmake_ should correctly handle projects with assembler sources (`*.s` or `*.S`). But if you still facing problems with assembler then try to upgrade your CMake to version newer than 2.8.5
|
||||
|
||||
## Copying
|
||||
|
||||
_android-cmake_ is distributed under the terms of [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,211 @@
|
|||
|
||||
============== r1 ============== (dead links)
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-1.5_r1-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-1.5_r1-darwin-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-1.5_r1-linux-x86.zip
|
||||
|
||||
============== r2 ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-1.6_r1-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-1.6_r1-darwin-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-1.6_r1-linux-x86.zip
|
||||
|
||||
============== r3 ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r3-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r3-darwin-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip
|
||||
|
||||
============== r4 ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r4-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r4-darwin-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r4-linux-x86.zip
|
||||
|
||||
============== r4b ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r4b-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r4b-darwin-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip
|
||||
|
||||
============== r5 ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r5-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r5-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r5-linux-x86.tar.bz2
|
||||
|
||||
============== r5b ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r5b-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r5b-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r5b-linux-x86.tar.bz2
|
||||
|
||||
============== r5c ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r5c-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r5c-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2
|
||||
|
||||
============== r6 ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r6-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r6-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2
|
||||
|
||||
============== r6b ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r6b-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r6b-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r6b-linux-x86.tar.bz2
|
||||
|
||||
============== r7 ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r7-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r7-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r7-linux-x86.tar.bz2
|
||||
|
||||
============== r7b ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r7b-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r7b-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r7b-linux-x86.tar.bz2
|
||||
|
||||
============== r7c ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r7c-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r7c-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r7c-linux-x86.tar.bz2
|
||||
|
||||
============== r8 ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2
|
||||
|
||||
============== r8b ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8b-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8b-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2
|
||||
|
||||
============== r8c ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8c-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8c-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8c-linux-x86.tar.bz2
|
||||
|
||||
============== r8d ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8d-windows.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8d-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8d-linux-x86.tar.bz2
|
||||
|
||||
============== r8e ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86_64.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86_64.tar.bz2
|
||||
|
||||
============== r9 ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86-legacy-toolchains.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64-legacy-toolchains.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86-legacy-toolchains.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64-legacy-toolchains.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86-legacy-toolchains.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64-legacy-toolchains.tar.bz2
|
||||
|
||||
============== r9b ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86-legacy-toolchains.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64-legacy-toolchains.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86-legacy-toolchains.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64-legacy-toolchains.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86-legacy-toolchains.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64-legacy-toolchains.tar.bz2
|
||||
|
||||
============== r9c ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86_64.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip
|
||||
|
||||
============== r9d ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r9d-cxx-stl-libs-with-debug-info.zip
|
||||
|
||||
============== r10 ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86_64.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86_64.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10-cxx-stl-libs-with-debug-info.zip
|
||||
|
||||
============== r10b ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86_64.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86_64.zip
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86_64.tar.bz2
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10b-cxx-stl-libs-with-debug-info.zip
|
||||
|
||||
============== r10c ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86.exe
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86_64.exe
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86.bin
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86_64.bin
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86.bin
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin
|
||||
|
||||
============== r10d ==============
|
||||
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86.exe
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86_64.exe
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86.bin
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86_64.bin
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86.bin
|
||||
* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin
|
|
@ -43,6 +43,7 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <ostream>
|
||||
|
@ -2365,6 +2366,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
|
|||
//ok, so far it looks like we're still in range of the horizontal edge
|
||||
if ( e->xcurr == horzEdge->xtop && !eMaxPair )
|
||||
{
|
||||
assert(horzEdge->nextInLML);
|
||||
if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange))
|
||||
{
|
||||
//if output polygons share an edge, they'll need joining later ...
|
||||
|
@ -2429,6 +2431,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
|
|||
if ( horzEdge->outIdx >= 0 )
|
||||
IntersectEdges( horzEdge, eMaxPair,
|
||||
IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth);
|
||||
assert(eMaxPair);
|
||||
if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error");
|
||||
DeleteFromAEL(eMaxPair);
|
||||
DeleteFromAEL(horzEdge);
|
||||
|
|
|
@ -135,10 +135,9 @@ bool OpenDDLExport::writeToStream( const std::string &statement ) {
|
|||
}
|
||||
|
||||
bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) {
|
||||
bool success( true );
|
||||
writeNodeHeader( node, statement );
|
||||
if (node->hasProperties()) {
|
||||
success |= writeProperties( node, statement );
|
||||
writeProperties( node, statement );
|
||||
}
|
||||
writeLineEnd( statement );
|
||||
|
||||
|
@ -360,11 +359,10 @@ bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement )
|
|||
}
|
||||
|
||||
DataArrayList *nextDataArrayList = al ;
|
||||
Value *nextValue( nextDataArrayList->m_dataList );
|
||||
while (ddl_nullptr != nextDataArrayList) {
|
||||
if (ddl_nullptr != nextDataArrayList) {
|
||||
statement += "{ ";
|
||||
nextValue = nextDataArrayList->m_dataList;
|
||||
Value *nextValue( nextDataArrayList->m_dataList );
|
||||
size_t idx( 0 );
|
||||
while (ddl_nullptr != nextValue) {
|
||||
if (idx > 0) {
|
||||
|
|
|
@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -275,22 +276,24 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) {
|
|||
}
|
||||
delete id;
|
||||
|
||||
Name *name(ddl_nullptr);
|
||||
in = OpenDDLParser::parseName(in, end, &name);
|
||||
Name *name_(ddl_nullptr);
|
||||
in = OpenDDLParser::parseName(in, end, &name_);
|
||||
std::unique_ptr<Name> name(name_);
|
||||
if( ddl_nullptr != name && ddl_nullptr != node ) {
|
||||
const std::string nodeName( name->m_id->m_buffer );
|
||||
node->setName( nodeName );
|
||||
delete name;
|
||||
}
|
||||
|
||||
|
||||
Property *first(ddl_nullptr);
|
||||
std::unique_ptr<Property> first;
|
||||
in = lookForNextToken(in, end);
|
||||
if (*in == Grammar::OpenPropertyToken[0]) {
|
||||
in++;
|
||||
Property *prop(ddl_nullptr), *prev(ddl_nullptr);
|
||||
std::unique_ptr<Property> prop, prev;
|
||||
while (*in != Grammar::ClosePropertyToken[0] && in != end) {
|
||||
in = OpenDDLParser::parseProperty(in, end, &prop);
|
||||
Property *prop_(ddl_nullptr);
|
||||
in = OpenDDLParser::parseProperty(in, end, &prop_);
|
||||
prop.reset(prop_);
|
||||
in = lookForNextToken(in, end);
|
||||
|
||||
if (*in != Grammar::CommaSeparator[0] && *in != Grammar::ClosePropertyToken[0]) {
|
||||
|
@ -300,20 +303,20 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) {
|
|||
|
||||
if (ddl_nullptr != prop && *in != Grammar::CommaSeparator[0]) {
|
||||
if (ddl_nullptr == first) {
|
||||
first = prop;
|
||||
first = std::move(prop);
|
||||
}
|
||||
if (ddl_nullptr != prev) {
|
||||
prev->m_next = prop;
|
||||
prev->m_next = prop.release();
|
||||
}
|
||||
prev = prop;
|
||||
prev = std::move(prop);
|
||||
}
|
||||
}
|
||||
++in;
|
||||
}
|
||||
|
||||
// set the properties
|
||||
if (ddl_nullptr != first && ddl_nullptr != node) {
|
||||
node->setProperties(first);
|
||||
if (first && ddl_nullptr != node) {
|
||||
node->setProperties(first.release());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,7 +342,6 @@ char *OpenDDLParser::parseStructure( char *in, char *end ) {
|
|||
} else {
|
||||
++in;
|
||||
logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback );
|
||||
error = true;
|
||||
return ddl_nullptr;
|
||||
}
|
||||
in = lookForNextToken( in, end );
|
||||
|
|
|
@ -204,7 +204,7 @@ local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
|
|||
uLong *pX;
|
||||
{
|
||||
uLong x ;
|
||||
int i;
|
||||
int i = 0;
|
||||
int err;
|
||||
|
||||
err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
|
||||
|
@ -232,7 +232,7 @@ local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
|
|||
uLong *pX;
|
||||
{
|
||||
uLong x ;
|
||||
int i;
|
||||
int i = 0;
|
||||
int err;
|
||||
|
||||
err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
|
||||
|
@ -725,19 +725,15 @@ local int unzlocal_GetCurrentFileInfoInternal (file,
|
|||
|
||||
if (lSeek!=0)
|
||||
{
|
||||
if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
|
||||
lSeek=0;
|
||||
else
|
||||
if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)!=0)
|
||||
err=UNZ_ERRNO;
|
||||
}
|
||||
if ((file_info.size_file_comment>0) && (commentBufferSize>0))
|
||||
if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
|
||||
err=UNZ_ERRNO;
|
||||
lSeek+=file_info.size_file_comment - uSizeRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
lSeek+=file_info.size_file_comment;
|
||||
}
|
||||
|
||||
if ((err==UNZ_OK) && (pfile_info!=NULL))
|
||||
|
@ -1129,7 +1125,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
|
|||
|
||||
if ((s->cur_file_info.compression_method!=0) &&
|
||||
(s->cur_file_info.compression_method!=Z_DEFLATED))
|
||||
err=UNZ_BADZIPFILE;
|
||||
return UNZ_BADZIPFILE;
|
||||
|
||||
pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
|
||||
pfile_in_zip_read_info->crc32=0;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#ifndef ZCONF_H
|
||||
#define ZCONF_H
|
||||
/* #undef Z_PREFIX */
|
||||
/* #undef Z_HAVE_UNISTD_H */
|
||||
|
||||
/*
|
||||
* If you *really* need a unique prefix for all types and library functions,
|
||||
|
|
|
@ -1742,7 +1742,7 @@ UML_LOOK = NO
|
|||
# the class node. If there are many fields or methods and many nodes the
|
||||
# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
|
||||
# threshold limits the number of items for each type to make the size more
|
||||
# managable. Set this to 0 for no limit. Note that the threshold may be
|
||||
# manageable. Set this to 0 for no limit. Note that the threshold may be
|
||||
# exceeded by 50% before the limit is enforced.
|
||||
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
|
|
10
doc/dox.h
10
doc/dox.h
|
@ -60,7 +60,7 @@ that it has not been implemented yet and some (most ...) formats lack proper spe
|
|||
<b>Stanford Ply</b> ( <i>*.ply</i> )<br>
|
||||
<b>TrueSpace</b> ( <i>*.cob, *.scn</i> )<sup>2</sup><br><br>
|
||||
</tt>
|
||||
See the @link importer_notes Importer Notes Page @endlink for informations, what a specific importer can do and what not.
|
||||
See the @link importer_notes Importer Notes Page @endlink for information, what a specific importer can do and what not.
|
||||
Note that although this paper claims to be the official documentation,
|
||||
http://assimp.sourceforge.net/main_features_formats.html
|
||||
<br>is usually the most up-to-date list of file formats supported by the library. <br>
|
||||
|
@ -81,7 +81,7 @@ formats handle the required endian conversion correctly, so large parts of the l
|
|||
|
||||
The assimp linker library and viewer application are provided under the BSD 3-clause license. This basically means
|
||||
that you are free to use it in open- or closed-source projects, for commercial or non-commercial purposes as you like
|
||||
as long as you retain the license informations and take own responsibility for what you do with it. For details see
|
||||
as long as you retain the license information and take own responsibility for what you do with it. For details see
|
||||
the LICENSE file.
|
||||
|
||||
You can find test models for almost all formats in the <assimp_root>/test/models directory. Beware, they're *free*,
|
||||
|
@ -1420,7 +1420,7 @@ IFC file properties (IfcPropertySet) are kept as per-node metadata, see aiNode::
|
|||
|
||||
This section contains implementations notes for the OgreXML importer.
|
||||
@subsection overview Overview
|
||||
Ogre importer is currently optimized for the Blender Ogre exporter, because thats the only one that I use. You can find the Blender Ogre exporter at: http://www.ogre3d.org/forums/viewtopic.php?f=8&t=45922
|
||||
Ogre importer is currently optimized for the Blender Ogre exporter, because that's the only one that I use. You can find the Blender Ogre exporter at: http://www.ogre3d.org/forums/viewtopic.php?f=8&t=45922
|
||||
|
||||
@subsection what What will be loaded?
|
||||
|
||||
|
@ -1434,7 +1434,7 @@ Skeleton: Skeleton with Bone hierarchy (Position and Rotation, but no Scaling in
|
|||
animations with rotation, translation and scaling keys.
|
||||
|
||||
@subsection export_Blender How to export Files from Blender
|
||||
You can find informations about how to use the Ogreexporter by your own, so here are just some options that you need, so the assimp
|
||||
You can find information about how to use the Ogreexporter by your own, so here are just some options that you need, so the assimp
|
||||
importer will load everything correctly:
|
||||
- Use either "Rendering Material" or "Custom Material" see @ref material
|
||||
- do not use "Flip Up Axies to Y"
|
||||
|
@ -1543,7 +1543,7 @@ Done! Please, share your loader that everyone can profit from it!
|
|||
|
||||
@section properties Properties
|
||||
|
||||
You can use properties to chance the behavior of you importer. In order to do so, you have to overide BaseImporter::SetupProperties, and specify
|
||||
You can use properties to chance the behavior of you importer. In order to do so, you have to override BaseImporter::SetupProperties, and specify
|
||||
you custom properties in config.h. Just have a look to the other AI_CONFIG_IMPORT_* defines and you will understand, how it works.
|
||||
|
||||
The properties can be set with Importer::SetProperty***() and can be accessed in your SetupProperties function with Importer::GetProperty***(). You can
|
||||
|
|
|
@ -266,6 +266,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define AI_CONFIG_PP_FD_REMOVE \
|
||||
"PP_FD_REMOVE"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Configures the #aiProcess_FindDegenerates to check the area of a
|
||||
* trinagle to be greates than e-6. If this is not the case the triangle will
|
||||
* be removed if #AI_CONFIG_PP_FD_REMOVE is set to true.
|
||||
*/
|
||||
#define AI_CONFIG_PP_FD_CHECKAREA \
|
||||
"PP_FD_CHECKAREA"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @brief Configures the #aiProcess_OptimizeGraph step to preserve nodes
|
||||
* matching a name in a given list.
|
||||
|
@ -903,7 +912,7 @@ enum aiComponent
|
|||
/** @brief Set the tessellation for IFC cylindrical shapes.
|
||||
*
|
||||
* This is used by the IFC importer to determine the tessellation parameter
|
||||
* for cylindrical shapes, i.e. the number of segments used to aproximate a circle.
|
||||
* for cylindrical shapes, i.e. the number of segments used to approximate a circle.
|
||||
* @note The default value is AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION and the
|
||||
* accepted values are in range [3, 180].
|
||||
* Property type: Integer.
|
||||
|
|
|
@ -65,11 +65,10 @@ template <typename TReal>
|
|||
class aiVector3t
|
||||
{
|
||||
public:
|
||||
|
||||
aiVector3t () : x(), y(), z() {}
|
||||
aiVector3t (TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {}
|
||||
explicit aiVector3t (TReal _xyz) : x(_xyz), y(_xyz), z(_xyz) {}
|
||||
aiVector3t (const aiVector3t& o) : x(o.x), y(o.y), z(o.z) {}
|
||||
aiVector3t() : x(), y(), z() {}
|
||||
aiVector3t(TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {}
|
||||
explicit aiVector3t (TReal _xyz ) : x(_xyz), y(_xyz), z(_xyz) {}
|
||||
aiVector3t( const aiVector3t& o ) : x(o.x), y(o.y), z(o.z) {}
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ class MeshKey(Structure):
|
|||
("mTime", c_double),
|
||||
|
||||
# Index into the aiMesh::mAnimMeshes array of the
|
||||
# mesh coresponding to the
|
||||
# mesh corresponding to the
|
||||
#aiMeshAnim hosting this
|
||||
# key frame. The referenced anim mesh is evaluated
|
||||
# according to the rules defined in the docs for
|
||||
|
|
|
@ -895,7 +895,7 @@ class PyAssimp3DViewer:
|
|||
aspect = camera.aspect
|
||||
|
||||
u = 0.1 # unit size (in m)
|
||||
l = 3 * u # lenght of the camera cone
|
||||
l = 3 * u # length of the camera cone
|
||||
f = 3 * u # aperture of the camera cone
|
||||
|
||||
glPushMatrix()
|
||||
|
|
|
@ -897,7 +897,7 @@ class PyAssimp3DViewer:
|
|||
aspect = camera.aspect
|
||||
|
||||
u = 0.1 # unit size (in m)
|
||||
l = 3 * u # lenght of the camera cone
|
||||
l = 3 * u # length of the camera cone
|
||||
f = 3 * u # aperture of the camera cone
|
||||
|
||||
glPushMatrix()
|
||||
|
|
|
@ -583,7 +583,7 @@ def clip_matrix(left, right, bottom, top, near, far, perspective=False):
|
|||
orthographic canonical view volume (a box).
|
||||
|
||||
Homogeneous coordinates transformed by the perspective clip matrix
|
||||
need to be dehomogenized (devided by w coordinate).
|
||||
need to be dehomogenized (divided by w coordinate).
|
||||
|
||||
>>> frustrum = numpy.random.rand(6)
|
||||
>>> frustrum[1] += frustrum[0]
|
||||
|
|
|
@ -51,7 +51,7 @@ import assimp.types;
|
|||
extern ( C ) {
|
||||
/*
|
||||
* These limits are required to match the settings Assimp was compiled
|
||||
* against. Therfore, do not redefine them unless you build the library
|
||||
* against. Therefore, do not redefine them unless you build the library
|
||||
* from source using the same definitions.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1951,7 +1951,7 @@ error:
|
|||
|
||||
if (NULL == exception)
|
||||
{
|
||||
/* thats really a problem because we cannot throw in this case */
|
||||
/* that's really a problem because we cannot throw in this case */
|
||||
env->FatalError("could not throw java.io.IOException");
|
||||
}
|
||||
gLastErrorString = imp.GetErrorString();
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
%include "interface/IOSystem.i"
|
||||
|
||||
|
||||
// We have to "instanciate" the templates used by the ASSSIMP_*_ARRAY macros
|
||||
// We have to "instantiate" the templates used by the ASSSIMP_*_ARRAY macros
|
||||
// here at the end to avoid running into forward reference issues (SWIG would
|
||||
// spit out the helper functions before the header includes for the element
|
||||
// types otherwise).
|
||||
|
|
|
@ -641,7 +641,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS
|
|||
{
|
||||
for(MeshHelper* helper in modelMeshes)
|
||||
{
|
||||
// Set up meterial state.
|
||||
// Set up material state.
|
||||
glCallList(helper.displayList);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ extern void exit(int);
|
|||
glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat,
|
||||
glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!).
|
||||
**/
|
||||
#ifndef GLUT_API_VERSION /* allow this to be overriden */
|
||||
#ifndef GLUT_API_VERSION /* allow this to be overridden */
|
||||
#define GLUT_API_VERSION 3
|
||||
#endif
|
||||
|
||||
|
@ -219,7 +219,7 @@ extern void exit(int);
|
|||
|
||||
GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa <GL/glut.h>
|
||||
**/
|
||||
#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */
|
||||
#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overridden. */
|
||||
#define GLUT_XLIB_IMPLEMENTATION 15
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
@echo off
|
||||
|
||||
set ASSIMP_PATH=D:\projects\asset-importer-lib\assimp
|
||||
set CMAKE_PATH="C:\Program Files\CMake\bin\cmake.exe"
|
||||
set ANDROID_NDK_PATH=C:\Users\kimkulling\AppData\Local\Android\Sdk\ndk-bundle
|
||||
set ANDROID_CMAKE_PATH=contrib\android-cmake
|
||||
|
||||
pushd %ASSIMP_PATH%
|
||||
|
||||
rmdir /s /q build
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
%CMAKE_PATH% .. ^
|
||||
-G"MinGW Makefiles" ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DCMAKE_TOOLCHAIN_FILE=%ANDROID_CMAKE_PATH%\android.toolchain.cmake ^
|
||||
-DCMAKE_MAKE_PROGRAM=%ANDROID_NDK_PATH%\prebuilt\windows-x86_64\bin\make.exe ^
|
||||
-DANDROID_NDK=%ANDROID_NDK_PATH% ^
|
||||
-DANDROID_NATIVE_API_LEVEL=android-9 ^
|
||||
-DASSIMP_ANDROID_JNIIOSYSTEM=ON ^
|
||||
-DANDROID_ABI=arm64-v8a ^
|
||||
-DASSIMP_BUILD_ZLIB=ON ^
|
||||
-DASSIMP_BUILD_TESTS=OFF
|
||||
|
||||
%CMAKE_PATH% --build .
|
||||
|
||||
popd
|
|
@ -52,24 +52,55 @@ INCLUDE_DIRECTORIES(
|
|||
# Assimp library can be found, even if it is not installed system-wide yet.
|
||||
LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib )
|
||||
|
||||
SOURCE_GROUP( unit FILES
|
||||
unit/CCompilerTest.c
|
||||
)
|
||||
|
||||
SET( TEST_SRCS
|
||||
SET( COMMON
|
||||
unit/utIOSystem.cpp
|
||||
unit/utIOStreamBuffer.cpp
|
||||
unit/utIssues.cpp
|
||||
unit/utAnim.cpp
|
||||
unit/AssimpAPITest.cpp
|
||||
unit/utBatchLoader.cpp
|
||||
unit/utDefaultIOStream.cpp
|
||||
unit/utFastAtof.cpp
|
||||
unit/utMetadata.cpp
|
||||
unit/SceneDiffer.h
|
||||
unit/SceneDiffer.cpp
|
||||
unit/UTLogStream.h
|
||||
unit/AbstractImportExportBase.cpp
|
||||
unit/TestIOSystem.h
|
||||
unit/TestModelFactory.h
|
||||
unit/utTypes.cpp
|
||||
unit/utVersion.cpp
|
||||
unit/utProfiler.cpp
|
||||
unit/utSharedPPData.cpp
|
||||
unit/utStringUtils.cpp
|
||||
)
|
||||
|
||||
SET( IMPORTERS
|
||||
unit/utLWSImportExport.cpp
|
||||
unit/utSMDImportExport.cpp
|
||||
unit/utglTFImportExport.cpp
|
||||
unit/utglTF2ImportExport.cpp
|
||||
unit/utHMPImportExport.cpp
|
||||
unit/utIFCImportExport.cpp
|
||||
unit/utFBXImporterExporter.cpp
|
||||
unit/utImporter.cpp
|
||||
unit/ut3DImportExport.cpp
|
||||
unit/ut3DSImportExport.cpp
|
||||
unit/utACImportExport.cpp
|
||||
unit/utAMFImportExport.cpp
|
||||
unit/utASEImportExport.cpp
|
||||
unit/utAnim.cpp
|
||||
unit/AssimpAPITest.cpp
|
||||
unit/utB3DImportExport.cpp
|
||||
unit/utBatchLoader.cpp
|
||||
unit/utD3MFImportExport.cpp
|
||||
unit/utQ3DImportExport.cpp
|
||||
unit/utSTLImportExport.cpp
|
||||
unit/utXImporterExporter.cpp
|
||||
unit/utX3DImportExport.cpp
|
||||
unit/utDXFImporterExporter.cpp
|
||||
unit/utPMXImporter.cpp
|
||||
unit/utPLYImportExport.cpp
|
||||
unit/utObjImportExport.cpp
|
||||
unit/utObjTools.cpp
|
||||
unit/utOpenGEXImportExport.cpp
|
||||
unit/utSIBImporter.cpp
|
||||
unit/utBlenderIntermediate.cpp
|
||||
unit/utBlendImportAreaLight.cpp
|
||||
unit/utBlenderImportExport.cpp
|
||||
|
@ -79,77 +110,60 @@ SET( TEST_SRCS
|
|||
unit/utColladaExportLight.cpp
|
||||
unit/utColladaImportExport.cpp
|
||||
unit/utCSMImportExport.cpp
|
||||
unit/utDefaultIOStream.cpp
|
||||
unit/utDXFImporterExporter.cpp
|
||||
unit/utFastAtof.cpp
|
||||
unit/utFBXImporterExporter.cpp
|
||||
unit/utFindDegenerates.cpp
|
||||
unit/utFindInvalidData.cpp
|
||||
unit/utFixInfacingNormals.cpp
|
||||
unit/utGenNormals.cpp
|
||||
unit/utglTFImportExport.cpp
|
||||
unit/utglTF2ImportExport.cpp
|
||||
unit/utHMPImportExport.cpp
|
||||
unit/utIFCImportExport.cpp
|
||||
unit/utImporter.cpp
|
||||
unit/utImproveCacheLocality.cpp
|
||||
unit/utIOSystem.cpp
|
||||
unit/utIOStreamBuffer.cpp
|
||||
unit/utIssues.cpp
|
||||
unit/utJoinVertices.cpp
|
||||
unit/utLimitBoneWeights.cpp
|
||||
unit/utLWSImportExport.cpp
|
||||
unit/utB3DImportExport.cpp
|
||||
)
|
||||
|
||||
SET( MATERIAL
|
||||
unit/utMaterialSystem.cpp
|
||||
)
|
||||
|
||||
SET( MATH
|
||||
unit/utMatrix3x3.cpp
|
||||
unit/utMatrix4x4.cpp
|
||||
unit/utMetadata.cpp
|
||||
unit/SceneDiffer.h
|
||||
unit/SceneDiffer.cpp
|
||||
unit/utSIBImporter.cpp
|
||||
unit/utObjImportExport.cpp
|
||||
unit/utObjTools.cpp
|
||||
unit/utOpenGEXImportExport.cpp
|
||||
unit/utPretransformVertices.cpp
|
||||
unit/utPLYImportExport.cpp
|
||||
unit/utPMXImporter.cpp
|
||||
unit/utRemoveComments.cpp
|
||||
unit/utRemoveComponent.cpp
|
||||
unit/utScenePreprocessor.cpp
|
||||
unit/utSceneCombiner.cpp
|
||||
unit/utSharedPPData.cpp
|
||||
unit/utStringUtils.cpp
|
||||
unit/utSMDImportExport.cpp
|
||||
unit/utSortByPType.cpp
|
||||
unit/utSplitLargeMeshes.cpp
|
||||
unit/utTargetAnimation.cpp
|
||||
unit/utTextureTransform.cpp
|
||||
unit/utTriangulate.cpp
|
||||
unit/utTypes.cpp
|
||||
unit/utVertexTriangleAdjacency.cpp
|
||||
unit/utVersion.cpp
|
||||
unit/utVector3.cpp
|
||||
unit/utXImporterExporter.cpp
|
||||
unit/utX3DImportExport.cpp
|
||||
unit/utD3MFImportExport.cpp
|
||||
unit/utQ3DImportExport.cpp
|
||||
unit/utProfiler.cpp
|
||||
)
|
||||
|
||||
SET( POST_PROCESSES
|
||||
unit/utImproveCacheLocality.cpp
|
||||
unit/utFixInfacingNormals.cpp
|
||||
unit/utGenNormals.cpp
|
||||
unit/utTriangulate.cpp
|
||||
unit/utTextureTransform.cpp
|
||||
unit/utRemoveRedundantMaterials.cpp
|
||||
unit/utRemoveVCProcess.cpp
|
||||
unit/utScaleProcess.cpp
|
||||
unit/utJoinVertices.cpp
|
||||
unit/utRemoveComments.cpp
|
||||
unit/utRemoveComponent.cpp
|
||||
unit/utVertexTriangleAdjacency.cpp
|
||||
unit/utJoinVertices.cpp
|
||||
unit/utSplitLargeMeshes.cpp
|
||||
unit/utFindDegenerates.cpp
|
||||
unit/utFindInvalidData.cpp
|
||||
unit/utLimitBoneWeights.cpp
|
||||
unit/utPretransformVertices.cpp
|
||||
unit/utScenePreprocessor.cpp
|
||||
unit/utTargetAnimation.cpp
|
||||
unit/utSortByPType.cpp
|
||||
unit/utSceneCombiner.cpp
|
||||
)
|
||||
|
||||
SOURCE_GROUP( tests FILES ${TEST_SRCS} )
|
||||
SOURCE_GROUP( tests/PostProcess FILES ${POST_PROCESSES})
|
||||
SOURCE_GROUP( UnitTests\\Compiler FILES unit/CCompilerTest.c )
|
||||
SOURCE_GROUP( UnitTests\\Common FILES ${COMMON} )
|
||||
SOURCE_GROUP( UnitTests\\Importers FILES ${IMPORTERS} )
|
||||
SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} )
|
||||
SOURCE_GROUP( UnitTests\\Math FILES ${MATH} )
|
||||
SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES})
|
||||
|
||||
add_executable( unit
|
||||
../contrib/gtest/src/gtest-all.cc
|
||||
unit/CCompilerTest.c
|
||||
unit/Main.cpp
|
||||
../code/Version.cpp
|
||||
${TEST_SRCS}
|
||||
${COMMON}
|
||||
${IMPORTERS}
|
||||
${MATERIAL}
|
||||
${MATH}
|
||||
${POST_PROCESSES}
|
||||
)
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ L'utilizzo della Creative Commons non influisce su questo diritto.
|
|||
************************************************
|
||||
|
||||
This model is released under Creative Commons Licence, Attribution 2.0
|
||||
for informations see:
|
||||
for information see:
|
||||
http://creativecommons.org
|
||||
http://creativecommons.org/licenses/by/2.0/
|
||||
feel free to use and improve it.
|
||||
|
|
|
@ -1 +1 @@
|
|||
Simple models for testing importer. No desription because models are simple and created by hands.
|
||||
Simple models for testing importer. No description because models are simple and created by hand.
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
solid testTriangle_1
|
||||
facet normal 0.0 0.0 1.0
|
||||
outer loop
|
||||
vertex 1.0 1.0 0.0
|
||||
vertex -1.0 1.0 0.0
|
||||
vertex 0.0 -1.0 0.0
|
||||
endloop
|
||||
endfacet
|
||||
endsolid
|
||||
solid testTriangle_2
|
||||
facet normal 0.0 0.0 1.0
|
||||
outer loop
|
||||
vertex 3.0 3.0 0.0
|
||||
vertex 2.0 3.0 0.0
|
||||
vertex 0.0 2.0 0.0
|
||||
endloop
|
||||
endfacet
|
||||
endsolid
|
|
@ -58,8 +58,7 @@ protected:
|
|||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void FindDegeneratesProcessTest::SetUp()
|
||||
{
|
||||
void FindDegeneratesProcessTest::SetUp() {
|
||||
mesh = new aiMesh();
|
||||
process = new FindDegeneratesProcess();
|
||||
|
||||
|
@ -107,16 +106,12 @@ void FindDegeneratesProcessTest::SetUp()
|
|||
mesh->mNumUVComponents[1] = numFaces;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void FindDegeneratesProcessTest::TearDown()
|
||||
{
|
||||
void FindDegeneratesProcessTest::TearDown() {
|
||||
delete mesh;
|
||||
delete process;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection)
|
||||
{
|
||||
TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection) {
|
||||
process->EnableInstantRemoval(false);
|
||||
process->ExecuteOnMesh(mesh);
|
||||
|
||||
|
@ -135,12 +130,18 @@ TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection)
|
|||
mesh->mPrimitiveTypes);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
TEST_F(FindDegeneratesProcessTest, testDegeneratesRemoval)
|
||||
{
|
||||
TEST_F(FindDegeneratesProcessTest, testDegeneratesRemoval) {
|
||||
process->EnableAreaCheck(false);
|
||||
process->EnableInstantRemoval(true);
|
||||
process->ExecuteOnMesh(mesh);
|
||||
|
||||
EXPECT_EQ(mesh->mNumUVComponents[1], mesh->mNumFaces);
|
||||
}
|
||||
|
||||
TEST_F(FindDegeneratesProcessTest, testDegeneratesRemovalWithAreaCheck) {
|
||||
process->EnableAreaCheck(true);
|
||||
process->EnableInstantRemoval(true);
|
||||
process->ExecuteOnMesh(mesh);
|
||||
|
||||
EXPECT_EQ(mesh->mNumUVComponents[1]-100, mesh->mNumFaces);
|
||||
}
|
||||
|
|
|
@ -294,12 +294,12 @@ TEST_F(utObjImportExport, relative_indices_Test) {
|
|||
const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure);
|
||||
EXPECT_NE(nullptr, scene);
|
||||
|
||||
EXPECT_EQ(scene->mNumMeshes, 1);
|
||||
EXPECT_EQ(scene->mNumMeshes, 1U);
|
||||
const aiMesh *mesh = scene->mMeshes[0];
|
||||
EXPECT_EQ(mesh->mNumVertices, 4);
|
||||
EXPECT_EQ(mesh->mNumFaces, 1);
|
||||
EXPECT_EQ(mesh->mNumVertices, 4U);
|
||||
EXPECT_EQ(mesh->mNumFaces, 1U);
|
||||
const aiFace face = mesh->mFaces[0];
|
||||
EXPECT_EQ(face.mNumIndices, 4);
|
||||
EXPECT_EQ(face.mNumIndices, 4U);
|
||||
for (unsigned int i = 0; i < face.mNumIndices; ++i)
|
||||
{
|
||||
EXPECT_EQ(face.mIndices[i], i);
|
||||
|
@ -318,12 +318,12 @@ TEST_F(utObjImportExport, homogeneous_coordinates_Test) {
|
|||
const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure);
|
||||
EXPECT_NE(nullptr, scene);
|
||||
|
||||
EXPECT_EQ(scene->mNumMeshes, 1);
|
||||
EXPECT_EQ(scene->mNumMeshes, 1U);
|
||||
const aiMesh *mesh = scene->mMeshes[0];
|
||||
EXPECT_EQ(mesh->mNumVertices, 3);
|
||||
EXPECT_EQ(mesh->mNumFaces, 1);
|
||||
EXPECT_EQ(mesh->mNumVertices, 3U);
|
||||
EXPECT_EQ(mesh->mNumFaces, 1U);
|
||||
const aiFace face = mesh->mFaces[0];
|
||||
EXPECT_EQ(face.mNumIndices, 3);
|
||||
EXPECT_EQ(face.mNumIndices, 3U);
|
||||
const aiVector3D vertice = mesh->mVertices[0];
|
||||
EXPECT_EQ(vertice.x, -1.0f);
|
||||
EXPECT_EQ(vertice.y, 0.0f);
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2017, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the following
|
||||
conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "UnitTestPCH.h"
|
||||
#include "SceneDiffer.h"
|
||||
#include "AbstractImportExportBase.h"
|
||||
|
||||
#include <assimp/Importer.hpp>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
class utSTLImporterExporter : public AbstractImportExportBase {
|
||||
public:
|
||||
virtual bool importerTest() {
|
||||
Assimp::Importer importer;
|
||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", 0 );
|
||||
return nullptr != scene;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F( utSTLImporterExporter, importXFromFileTest ) {
|
||||
EXPECT_TRUE( importerTest() );
|
||||
}
|
||||
|
||||
TEST_F( utSTLImporterExporter, test_with_two_solids ) {
|
||||
Assimp::Importer importer;
|
||||
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", 0 );
|
||||
EXPECT_NE( nullptr, scene );
|
||||
}
|
|
@ -177,6 +177,17 @@ inline uint32_t Write<aiVector3D>(const aiVector3D& v)
|
|||
return t;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Serialize a color value
|
||||
template <>
|
||||
inline uint32_t Write<aiColor3D>(const aiColor3D& v)
|
||||
{
|
||||
uint32_t t = Write<float>(v.r);
|
||||
t += Write<float>(v.g);
|
||||
t += Write<float>(v.b);
|
||||
return t;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Serialize a color value
|
||||
template <>
|
||||
|
@ -198,6 +209,7 @@ inline uint32_t Write<aiQuaternion>(const aiQuaternion& v)
|
|||
t += Write<float>(v.x);
|
||||
t += Write<float>(v.y);
|
||||
t += Write<float>(v.z);
|
||||
ai_assert(t == 16);
|
||||
return 16;
|
||||
}
|
||||
|
||||
|
@ -565,9 +577,9 @@ uint32_t WriteBinaryLight(const aiLight* l)
|
|||
len += Write<float>(l->mAttenuationQuadratic);
|
||||
}
|
||||
|
||||
len += Write<aiVector3D>((const aiVector3D&)l->mColorDiffuse);
|
||||
len += Write<aiVector3D>((const aiVector3D&)l->mColorSpecular);
|
||||
len += Write<aiVector3D>((const aiVector3D&)l->mColorAmbient);
|
||||
len += Write<aiColor3D>(l->mColorDiffuse);
|
||||
len += Write<aiColor3D>(l->mColorSpecular);
|
||||
len += Write<aiColor3D>(l->mColorAmbient);
|
||||
|
||||
if (l->mType == aiLightSource_SPOT) {
|
||||
len += Write<float>(l->mAngleInnerCone);
|
||||
|
|
|
@ -561,7 +561,7 @@ void CGLView::Enable_Textures(const bool pEnable)
|
|||
}
|
||||
|
||||
/********************************************************************/
|
||||
/*********************** Overrided functions ************************/
|
||||
/*********************** Override functions ************************/
|
||||
/********************************************************************/
|
||||
|
||||
void CGLView::initializeGL()
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue