Compare commits
10 Commits
master
...
feature/ru
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e73a537081 | ||
|
|
48515a4aa1 | ||
|
|
1ed019b869 | ||
|
|
7c7a1233f5 | ||
|
|
3e6482bca0 | ||
|
|
c0d273cb3b | ||
|
|
e730b7803c | ||
|
|
cedc5a8d10 | ||
|
|
4d3a694807 | ||
|
|
517fb1b242 |
4
.github/workflows/ccpp.yml
vendored
4
.github/workflows/ccpp.yml
vendored
@@ -182,7 +182,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
steps:
|
steps:
|
||||||
- uses: softprops/action-gh-release@v3
|
- uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
name: create-release
|
name: create-release
|
||||||
- id: upload-url
|
- id: upload-url
|
||||||
@@ -197,4 +197,4 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
*.zip
|
*.zip
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/cd.yml
vendored
2
.github/workflows/cd.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
|||||||
filename: ${{ matrix.name }}-${{ github.event.release.tag_name }}.zip
|
filename: ${{ matrix.name }}-${{ github.event.release.tag_name }}.zip
|
||||||
directory: build/bin/
|
directory: build/bin/
|
||||||
|
|
||||||
- uses: softprops/action-gh-release@v3
|
- uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
files: build/bin/${{ matrix.name }}-${{ github.event.release.tag_name }}.zip
|
files: build/bin/${{ matrix.name }}-${{ github.event.release.tag_name }}.zip
|
||||||
append_body: true
|
append_body: true
|
||||||
|
|||||||
@@ -149,18 +149,11 @@ aiQuaternion Read<aiQuaternion>(IOStream *stream) {
|
|||||||
template <>
|
template <>
|
||||||
aiString Read<aiString>(IOStream *stream) {
|
aiString Read<aiString>(IOStream *stream) {
|
||||||
aiString s;
|
aiString s;
|
||||||
uint32_t len;
|
stream->Read(&s.length, 4, 1);
|
||||||
if (stream->Read(&len, 4, 1) != 1) {
|
if (s.length) {
|
||||||
throw DeadlyImportError("ASSBIN: Unexpected EOF reading string length");
|
stream->Read(s.data, s.length, 1);
|
||||||
}
|
}
|
||||||
if (len >= AI_MAXLEN) {
|
s.data[s.length] = 0;
|
||||||
throw DeadlyImportError("ASSBIN: String length too large, potential buffer overflow attempt");
|
|
||||||
}
|
|
||||||
s.length = len;
|
|
||||||
if ((s.length > 0) && (stream->Read(s.data, s.length, 1) != 1)) {
|
|
||||||
throw DeadlyImportError("ASSBIN: Unexpected EOF reading string data");
|
|
||||||
}
|
|
||||||
s.data[s.length] = '\0';
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -507,20 +507,16 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (table && !table->mMap.empty()) {
|
if (table && !table->mMap.empty()) {
|
||||||
if (matIdx < newMats.size()) {
|
std::pair<Collada::Effect *, aiMaterial *> &mat = newMats[matIdx];
|
||||||
std::pair<Collada::Effect *, aiMaterial *> &mat = newMats[matIdx];
|
|
||||||
|
|
||||||
// Iterate through all texture channels assigned to the effect and
|
// Iterate through all texture channels assigned to the effect and
|
||||||
// check whether we have mapping information for it.
|
// check whether we have mapping information for it.
|
||||||
ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table);
|
ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table);
|
||||||
ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table);
|
ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table);
|
||||||
ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table);
|
ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table);
|
||||||
ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table);
|
ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table);
|
||||||
ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent, *table);
|
ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent, *table);
|
||||||
ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table);
|
ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table);
|
||||||
} else {
|
|
||||||
ASSIMP_LOG_WARN("Collada: Ignoring material mapping for mesh \"", mid.mMeshOrController, "\". Material index ", matIdx, " is out of bounds (newMats.size()=", newMats.size(), ").");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// built lookup index of the Mesh-Submesh-Material combination
|
// built lookup index of the Mesh-Submesh-Material combination
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "FBXParser.h"
|
#include "FBXParser.h"
|
||||||
#include "FBXDocument.h"
|
#include "FBXDocument.h"
|
||||||
#include "FBXMeshGeometry.h"
|
#include "FBXMeshGeometry.h"
|
||||||
@@ -146,10 +144,8 @@ BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc,
|
|||||||
for (const Connection* con : conns) {
|
for (const Connection* con : conns) {
|
||||||
const BlendShapeChannel* const bspc = ProcessSimpleConnection<BlendShapeChannel>(*con, false, "BlendShapeChannel -> BlendShape", element);
|
const BlendShapeChannel* const bspc = ProcessSimpleConnection<BlendShapeChannel>(*con, false, "BlendShapeChannel -> BlendShape", element);
|
||||||
if (bspc) {
|
if (bspc) {
|
||||||
// Only add a channel if it doesn't exist already
|
auto pr = blendShapeChannels.insert(bspc);
|
||||||
if (std::find(blendShapeChannels.begin(), blendShapeChannels.end(), bspc) == blendShapeChannels.end()) {
|
if (!pr.second) {
|
||||||
blendShapeChannels.push_back(bspc);
|
|
||||||
} else {
|
|
||||||
FBXImporter::LogWarn("there is the same blendShapeChannel id ", bspc->ID());
|
FBXImporter::LogWarn("there is the same blendShapeChannel id ", bspc->ID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,10 +170,8 @@ BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const
|
|||||||
for (const Connection* con : conns) {
|
for (const Connection* con : conns) {
|
||||||
const ShapeGeometry* const sg = ProcessSimpleConnection<ShapeGeometry>(*con, false, "Shape -> BlendShapeChannel", element);
|
const ShapeGeometry* const sg = ProcessSimpleConnection<ShapeGeometry>(*con, false, "Shape -> BlendShapeChannel", element);
|
||||||
if (sg) {
|
if (sg) {
|
||||||
// Only add a geometry if it doesn't exist already
|
auto pr = shapeGeometries.insert(sg);
|
||||||
if (std::find(shapeGeometries.begin(), shapeGeometries.end(), sg) == shapeGeometries.end()) {
|
if (!pr.second) {
|
||||||
shapeGeometries.push_back(sg);
|
|
||||||
} else {
|
|
||||||
FBXImporter::LogWarn("there is the same shapeGeometrie id ", sg->ID());
|
FBXImporter::LogWarn("there is the same shapeGeometrie id ", sg->ID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -865,14 +865,14 @@ public:
|
|||||||
return fullWeights;
|
return fullWeights;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<const ShapeGeometry*>& GetShapeGeometries() const {
|
const std::unordered_set<const ShapeGeometry*>& GetShapeGeometries() const {
|
||||||
return shapeGeometries;
|
return shapeGeometries;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float percent;
|
float percent;
|
||||||
WeightArray fullWeights;
|
WeightArray fullWeights;
|
||||||
std::vector<const ShapeGeometry*> shapeGeometries;
|
std::unordered_set<const ShapeGeometry*> shapeGeometries;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DOM class for BlendShape deformers */
|
/** DOM class for BlendShape deformers */
|
||||||
@@ -882,12 +882,12 @@ public:
|
|||||||
|
|
||||||
virtual ~BlendShape() = default;
|
virtual ~BlendShape() = default;
|
||||||
|
|
||||||
const std::vector<const BlendShapeChannel*>& BlendShapeChannels() const {
|
const std::unordered_set<const BlendShapeChannel*>& BlendShapeChannels() const {
|
||||||
return blendShapeChannels;
|
return blendShapeChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<const BlendShapeChannel*> blendShapeChannels;
|
std::unordered_set<const BlendShapeChannel*> blendShapeChannels;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DOM class for skin deformer clusters (aka sub-deformers) */
|
/** DOM class for skin deformer clusters (aka sub-deformers) */
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ namespace {
|
|||||||
// Returns whether the class can handle the format of the given file.
|
// Returns whether the class can handle the format of the given file.
|
||||||
bool FBXImporter::CanRead(const std::string & pFile, IOSystem * pIOHandler, bool /*checkSig*/) const {
|
bool FBXImporter::CanRead(const std::string & pFile, IOSystem * pIOHandler, bool /*checkSig*/) const {
|
||||||
// at least ASCII-FBX files usually have a 'FBX' somewhere in their head
|
// at least ASCII-FBX files usually have a 'FBX' somewhere in their head
|
||||||
static const char *tokens[] = { " \n\r\n ", "fbx" };
|
static const char *tokens[] = { " \n\r\n " };
|
||||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
|
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
|
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "FBXMeshGeometry.h"
|
#include "FBXMeshGeometry.h"
|
||||||
@@ -70,10 +69,8 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
|
|||||||
}
|
}
|
||||||
const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
|
const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
|
||||||
if (bsp) {
|
if (bsp) {
|
||||||
// Only add a blendshape if it doesn't exist already
|
auto pr = blendShapes.insert(bsp);
|
||||||
if (std::find(blendShapes.begin(), blendShapes.end(), bsp) == blendShapes.end()) {
|
if (!pr.second) {
|
||||||
blendShapes.push_back(bsp);
|
|
||||||
} else {
|
|
||||||
FBXImporter::LogWarn("there is the same blendShape id ", bsp->ID());
|
FBXImporter::LogWarn("there is the same blendShape id ", bsp->ID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,7 +78,7 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
|
const std::unordered_set<const BlendShape*>& Geometry::GetBlendShapes() const {
|
||||||
return blendShapes;
|
return blendShapes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,11 +72,11 @@ public:
|
|||||||
|
|
||||||
/// @brief Get the BlendShape attached to this geometry or nullptr
|
/// @brief Get the BlendShape attached to this geometry or nullptr
|
||||||
/// @return The blendshape arrays.
|
/// @return The blendshape arrays.
|
||||||
const std::vector<const BlendShape*>& GetBlendShapes() const;
|
const std::unordered_set<const BlendShape*>& GetBlendShapes() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Skin* skin;
|
const Skin* skin;
|
||||||
std::vector<const BlendShape*> blendShapes;
|
std::unordered_set<const BlendShape*> blendShapes;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#if !defined ASSIMP_BUILD_NO_M3D_IMPORTER || !(defined ASSIMP_BUILD_NO_EXPORT || defined ASSIMP_BUILD_NO_M3D_EXPORTER)
|
#if !defined ASSIMP_BUILD_NO_M3D_IMPORTER || !(defined ASSIMP_BUILD_NO_EXPORT || defined ASSIMP_BUILD_NO_M3D_EXPORTER)
|
||||||
@@ -102,68 +103,15 @@ M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &b
|
|||||||
ai_assert(nullptr != pIOHandler);
|
ai_assert(nullptr != pIOHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Security fix: Validate buffer size and content before processing
|
|
||||||
if (buffer.empty()) {
|
|
||||||
ASSIMP_LOG_ERROR("M3D: Empty buffer provided");
|
|
||||||
m3d_ = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for minimum valid M3D file size (header + basic structure)
|
|
||||||
const size_t MIN_VALID_M3D_SIZE = 100; // Minimum reasonable size for a valid M3D file
|
|
||||||
if (buffer.size() < MIN_VALID_M3D_SIZE) {
|
|
||||||
ASSIMP_LOG_ERROR("M3D: Buffer too small to be a valid M3D file");
|
|
||||||
m3d_ = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate M3D magic signature to ensure this is actually an M3D file
|
|
||||||
// M3D files should start with "3DMO" or "3dmo" magic signature
|
|
||||||
if (buffer.size() >= 4) {
|
|
||||||
bool valid_signature = false;
|
|
||||||
// Check for "3DMO" (uppercase)
|
|
||||||
if (buffer[0] == '3' && buffer[1] == 'D' && buffer[2] == 'M' && buffer[3] == 'O') {
|
|
||||||
valid_signature = true;
|
|
||||||
}
|
|
||||||
// Check for "3dmo" (lowercase)
|
|
||||||
else if (buffer[0] == '3' && buffer[1] == 'd' && buffer[2] == 'm' && buffer[3] == 'o') {
|
|
||||||
valid_signature = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid_signature) {
|
|
||||||
ASSIMP_LOG_ERROR("M3D: Invalid file signature - not a valid M3D file");
|
|
||||||
m3d_ = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a safe copy of the buffer with guard pages/validation
|
|
||||||
// This helps prevent buffer overflows from affecting the main process
|
|
||||||
std::vector<unsigned char> safe_buffer = buffer;
|
|
||||||
|
|
||||||
// Add a guard page at the end to catch any overflow attempts
|
|
||||||
// Note: This is a defensive measure, not a complete fix for the underlying issue
|
|
||||||
safe_buffer.resize(safe_buffer.size() + 1);
|
|
||||||
safe_buffer.back() = 0xFF; // Guard byte
|
|
||||||
|
|
||||||
#ifdef ASSIMP_USE_M3D_READFILECB
|
#ifdef ASSIMP_USE_M3D_READFILECB
|
||||||
// pass this IOHandler to the C callback in a thread-local pointer
|
// pass this IOHandler to the C callback in a thread-local pointer
|
||||||
m3dimporter_pIOHandler = pIOHandler;
|
m3dimporter_pIOHandler = pIOHandler;
|
||||||
m3d_ = m3d_load(const_cast<unsigned char *>(safe_buffer.data()), m3dimporter_readfile, free, nullptr);
|
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
|
||||||
// Clear the C callback
|
// Clear the C callback
|
||||||
m3dimporter_pIOHandler = nullptr;
|
m3dimporter_pIOHandler = nullptr;
|
||||||
#else
|
#else
|
||||||
m3d_ = m3d_load(const_cast<unsigned char *>(safe_buffer.data()), nullptr, nullptr, nullptr);
|
m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Verify the guard byte wasn't overwritten (indicating potential buffer overflow)
|
|
||||||
if (safe_buffer.empty() || safe_buffer.back() != 0xFF) {
|
|
||||||
ASSIMP_LOG_ERROR("M3D: Potential buffer overflow detected during loading");
|
|
||||||
if (m3d_) {
|
|
||||||
m3d_free(m3d_);
|
|
||||||
m3d_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
M3DWrapper::~M3DWrapper() {
|
M3DWrapper::~M3DWrapper() {
|
||||||
@@ -199,4 +147,4 @@ void M3DWrapper::ClearSave() {
|
|||||||
}
|
}
|
||||||
} // namespace Assimp
|
} // namespace Assimp
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public:
|
|||||||
|
|
||||||
/// Construct an M3D model from provided buffer
|
/// Construct an M3D model from provided buffer
|
||||||
/// @note The m3d.h SDK function does not mark the data as const. Have assumed it does not write.
|
/// @note The m3d.h SDK function does not mark the data as const. Have assumed it does not write.
|
||||||
/// SECURITY: Buffer size validation and guard pages added to mitigate potential overflows
|
/// BUG: SECURITY: The m3d.h SDK cannot be informed of the buffer size. BUFFER OVERFLOW IS CERTAIN
|
||||||
explicit M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer);
|
explicit M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer);
|
||||||
|
|
||||||
/// Theclasss destructor.
|
/// Theclasss destructor.
|
||||||
|
|||||||
@@ -1038,27 +1038,21 @@ size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remap
|
|||||||
|
|
||||||
const size_t maxSize = GetMaxByteSize();
|
const size_t maxSize = GetMaxByteSize();
|
||||||
|
|
||||||
if (elemSize > maxSize) {
|
|
||||||
throw DeadlyImportError("GLTF: elemSize ", elemSize, " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t maxCount = (maxSize - elemSize) / stride + 1;
|
|
||||||
|
|
||||||
if (count > maxCount) {
|
|
||||||
throw DeadlyImportError("GLTF: count ", count, " > maxCount ", maxCount, " in ", getContextForErrorMessages(id, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
outData = new T[usedCount];
|
outData = new T[usedCount];
|
||||||
|
|
||||||
if (remappingIndices != nullptr) {
|
if (remappingIndices != nullptr) {
|
||||||
|
const unsigned int maxIndexCount = static_cast<unsigned int>(maxSize / stride);
|
||||||
for (size_t i = 0; i < usedCount; ++i) {
|
for (size_t i = 0; i < usedCount; ++i) {
|
||||||
size_t srcIdx = (*remappingIndices)[i];
|
size_t srcIdx = (*remappingIndices)[i];
|
||||||
if (srcIdx >= count) {
|
if (srcIdx >= maxIndexCount) {
|
||||||
throw DeadlyImportError("GLTF: index ", srcIdx, " >= count ", count, " in ", getContextForErrorMessages(id, name));
|
throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
|
||||||
}
|
}
|
||||||
memcpy(outData + i, data + srcIdx * stride, elemSize);
|
memcpy(outData + i, data + srcIdx * stride, elemSize);
|
||||||
}
|
}
|
||||||
} else { // non-indexed cases
|
} else { // non-indexed cases
|
||||||
|
if (usedCount * stride > maxSize) {
|
||||||
|
throw DeadlyImportError("GLTF: count*stride ", (usedCount * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
|
||||||
|
}
|
||||||
if (stride == elemSize && targetElemSize == elemSize) {
|
if (stride == elemSize && targetElemSize == elemSize) {
|
||||||
memcpy(outData, data, totalSize);
|
memcpy(outData, data, totalSize);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -556,6 +556,12 @@ void glTF2Exporter::GetMatTexProp(const aiMaterial &mat, unsigned int &prop, con
|
|||||||
mat.Get(textureKey.c_str(), tt, slot, prop);
|
mat.Get(textureKey.c_str(), tt, slot, prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void glTF2Exporter::GetMatTexProp(const aiMaterial &mat, float &prop, const char *propName, aiTextureType tt, unsigned int slot) {
|
||||||
|
std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
|
||||||
|
|
||||||
|
mat.Get(textureKey.c_str(), tt, slot, prop);
|
||||||
|
}
|
||||||
|
|
||||||
void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0) {
|
void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0) {
|
||||||
if (mat.GetTextureCount(tt) == 0) {
|
if (mat.GetTextureCount(tt) == 0) {
|
||||||
return;
|
return;
|
||||||
@@ -646,7 +652,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, NormalTextureInfo &prop, ai
|
|||||||
|
|
||||||
if (texture) {
|
if (texture) {
|
||||||
// GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
|
// GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
|
||||||
mat.Get(AI_MATKEY_GLTF_TEXTURE_SCALE(tt, slot), prop.scale);
|
GetMatTexProp(mat, prop.scale, "scale", tt, slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,7 +663,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, OcclusionTextureInfo &prop,
|
|||||||
|
|
||||||
if (texture) {
|
if (texture) {
|
||||||
// GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
|
// GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
|
||||||
mat.Get(AI_MATKEY_GLTF_TEXTURE_STRENGTH(tt, slot), prop.strength);
|
GetMatTexProp(mat, prop.strength, "strength", tt, slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ protected:
|
|||||||
void WriteBinaryData(IOStream *outfile, std::size_t sceneLength);
|
void WriteBinaryData(IOStream *outfile, std::size_t sceneLength);
|
||||||
void GetTexSampler(const aiMaterial &mat, glTFCommon::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
|
void GetTexSampler(const aiMaterial &mat, glTFCommon::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
|
||||||
void GetMatTexProp(const aiMaterial &mat, unsigned int &prop, const char *propName, aiTextureType tt, unsigned int idx);
|
void GetMatTexProp(const aiMaterial &mat, unsigned int &prop, const char *propName, aiTextureType tt, unsigned int idx);
|
||||||
|
void GetMatTexProp(const aiMaterial &mat, float &prop, const char *propName, aiTextureType tt, unsigned int idx);
|
||||||
void GetMatTex(const aiMaterial &mat, glTFCommon::Ref<glTF2::Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot);
|
void GetMatTex(const aiMaterial &mat, glTFCommon::Ref<glTF2::Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot);
|
||||||
void GetMatTex(const aiMaterial &mat, glTF2::TextureInfo &prop, aiTextureType tt, unsigned int slot);
|
void GetMatTex(const aiMaterial &mat, glTF2::TextureInfo &prop, aiTextureType tt, unsigned int slot);
|
||||||
void GetMatTex(const aiMaterial &mat, glTF2::NormalTextureInfo &prop, aiTextureType tt, unsigned int slot);
|
void GetMatTex(const aiMaterial &mat, glTF2::NormalTextureInfo &prop, aiTextureType tt, unsigned int slot);
|
||||||
|
|||||||
@@ -237,7 +237,8 @@ static void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset
|
|||||||
SetMaterialTextureProperty(embeddedTexIdxs, r, static_cast<TextureInfo>(prop), mat, texType, texSlot);
|
SetMaterialTextureProperty(embeddedTexIdxs, r, static_cast<TextureInfo>(prop), mat, texType, texSlot);
|
||||||
|
|
||||||
if (prop.texture && prop.texture->source) {
|
if (prop.texture && prop.texture->source) {
|
||||||
mat->AddProperty(&prop.strength, 1, AI_MATKEY_GLTF_TEXTURE_STRENGTH(texType, texSlot));
|
std::string textureStrengthKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + "strength";
|
||||||
|
mat->AddProperty(&prop.strength, 1, textureStrengthKey.c_str(), texType, texSlot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,55 +58,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace {
|
|
||||||
ai_real calculateInputACMR(aiMesh *pMesh, const aiFace *const pcEnd,
|
|
||||||
unsigned int configCacheDepth, unsigned int meshNum) {
|
|
||||||
ai_real fACMR = 0.0f;
|
|
||||||
unsigned int *piFIFOStack = new unsigned int[configCacheDepth];
|
|
||||||
memset(piFIFOStack, 0xff, configCacheDepth * sizeof(unsigned int));
|
|
||||||
unsigned int *piCur = piFIFOStack;
|
|
||||||
const unsigned int *const piCurEnd = piFIFOStack + configCacheDepth;
|
|
||||||
|
|
||||||
// count the number of cache misses
|
|
||||||
unsigned int iCacheMisses = 0;
|
|
||||||
for (const aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) {
|
|
||||||
for (unsigned int qq = 0; qq < 3; ++qq) {
|
|
||||||
bool bInCache = false;
|
|
||||||
for (unsigned int *pp = piFIFOStack; pp < piCurEnd; ++pp) {
|
|
||||||
if (*pp == pcFace->mIndices[qq]) {
|
|
||||||
// the vertex is in cache
|
|
||||||
bInCache = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!bInCache) {
|
|
||||||
++iCacheMisses;
|
|
||||||
if (piCurEnd == piCur) {
|
|
||||||
piCur = piFIFOStack;
|
|
||||||
}
|
|
||||||
*piCur++ = pcFace->mIndices[qq];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete[] piFIFOStack;
|
|
||||||
fACMR = (ai_real)iCacheMisses / pMesh->mNumFaces;
|
|
||||||
if (3.0 == fACMR) {
|
|
||||||
char szBuff[128]; // should be sufficiently large in every case
|
|
||||||
|
|
||||||
// the JoinIdenticalVertices process has not been executed on this
|
|
||||||
// mesh, otherwise this value would normally be at least minimally
|
|
||||||
// smaller than 3.0 ...
|
|
||||||
ai_snprintf(szBuff, 128, "Mesh %u: Not suitable for vcache optimization", meshNum);
|
|
||||||
ASSIMP_LOG_WARN(szBuff);
|
|
||||||
return static_cast<ai_real>(0.f);
|
|
||||||
}
|
|
||||||
return fACMR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Constructor to be privately used by Importer
|
// Constructor to be privately used by Importer
|
||||||
ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() : mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) {
|
ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() :
|
||||||
|
mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,6 +107,51 @@ void ImproveCacheLocalityProcess::Execute(aiScene *pScene) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static ai_real calculateInputACMR(aiMesh *pMesh, const aiFace *const pcEnd,
|
||||||
|
unsigned int configCacheDepth, unsigned int meshNum) {
|
||||||
|
ai_real fACMR = 0.0f;
|
||||||
|
unsigned int *piFIFOStack = new unsigned int[configCacheDepth];
|
||||||
|
memset(piFIFOStack, 0xff, configCacheDepth * sizeof(unsigned int));
|
||||||
|
unsigned int *piCur = piFIFOStack;
|
||||||
|
const unsigned int *const piCurEnd = piFIFOStack + configCacheDepth;
|
||||||
|
|
||||||
|
// count the number of cache misses
|
||||||
|
unsigned int iCacheMisses = 0;
|
||||||
|
for (const aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) {
|
||||||
|
for (unsigned int qq = 0; qq < 3; ++qq) {
|
||||||
|
bool bInCache = false;
|
||||||
|
for (unsigned int *pp = piFIFOStack; pp < piCurEnd; ++pp) {
|
||||||
|
if (*pp == pcFace->mIndices[qq]) {
|
||||||
|
// the vertex is in cache
|
||||||
|
bInCache = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!bInCache) {
|
||||||
|
++iCacheMisses;
|
||||||
|
if (piCurEnd == piCur) {
|
||||||
|
piCur = piFIFOStack;
|
||||||
|
}
|
||||||
|
*piCur++ = pcFace->mIndices[qq];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] piFIFOStack;
|
||||||
|
fACMR = (ai_real)iCacheMisses / pMesh->mNumFaces;
|
||||||
|
if (3.0 == fACMR) {
|
||||||
|
char szBuff[128]; // should be sufficiently large in every case
|
||||||
|
|
||||||
|
// the JoinIdenticalVertices process has not been executed on this
|
||||||
|
// mesh, otherwise this value would normally be at least minimally
|
||||||
|
// smaller than 3.0 ...
|
||||||
|
ai_snprintf(szBuff, 128, "Mesh %u: Not suitable for vcache optimization", meshNum);
|
||||||
|
ASSIMP_LOG_WARN(szBuff);
|
||||||
|
return static_cast<ai_real>(0.f);
|
||||||
|
}
|
||||||
|
return fACMR;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Improves the cache coherency of a specific mesh
|
// Improves the cache coherency of a specific mesh
|
||||||
ai_real ImproveCacheLocalityProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshNum) {
|
ai_real ImproveCacheLocalityProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshNum) {
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ public:
|
|||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
/// Get the remaining stream size (to the end of the stream)
|
/// Get the remaining stream size (to the end of the stream)
|
||||||
size_t GetRemainingSize() const {
|
size_t GetRemainingSize() const {
|
||||||
return static_cast<size_t>(mEnd - mCurrent);
|
return (unsigned int)(mEnd - mCurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
@@ -190,29 +190,16 @@ public:
|
|||||||
* return value is the remaining size of the stream if no custom
|
* return value is the remaining size of the stream if no custom
|
||||||
* read limit has been set. */
|
* read limit has been set. */
|
||||||
size_t GetRemainingSizeToLimit() const {
|
size_t GetRemainingSizeToLimit() const {
|
||||||
return static_cast<size_t>(mLimit - mCurrent);
|
return (unsigned int)(mLimit - mCurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
/** Increase the file pointer (relative seeking) */
|
/** Increase the file pointer (relative seeking) */
|
||||||
void IncPtr(intptr_t plus) {
|
void IncPtr(intptr_t plus) {
|
||||||
// Ensure internal pointer invariants hold
|
|
||||||
if (mCurrent < mBuffer || mCurrent > mLimit) {
|
|
||||||
throw DeadlyImportError("StreamReader: Invalid internal pointer state");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plus < 0) {
|
|
||||||
const size_t absPlus = static_cast<size_t>(-(plus + 1)) + 1;
|
|
||||||
if (absPlus > static_cast<size_t>(mCurrent - mBuffer)) {
|
|
||||||
throw DeadlyImportError("StreamReader: Attempted to seek outside buffer bounds");
|
|
||||||
}
|
|
||||||
} else if (plus > 0) {
|
|
||||||
if (static_cast<size_t>(plus) > static_cast<size_t>(mLimit - mCurrent)) {
|
|
||||||
throw DeadlyImportError("StreamReader: Attempted to seek outside buffer bounds");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mCurrent += plus;
|
mCurrent += plus;
|
||||||
|
if (mCurrent > mLimit) {
|
||||||
|
throw DeadlyImportError("End of file or read limit was reached");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
@@ -246,9 +233,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Get the current offset from the beginning of the file
|
/// @brief Get the current offset from the beginning of the file
|
||||||
/// @return The current offset from the beginning of the file.
|
|
||||||
int GetCurrentPos() const {
|
int GetCurrentPos() const {
|
||||||
return static_cast<int>(mCurrent - mBuffer);
|
return (unsigned int)(mCurrent - mBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCurrentPos(size_t pos) {
|
void SetCurrentPos(size_t pos) {
|
||||||
@@ -258,10 +244,10 @@ public:
|
|||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
/** Setup a temporary read limit
|
/** Setup a temporary read limit
|
||||||
*
|
*
|
||||||
* @param _limit Maximum number of bytes to be read from
|
* @param limit Maximum number of bytes to be read from
|
||||||
* the beginning of the file. Specifying UINT_MAX
|
* the beginning of the file. Specifying UINT_MAX
|
||||||
* resets the limit to the original end of the stream.
|
* resets the limit to the original end of the stream.
|
||||||
* @return The previously set limit. */
|
* Returns the previously set limit. */
|
||||||
unsigned int SetReadLimit(unsigned int _limit) {
|
unsigned int SetReadLimit(unsigned int _limit) {
|
||||||
unsigned int prev = GetReadLimit();
|
unsigned int prev = GetReadLimit();
|
||||||
if (UINT_MAX == _limit) {
|
if (UINT_MAX == _limit) {
|
||||||
@@ -278,10 +264,9 @@ public:
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
/** Get the current read limit in bytes. Reading over this limit
|
/** Get the current read limit in bytes. Reading over this limit
|
||||||
* accidentally raises an exception.
|
* accidentally raises an exception. */
|
||||||
* @return The current limit. */
|
|
||||||
unsigned int GetReadLimit() const {
|
unsigned int GetReadLimit() const {
|
||||||
return static_cast<unsigned int>(mLimit - mBuffer);
|
return (unsigned int)(mLimit - mBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user