Merge branch 'master' into master
|
@ -0,0 +1,128 @@
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, religion, or sexual identity
|
||||||
|
and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the
|
||||||
|
overall community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or
|
||||||
|
advances of any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email
|
||||||
|
address, without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
.
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series
|
||||||
|
of actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or
|
||||||
|
permanent ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within
|
||||||
|
the community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.0, available at
|
||||||
|
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||||
|
enforcement ladder](https://github.com/mozilla/diversity).
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
https://www.contributor-covenant.org/faq. Translations are available at
|
||||||
|
https://www.contributor-covenant.org/translations.
|
40
Readme.md
|
@ -1,6 +1,8 @@
|
||||||
Open Asset Import Library (assimp)
|
Open Asset Import Library (assimp)
|
||||||
==================================
|
==================================
|
||||||
A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
|
|
||||||
|
Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
|
||||||
|
|
||||||
### Current project status ###
|
### Current project status ###
|
||||||
[![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp)
|
[![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp)
|
||||||
![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
|
![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
|
||||||
|
@ -22,15 +24,19 @@ Additionally, assimp features various __mesh post processing tools__: normals an
|
||||||
### Latest Doc's ###
|
### Latest Doc's ###
|
||||||
Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/).
|
Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/).
|
||||||
|
|
||||||
### Get involved ###
|
### Prebuild binaries ###
|
||||||
This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
|
Please check our [Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib)
|
||||||
<br>
|
|
||||||
You find a bug in the docs? Use [Doc-Repo](https://github.com/assimp/assimp-docs).
|
|
||||||
<br>
|
|
||||||
Please check our Wiki as well: https://github.com/assimp/assimp/wiki
|
|
||||||
|
|
||||||
If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
|
If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
|
||||||
|
|
||||||
|
### Communities ###
|
||||||
|
- Ask a question at [The Assimp-Discussion Board](https://github.com/assimp/assimp/discussions)
|
||||||
|
- Ask on [Assimp-Community on Reddit](https://www.reddit.com/r/Assimp/)
|
||||||
|
- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
|
||||||
|
- Nothing has worked? File a question or an issue-report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues)
|
||||||
|
|
||||||
|
And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
|
||||||
|
|
||||||
#### Supported file formats ####
|
#### Supported file formats ####
|
||||||
You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md)
|
You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md)
|
||||||
|
|
||||||
|
@ -65,28 +71,18 @@ Open Asset Import Library is implemented in C++. The directory structure looks l
|
||||||
/port Ports to other languages and scripts to maintain those.
|
/port Ports to other languages and scripts to maintain those.
|
||||||
/test Unit- and regression tests, test suite of models
|
/test Unit- and regression tests, test suite of models
|
||||||
/tools Tools (old assimp viewer, command line `assimp`)
|
/tools Tools (old assimp viewer, command line `assimp`)
|
||||||
/samples A small number of samples to illustrate possible
|
/samples A small number of samples to illustrate possible use-cases for Assimp
|
||||||
use cases for Assimp
|
|
||||||
|
|
||||||
The source code is organized in the following way:
|
The source code is organized in the following way:
|
||||||
|
|
||||||
code/Common The base implementation for importers and the infrastructure
|
code/Common The base implementation for importers and the infrastructure
|
||||||
|
code/CApi Special implementations which are only used for the C-API
|
||||||
|
code/Geometry A collection of geometry tools
|
||||||
|
code/Material The material system
|
||||||
|
code/PBR An exporter for physical based models
|
||||||
code/PostProcessing The post-processing steps
|
code/PostProcessing The post-processing steps
|
||||||
code/AssetLib/<FormatName> Implementation for import and export for the format
|
code/AssetLib/<FormatName> Implementation for import and export for the format
|
||||||
|
|
||||||
### Where to get help ###
|
|
||||||
To find our documentation, visit [our website](https://assimp.org/) or check out [Wiki](https://github.com/assimp/assimp/wiki)
|
|
||||||
|
|
||||||
If the docs don't solve your problem, you can:
|
|
||||||
- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
|
|
||||||
- Ask on [Assimp-Community on Reddit](https://www.reddit.com/r/Assimp/)
|
|
||||||
- Ask a question at [The Assimp-Discussion Board](https://github.com/assimp/assimp/discussions)
|
|
||||||
- Nothing has worked? File a question or an issue-report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues)
|
|
||||||
|
|
||||||
Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
|
|
||||||
|
|
||||||
And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
|
|
||||||
|
|
||||||
### Contributing ###
|
### Contributing ###
|
||||||
Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
|
Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
|
||||||
a pull request with your changes against the main repository's `master` branch.
|
a pull request with your changes against the main repository's `master` branch.
|
||||||
|
|
|
@ -652,7 +652,7 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
|
||||||
bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
|
bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
|
||||||
const PropertyTable &props = model.Props();
|
const PropertyTable &props = model.Props();
|
||||||
|
|
||||||
const auto zero_epsilon = ai_epsilon;
|
const auto zero_epsilon = Math::getEpsilon<ai_real>();
|
||||||
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
|
const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
|
||||||
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
|
for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
|
||||||
const TransformationComp comp = static_cast<TransformationComp>(i);
|
const TransformationComp comp = static_cast<TransformationComp>(i);
|
||||||
|
|
|
@ -513,21 +513,22 @@ struct Camera : public Object {
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
|
struct Perspective {
|
||||||
|
float aspectRatio; //!<The floating - point aspect ratio of the field of view. (0 = undefined = use the canvas one)
|
||||||
|
float yfov; //!<The floating - point vertical field of view in radians. (required)
|
||||||
|
float zfar; //!<The floating - point distance to the far clipping plane. (required)
|
||||||
|
float znear; //!< The floating - point distance to the near clipping plane. (required)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ortographic {
|
||||||
|
float xmag; //! The floating-point horizontal magnification of the view. (required)
|
||||||
|
float ymag; //! The floating-point vertical magnification of the view. (required)
|
||||||
|
float zfar; //! The floating-point distance to the far clipping plane. (required)
|
||||||
|
float znear; //! The floating-point distance to the near clipping plane. (required)
|
||||||
|
};
|
||||||
union {
|
union {
|
||||||
struct {
|
struct Perspective perspective;
|
||||||
float aspectRatio; //!<The floating - point aspect ratio of the field of view. (0 = undefined = use the canvas one)
|
struct Ortographic ortographic;
|
||||||
float yfov; //!<The floating - point vertical field of view in radians. (required)
|
|
||||||
float zfar; //!<The floating - point distance to the far clipping plane. (required)
|
|
||||||
float znear; //!< The floating - point distance to the near clipping plane. (required)
|
|
||||||
} perspective;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
float xmag; //! The floating-point horizontal magnification of the view. (required)
|
|
||||||
float ymag; //! The floating-point vertical magnification of the view. (required)
|
|
||||||
float zfar; //! The floating-point distance to the far clipping plane. (required)
|
|
||||||
float znear; //! The floating-point distance to the near clipping plane. (required)
|
|
||||||
} ortographic;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Camera() = default;
|
Camera() = default;
|
||||||
|
|
|
@ -565,7 +565,7 @@ struct Accessor : public Object {
|
||||||
inline size_t GetMaxByteSize();
|
inline size_t GetMaxByteSize();
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void ExtractData(T *&outData);
|
size_t ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices = nullptr);
|
||||||
|
|
||||||
void WriteData(size_t count, const void *src_buffer, size_t src_stride);
|
void WriteData(size_t count, const void *src_buffer, size_t src_stride);
|
||||||
void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride);
|
void WriteSparseValues(size_t count, const void *src_data, size_t src_dataStride);
|
||||||
|
|
|
@ -962,14 +962,15 @@ inline size_t Accessor::GetMaxByteSize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void Accessor::ExtractData(T *&outData) {
|
size_t Accessor::ExtractData(T *&outData, const std::vector<unsigned int> *remappingIndices) {
|
||||||
uint8_t *data = GetPointer();
|
uint8_t *data = GetPointer();
|
||||||
if (!data) {
|
if (!data) {
|
||||||
throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
|
throw DeadlyImportError("GLTF2: data is null when extracting data from ", getContextForErrorMessages(id, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size_t usedCount = (remappingIndices != nullptr) ? remappingIndices->size() : count;
|
||||||
const size_t elemSize = GetElementSize();
|
const size_t elemSize = GetElementSize();
|
||||||
const size_t totalSize = elemSize * count;
|
const size_t totalSize = elemSize * usedCount;
|
||||||
|
|
||||||
const size_t stride = GetStride();
|
const size_t stride = GetStride();
|
||||||
|
|
||||||
|
@ -980,18 +981,31 @@ void Accessor::ExtractData(T *&outData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t maxSize = GetMaxByteSize();
|
const size_t maxSize = GetMaxByteSize();
|
||||||
if (count * stride > maxSize) {
|
|
||||||
throw DeadlyImportError("GLTF: count*stride ", (count * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
outData = new T[count];
|
outData = new T[usedCount];
|
||||||
if (stride == elemSize && targetElemSize == elemSize) {
|
|
||||||
memcpy(outData, data, totalSize);
|
if (remappingIndices != nullptr) {
|
||||||
} else {
|
const unsigned int maxIndex = static_cast<unsigned int>(maxSize / stride - 1);
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < usedCount; ++i) {
|
||||||
memcpy(outData + i, data + i * stride, elemSize);
|
size_t srcIdx = (*remappingIndices)[i];
|
||||||
|
if (srcIdx > maxIndex) {
|
||||||
|
throw DeadlyImportError("GLTF: index*stride ", (srcIdx * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
|
||||||
|
}
|
||||||
|
memcpy(outData + i, data + srcIdx * stride, elemSize);
|
||||||
|
}
|
||||||
|
} 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) {
|
||||||
|
memcpy(outData, data, totalSize);
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < usedCount; ++i) {
|
||||||
|
memcpy(outData + i, data + i * stride, elemSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return usedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t src_stride) {
|
inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t src_stride) {
|
||||||
|
|
|
@ -453,6 +453,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
unsigned int k = 0;
|
unsigned int k = 0;
|
||||||
meshOffsets.clear();
|
meshOffsets.clear();
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<unsigned int> usedVertexIndices;
|
||||||
|
std::vector<unsigned int> reverseMappingIndices;
|
||||||
|
std::vector<unsigned int> indexBuffer;
|
||||||
|
|
||||||
for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
|
for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
|
||||||
Mesh &mesh = r.meshes[m];
|
Mesh &mesh = r.meshes[m];
|
||||||
|
|
||||||
|
@ -462,6 +467,50 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
|
for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
|
||||||
Mesh::Primitive &prim = mesh.primitives[p];
|
Mesh::Primitive &prim = mesh.primitives[p];
|
||||||
|
|
||||||
|
Mesh::Primitive::Attributes &attr = prim.attributes;
|
||||||
|
|
||||||
|
// Find out the maximum number of vertices:
|
||||||
|
size_t numAllVertices = 0;
|
||||||
|
if (!attr.position.empty() && attr.position[0]) {
|
||||||
|
numAllVertices = attr.position[0]->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract used vertices:
|
||||||
|
bool useIndexBuffer = prim.indices;
|
||||||
|
std::vector<unsigned int>* vertexRemappingTable = nullptr;
|
||||||
|
if (useIndexBuffer) {
|
||||||
|
size_t count = prim.indices->count;
|
||||||
|
indexBuffer.resize(count);
|
||||||
|
usedVertexIndices.clear();
|
||||||
|
reverseMappingIndices.clear();
|
||||||
|
usedVertexIndices.reserve(count / 3); // this is a very rough heuristic to reduce re-allocations
|
||||||
|
vertexRemappingTable = &usedVertexIndices;
|
||||||
|
Accessor::Indexer data = prim.indices->GetIndexer();
|
||||||
|
if (!data.IsValid()) {
|
||||||
|
throw DeadlyImportError("GLTF: Invalid accessor without data in mesh ", getContextForErrorMessages(mesh.id, mesh.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the vertex remapping table and the modified index buffer (used later instead of the original one)
|
||||||
|
// In case no index buffer is used, the original vertex arrays are being used so no remapping is required in the first place.
|
||||||
|
const unsigned int unusedIndex = ~0u;
|
||||||
|
for (unsigned int i = 0; i < count; ++i) {
|
||||||
|
unsigned int index = data.GetUInt(i);
|
||||||
|
if (index >= numAllVertices) {
|
||||||
|
// Out-of-range indices will be filtered out when adding the faces and then lead to a warning. At this stage, we just keep them.
|
||||||
|
indexBuffer[i] = index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (index >= reverseMappingIndices.size()) {
|
||||||
|
reverseMappingIndices.resize(index + 1, unusedIndex);
|
||||||
|
}
|
||||||
|
if (reverseMappingIndices[index] == unusedIndex) {
|
||||||
|
reverseMappingIndices[index] = static_cast<unsigned int>(usedVertexIndices.size());
|
||||||
|
usedVertexIndices.push_back(index);
|
||||||
|
}
|
||||||
|
indexBuffer[i] = reverseMappingIndices[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
aiMesh *aim = new aiMesh();
|
aiMesh *aim = new aiMesh();
|
||||||
meshes.push_back(std::unique_ptr<aiMesh>(aim));
|
meshes.push_back(std::unique_ptr<aiMesh>(aim));
|
||||||
|
|
||||||
|
@ -491,28 +540,25 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh::Primitive::Attributes &attr = prim.attributes;
|
|
||||||
|
|
||||||
if (!attr.position.empty() && attr.position[0]) {
|
if (!attr.position.empty() && attr.position[0]) {
|
||||||
aim->mNumVertices = static_cast<unsigned int>(attr.position[0]->count);
|
aim->mNumVertices = static_cast<unsigned int>(attr.position[0]->ExtractData(aim->mVertices, vertexRemappingTable));
|
||||||
attr.position[0]->ExtractData(aim->mVertices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!attr.normal.empty() && attr.normal[0]) {
|
if (!attr.normal.empty() && attr.normal[0]) {
|
||||||
if (attr.normal[0]->count != aim->mNumVertices) {
|
if (attr.normal[0]->count != numAllVertices) {
|
||||||
DefaultLogger::get()->warn("Normal count in mesh \"", mesh.name, "\" does not match the vertex count, normals ignored.");
|
DefaultLogger::get()->warn("Normal count in mesh \"", mesh.name, "\" does not match the vertex count, normals ignored.");
|
||||||
} else {
|
} else {
|
||||||
attr.normal[0]->ExtractData(aim->mNormals);
|
attr.normal[0]->ExtractData(aim->mNormals, vertexRemappingTable);
|
||||||
|
|
||||||
// only extract tangents if normals are present
|
// only extract tangents if normals are present
|
||||||
if (!attr.tangent.empty() && attr.tangent[0]) {
|
if (!attr.tangent.empty() && attr.tangent[0]) {
|
||||||
if (attr.tangent[0]->count != aim->mNumVertices) {
|
if (attr.tangent[0]->count != numAllVertices) {
|
||||||
DefaultLogger::get()->warn("Tangent count in mesh \"", mesh.name, "\" does not match the vertex count, tangents ignored.");
|
DefaultLogger::get()->warn("Tangent count in mesh \"", mesh.name, "\" does not match the vertex count, tangents ignored.");
|
||||||
} else {
|
} else {
|
||||||
// generate bitangents from normals and tangents according to spec
|
// generate bitangents from normals and tangents according to spec
|
||||||
Tangent *tangents = nullptr;
|
Tangent *tangents = nullptr;
|
||||||
|
|
||||||
attr.tangent[0]->ExtractData(tangents);
|
attr.tangent[0]->ExtractData(tangents, vertexRemappingTable);
|
||||||
|
|
||||||
aim->mTangents = new aiVector3D[aim->mNumVertices];
|
aim->mTangents = new aiVector3D[aim->mNumVertices];
|
||||||
aim->mBitangents = new aiVector3D[aim->mNumVertices];
|
aim->mBitangents = new aiVector3D[aim->mNumVertices];
|
||||||
|
@ -529,7 +575,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) {
|
for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) {
|
||||||
if (attr.color[c]->count != aim->mNumVertices) {
|
if (attr.color[c]->count != numAllVertices) {
|
||||||
DefaultLogger::get()->warn("Color stream size in mesh \"", mesh.name,
|
DefaultLogger::get()->warn("Color stream size in mesh \"", mesh.name,
|
||||||
"\" does not match the vertex count");
|
"\" does not match the vertex count");
|
||||||
continue;
|
continue;
|
||||||
|
@ -537,7 +583,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
|
|
||||||
auto componentType = attr.color[c]->componentType;
|
auto componentType = attr.color[c]->componentType;
|
||||||
if (componentType == glTF2::ComponentType_FLOAT) {
|
if (componentType == glTF2::ComponentType_FLOAT) {
|
||||||
attr.color[c]->ExtractData(aim->mColors[c]);
|
attr.color[c]->ExtractData(aim->mColors[c], vertexRemappingTable);
|
||||||
} else {
|
} else {
|
||||||
if (componentType == glTF2::ComponentType_UNSIGNED_BYTE) {
|
if (componentType == glTF2::ComponentType_UNSIGNED_BYTE) {
|
||||||
aim->mColors[c] = GetVertexColorsForType<unsigned char>(attr.color[c]);
|
aim->mColors[c] = GetVertexColorsForType<unsigned char>(attr.color[c]);
|
||||||
|
@ -552,13 +598,13 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr.texcoord[tc]->count != aim->mNumVertices) {
|
if (attr.texcoord[tc]->count != numAllVertices) {
|
||||||
DefaultLogger::get()->warn("Texcoord stream size in mesh \"", mesh.name,
|
DefaultLogger::get()->warn("Texcoord stream size in mesh \"", mesh.name,
|
||||||
"\" does not match the vertex count");
|
"\" does not match the vertex count");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]);
|
attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc], vertexRemappingTable);
|
||||||
aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();
|
aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();
|
||||||
|
|
||||||
aiVector3D *values = aim->mTextureCoords[tc];
|
aiVector3D *values = aim->mTextureCoords[tc];
|
||||||
|
@ -583,11 +629,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
Mesh::Primitive::Target &target = targets[i];
|
Mesh::Primitive::Target &target = targets[i];
|
||||||
|
|
||||||
if (needPositions) {
|
if (needPositions) {
|
||||||
if (target.position[0]->count != aim->mNumVertices) {
|
if (target.position[0]->count != numAllVertices) {
|
||||||
ASSIMP_LOG_WARN("Positions of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
|
ASSIMP_LOG_WARN("Positions of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
|
||||||
} else {
|
} else {
|
||||||
aiVector3D *positionDiff = nullptr;
|
aiVector3D *positionDiff = nullptr;
|
||||||
target.position[0]->ExtractData(positionDiff);
|
target.position[0]->ExtractData(positionDiff, vertexRemappingTable);
|
||||||
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
|
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
|
||||||
aiAnimMesh.mVertices[vertexId] += positionDiff[vertexId];
|
aiAnimMesh.mVertices[vertexId] += positionDiff[vertexId];
|
||||||
}
|
}
|
||||||
|
@ -595,11 +641,11 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (needNormals) {
|
if (needNormals) {
|
||||||
if (target.normal[0]->count != aim->mNumVertices) {
|
if (target.normal[0]->count != numAllVertices) {
|
||||||
ASSIMP_LOG_WARN("Normals of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
|
ASSIMP_LOG_WARN("Normals of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
|
||||||
} else {
|
} else {
|
||||||
aiVector3D *normalDiff = nullptr;
|
aiVector3D *normalDiff = nullptr;
|
||||||
target.normal[0]->ExtractData(normalDiff);
|
target.normal[0]->ExtractData(normalDiff, vertexRemappingTable);
|
||||||
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
|
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
|
||||||
aiAnimMesh.mNormals[vertexId] += normalDiff[vertexId];
|
aiAnimMesh.mNormals[vertexId] += normalDiff[vertexId];
|
||||||
}
|
}
|
||||||
|
@ -610,14 +656,14 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
if (!aiAnimMesh.HasNormals()) {
|
if (!aiAnimMesh.HasNormals()) {
|
||||||
// prevent nullptr access to aiAnimMesh.mNormals below when no normals are available
|
// prevent nullptr access to aiAnimMesh.mNormals below when no normals are available
|
||||||
ASSIMP_LOG_WARN("Bitangents of target ", i, " in mesh \"", mesh.name, "\" can't be computed, because mesh has no normals.");
|
ASSIMP_LOG_WARN("Bitangents of target ", i, " in mesh \"", mesh.name, "\" can't be computed, because mesh has no normals.");
|
||||||
} else if (target.tangent[0]->count != aim->mNumVertices) {
|
} else if (target.tangent[0]->count != numAllVertices) {
|
||||||
ASSIMP_LOG_WARN("Tangents of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
|
ASSIMP_LOG_WARN("Tangents of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count");
|
||||||
} else {
|
} else {
|
||||||
Tangent *tangent = nullptr;
|
Tangent *tangent = nullptr;
|
||||||
attr.tangent[0]->ExtractData(tangent);
|
attr.tangent[0]->ExtractData(tangent, vertexRemappingTable);
|
||||||
|
|
||||||
aiVector3D *tangentDiff = nullptr;
|
aiVector3D *tangentDiff = nullptr;
|
||||||
target.tangent[0]->ExtractData(tangentDiff);
|
target.tangent[0]->ExtractData(tangentDiff, vertexRemappingTable);
|
||||||
|
|
||||||
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; ++vertexId) {
|
for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; ++vertexId) {
|
||||||
tangent[vertexId].xyz += tangentDiff[vertexId];
|
tangent[vertexId].xyz += tangentDiff[vertexId];
|
||||||
|
@ -641,20 +687,15 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
aiFace *facePtr = nullptr;
|
aiFace *facePtr = nullptr;
|
||||||
size_t nFaces = 0;
|
size_t nFaces = 0;
|
||||||
|
|
||||||
if (prim.indices) {
|
if (useIndexBuffer) {
|
||||||
size_t count = prim.indices->count;
|
size_t count = indexBuffer.size();
|
||||||
|
|
||||||
Accessor::Indexer data = prim.indices->GetIndexer();
|
|
||||||
if (!data.IsValid()) {
|
|
||||||
throw DeadlyImportError("GLTF: Invalid accessor without data in mesh ", getContextForErrorMessages(mesh.id, mesh.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (prim.mode) {
|
switch (prim.mode) {
|
||||||
case PrimitiveMode_POINTS: {
|
case PrimitiveMode_POINTS: {
|
||||||
nFaces = count;
|
nFaces = count;
|
||||||
facePtr = faces = new aiFace[nFaces];
|
facePtr = faces = new aiFace[nFaces];
|
||||||
for (unsigned int i = 0; i < count; ++i) {
|
for (unsigned int i = 0; i < count; ++i) {
|
||||||
SetFaceAndAdvance1(facePtr, aim->mNumVertices, data.GetUInt(i));
|
SetFaceAndAdvance1(facePtr, aim->mNumVertices, indexBuffer[i]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -667,7 +708,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
}
|
}
|
||||||
facePtr = faces = new aiFace[nFaces];
|
facePtr = faces = new aiFace[nFaces];
|
||||||
for (unsigned int i = 0; i < count; i += 2) {
|
for (unsigned int i = 0; i < count; i += 2) {
|
||||||
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1));
|
SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -676,12 +717,12 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
case PrimitiveMode_LINE_STRIP: {
|
case PrimitiveMode_LINE_STRIP: {
|
||||||
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
|
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
|
||||||
facePtr = faces = new aiFace[nFaces];
|
facePtr = faces = new aiFace[nFaces];
|
||||||
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1));
|
SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[0], indexBuffer[1]);
|
||||||
for (unsigned int i = 2; i < count; ++i) {
|
for (unsigned int i = 2; i < count; ++i) {
|
||||||
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i - 1), data.GetUInt(i));
|
SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[i - 1], indexBuffer[i]);
|
||||||
}
|
}
|
||||||
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
|
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
|
||||||
SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(static_cast<int>(count) - 1), faces[0].mIndices[0]);
|
SetFaceAndAdvance2(facePtr, aim->mNumVertices, indexBuffer[static_cast<int>(count) - 1], faces[0].mIndices[0]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -694,7 +735,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
}
|
}
|
||||||
facePtr = faces = new aiFace[nFaces];
|
facePtr = faces = new aiFace[nFaces];
|
||||||
for (unsigned int i = 0; i < count; i += 3) {
|
for (unsigned int i = 0; i < count; i += 3) {
|
||||||
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
|
SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1], indexBuffer[i + 2]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -705,10 +746,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
// The ordering is to ensure that the triangles are all drawn with the same orientation
|
// The ordering is to ensure that the triangles are all drawn with the same orientation
|
||||||
if ((i + 1) % 2 == 0) {
|
if ((i + 1) % 2 == 0) {
|
||||||
// For even n, vertices n + 1, n, and n + 2 define triangle n
|
// For even n, vertices n + 1, n, and n + 2 define triangle n
|
||||||
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2));
|
SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i + 1], indexBuffer[i], indexBuffer[i + 2]);
|
||||||
} else {
|
} else {
|
||||||
// For odd n, vertices n, n+1, and n+2 define triangle n
|
// For odd n, vertices n, n+1, and n+2 define triangle n
|
||||||
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
|
SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[i], indexBuffer[i + 1], indexBuffer[i + 2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -716,9 +757,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
||||||
case PrimitiveMode_TRIANGLE_FAN:
|
case PrimitiveMode_TRIANGLE_FAN:
|
||||||
nFaces = count - 2;
|
nFaces = count - 2;
|
||||||
facePtr = faces = new aiFace[nFaces];
|
facePtr = faces = new aiFace[nFaces];
|
||||||
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
|
SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[0], indexBuffer[1], indexBuffer[2]);
|
||||||
for (unsigned int i = 1; i < nFaces; ++i) {
|
for (unsigned int i = 1; i < nFaces; ++i) {
|
||||||
SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(i + 1), data.GetUInt(i + 2));
|
SetFaceAndAdvance3(facePtr, aim->mNumVertices, indexBuffer[0], indexBuffer[i + 1], indexBuffer[i + 2]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1195,7 +1195,69 @@ TARGET_USE_COMMON_OUTPUT_DIRECTORY(assimp)
|
||||||
IF (ASSIMP_WARNINGS_AS_ERRORS)
|
IF (ASSIMP_WARNINGS_AS_ERRORS)
|
||||||
MESSAGE(STATUS "Treating all warnings as errors (for assimp library only)")
|
MESSAGE(STATUS "Treating all warnings as errors (for assimp library only)")
|
||||||
IF (MSVC)
|
IF (MSVC)
|
||||||
TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX)
|
|
||||||
|
IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
|
||||||
|
TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror
|
||||||
|
-Wno-unused-function
|
||||||
|
-Wno-microsoft-enum-value
|
||||||
|
-Wno-switch-enum
|
||||||
|
-Wno-covered-switch-default
|
||||||
|
-Wno-reserved-identifier
|
||||||
|
-Wno-c++98-compat-pedantic
|
||||||
|
-Wno-c++98-compat
|
||||||
|
-Wno-documentation
|
||||||
|
-Wno-documentation-unknown-command
|
||||||
|
-Wno-deprecated-dynamic-exception-spec
|
||||||
|
-Wno-undef
|
||||||
|
-Wno-suggest-destructor-override
|
||||||
|
-Wno-suggest-override
|
||||||
|
-Wno-inconsistent-missing-destructor-override
|
||||||
|
-Wno-zero-as-null-pointer-constant
|
||||||
|
-Wno-global-constructors
|
||||||
|
-Wno-exit-time-destructors
|
||||||
|
-Wno-extra-semi-stmt
|
||||||
|
-Wno-missing-prototypes
|
||||||
|
-Wno-old-style-cast
|
||||||
|
-Wno-cast-align
|
||||||
|
-Wno-cast-qual
|
||||||
|
-Wno-float-equal
|
||||||
|
-Wno-implicit-int-float-conversion
|
||||||
|
-Wno-sign-conversion
|
||||||
|
-Wno-implicit-float-conversion
|
||||||
|
-Wno-implicit-int-conversion
|
||||||
|
-Wno-float-conversion
|
||||||
|
-Wno-double-promotion
|
||||||
|
-Wno-unused-macros
|
||||||
|
-Wno-disabled-macro-expansion
|
||||||
|
-Wno-shadow-field
|
||||||
|
-Wno-shadow
|
||||||
|
-Wno-language-extension-token
|
||||||
|
-Wno-header-hygiene
|
||||||
|
-Wno-tautological-value-range-compare
|
||||||
|
-Wno-tautological-type-limit-compare
|
||||||
|
-Wno-missing-noreturn
|
||||||
|
-Wno-missing-variable-declarations
|
||||||
|
-Wno-extra-semi
|
||||||
|
-Wno-nonportable-system-include-path
|
||||||
|
-Wno-undefined-reinterpret-cast
|
||||||
|
-Wno-shift-sign-overflow
|
||||||
|
-Wno-deprecated-copy-with-user-provided-dtor
|
||||||
|
-Wno-deprecated-copy-with-dtor
|
||||||
|
-Wno-deprecated
|
||||||
|
-Wno-format-nonliteral
|
||||||
|
-Wno-format-non-iso
|
||||||
|
-Wno-comma
|
||||||
|
-Wno-unreachable-code-break
|
||||||
|
-Wno-unreachable-code-return
|
||||||
|
-Wno-unreachable-code
|
||||||
|
-Wno-implicit-fallthrough
|
||||||
|
-Wno-unused-template
|
||||||
|
-Wno-undefined-func-template
|
||||||
|
-Wno-declaration-after-statement
|
||||||
|
)
|
||||||
|
ELSE()
|
||||||
|
TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX)
|
||||||
|
ENDIF()
|
||||||
ELSE()
|
ELSE()
|
||||||
TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror)
|
TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
|
@ -103,7 +103,7 @@ int cryptrand(unsigned char *buf, unsigned int len)
|
||||||
unsigned __int64 pentium_tsc[1];
|
unsigned __int64 pentium_tsc[1];
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
|
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP
|
||||||
if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||||
{
|
{
|
||||||
result = CryptGenRandom(provider, len, buf);
|
result = CryptGenRandom(provider, len, buf);
|
||||||
|
@ -111,6 +111,7 @@ int cryptrand(unsigned char *buf, unsigned int len)
|
||||||
if (result)
|
if (result)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (rlen = 0; rlen < (int)len; ++rlen)
|
for (rlen = 0; rlen < (int)len; ++rlen)
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,7 +76,15 @@ if(MSVC)
|
||||||
set(CMAKE_DEBUG_POSTFIX "d")
|
set(CMAKE_DEBUG_POSTFIX "d")
|
||||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||||
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
|
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
|
||||||
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-non-prototype")
|
||||||
|
endif()
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
else()
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
|
||||||
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-non-prototype")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||||
|
@ -88,7 +96,7 @@ if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||||
message(STATUS "to 'zconf.h.included' because this file is included with zlib")
|
message(STATUS "to 'zconf.h.included' because this file is included with zlib")
|
||||||
message(STATUS "but CMake generates it automatically in the build directory.")
|
message(STATUS "but CMake generates it automatically in the build directory.")
|
||||||
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
|
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)
|
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)
|
||||||
|
|
After Width: | Height: | Size: 228 KiB |
After Width: | Height: | Size: 118 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 40 KiB |
|
@ -65,3 +65,24 @@ TEST(ut3DImportExport, importBoxUC) {
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3D/box.uc", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3D/box.uc", aiProcess_ValidateDataStructure);
|
||||||
ASSERT_NE(nullptr, scene);
|
ASSERT_NE(nullptr, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(ut3DImportExport, importMarRifle) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3D/mar_rifle.uc", aiProcess_ValidateDataStructure);
|
||||||
|
ASSERT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(ut3DImportExport, importMarRifleA) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3D/mar_rifle_a.3d", aiProcess_ValidateDataStructure);
|
||||||
|
ASSERT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(ut3DImportExport, importMarRifleD) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3D/mar_rifle_d.3d", aiProcess_ValidateDataStructure);
|
||||||
|
ASSERT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
|
@ -70,3 +70,115 @@ TEST_F(ut3DSImportExport, import3DSformatdetection) {
|
||||||
|
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importCameraRollAnim) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/CameraRollAnim.3ds", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importCameraRollAnimWithChildObject) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/CameraRollAnimWithChildObject.3ds", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importCubesWithAlpha) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/cubes_with_alpha.3DS", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importCubeWithDiffuseTexture) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/cube_with_diffuse_texture.3DS", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importCubeWithSpecularTexture) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/cube_with_specular_texture.3DS", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importRotatingCube) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/RotatingCube.3DS", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importTargetCameraAnim) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/TargetCameraAnim.3ds", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importTest1) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/test1.3ds", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importCartWheel) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/cart_wheel.3DS", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importGranate) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/Granate.3DS", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importJeep1) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/jeep1.3ds", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importMarRifle) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/mar_rifle.3ds", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importMp5Sil) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/mp5_sil.3ds", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(ut3DSImportExport, importPyramob) {
|
||||||
|
::Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/3DS/pyramob.3DS", aiProcess_ValidateDataStructure);
|
||||||
|
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
|
@ -55,6 +55,20 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(utBVHImportExport, importBlenFromFileTest) {
|
TEST_F(utBVHImportExport, import01_01) {
|
||||||
EXPECT_TRUE(importerTest());
|
EXPECT_TRUE(importerTest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(utBVHImportExport, import01_03) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/BVH/01_03.bvh", aiProcess_ValidateDataStructure);
|
||||||
|
ASSERT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(utBVHImportExport, importBoxingToes) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/BVH/Boxing_Toes.bvh", aiProcess_ValidateDataStructure);
|
||||||
|
ASSERT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
|
@ -71,3 +71,17 @@ TEST_F(utDXFImporterExporter, issue2229) {
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/DXF/issue_2229.dxf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/DXF/issue_2229.dxf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(utDXFImporterExporter, importWuson) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/DXF/wuson.dxf", aiProcess_ValidateDataStructure);
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(utDXFImporterExporter, importRifle) {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_NONBSD_DIR "/DXF/rifle.dxf", aiProcess_ValidateDataStructure);
|
||||||
|
EXPECT_NE(nullptr, scene);
|
||||||
|
}
|
||||||
|
|
|
@ -380,7 +380,7 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLines) {
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_08.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_08.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
std::array<unsigned int, 5> l1 = { { 0u, 3u, 2u, 1u, 0u } };
|
std::array<unsigned int, 5> l1 = { { 0u, 1u, 2u, 3u, 0u } };
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
||||||
|
@ -394,7 +394,7 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineLoop) {
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_09.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_09.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
std::array<unsigned int, 5> l1 = { { 0, 3u, 2u, 1u, 0u } };
|
std::array<unsigned int, 5> l1 = { { 0, 1u, 2u, 3u, 0u } };
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
||||||
|
@ -408,7 +408,7 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeLineStrip) {
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_10.gltf", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/glTF-Asset-Generator/Mesh_PrimitiveMode/Mesh_PrimitiveMode_10.gltf", aiProcess_ValidateDataStructure);
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
std::array<unsigned int, 5> l1 = { { 0u, 3u, 2u, 1u, 0u } };
|
std::array<unsigned int, 5> l1 = { { 0u, 1u, 2u, 3u, 0u } };
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 2u);
|
||||||
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
for (unsigned int i = 0; i < scene->mMeshes[0]->mNumFaces; ++i) {
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[i].mIndices[0], l1[i]);
|
||||||
|
@ -423,13 +423,13 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesStrip) {
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
|
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
std::array<unsigned int, 3> f1 = { { 0u, 3u, 1u } };
|
std::array<unsigned int, 3> f1 = { { 0u, 1u, 2u } };
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<unsigned int, 3> f2 = { { 1u, 3u, 2u } };
|
std::array<unsigned int, 3> f2 = { { 2u, 1u, 3u } };
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
||||||
|
@ -443,13 +443,13 @@ TEST_F(utglTF2ImportExport, importglTF2PrimitiveModeTrianglesFan) {
|
||||||
EXPECT_NE(nullptr, scene);
|
EXPECT_NE(nullptr, scene);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
EXPECT_EQ(scene->mMeshes[0]->mNumVertices, 4u);
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
|
EXPECT_EQ(scene->mMeshes[0]->mNumFaces, 2u);
|
||||||
std::array<unsigned int, 3> f1 = { { 0u, 3u, 2u } };
|
std::array<unsigned int, 3> f1 = { { 0u, 1u, 2u } };
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mNumIndices, 3u);
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[0].mIndices[i], f1[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<unsigned int, 3> f2 = { { 0u, 2u, 1u } };
|
std::array<unsigned int, 3> f2 = { { 0u, 2u, 3u } };
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mNumIndices, 3u);
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
EXPECT_EQ(scene->mMeshes[0]->mFaces[1].mIndices[i], f2[i]);
|
||||||
|
|