Model.h#
Contains the class representing an entire Scene, or Model.
Includes#
PVRAssets/model/Animation.h
PVRAssets/model/Camera.h
PVRAssets/model/FormattedUserData.h
PVRAssets/model/Light.h
PVRAssets/model/Mesh.h
Included By#
Namespaces#
Classes#
Enums#
Functions#
Typedefs#
Source Code#
#pragma once
#include "PVRAssets/model/FormattedUserData.h"
#include "PVRAssets/model/Camera.h"
#include "PVRAssets/model/Animation.h"
#include "PVRAssets/model/Light.h"
#include "PVRAssets/model/Mesh.h"
namespace pvr {
class Stream;
namespace assets {
class Model;
class Mesh;
class Camera;
class Light;
typedef std::shared_ptr<Model> ModelHandle;
typedef std::shared_ptr<Mesh> MeshHandle;
typedef std::shared_ptr<Camera> CameraHandle;
typedef std::shared_ptr<Light> LightHandle;
struct Skeleton
{
std::string name;
std::vector<uint32_t> bones;
std::vector<glm::mat4> invBindMatrices;
};
enum class ModelFileFormat
{
UNKNOWN = 0,
POD,
GLTF,
};
class Model
{
public:
typedef assets::Mesh Mesh;
class Node
{
public:
struct InternalData
{
StringHash name;
uint32_t objectIndex;
uint32_t materialIndex;
uint32_t parentIndex;
UInt8Buffer userData;
CustomData formattedUserData;
enum TransformFlags
{
Identity = 0,
Scale = 0x01,
Rotate = 0x02,
Translate = 0x04,
SRT = Scale | Rotate | Translate,
Matrix = 64,
};
// CONTAINS
float frameTransform[16];
// NODE'S LOCAL SPACE SRT
glm::vec3 scale;
glm::quat rotation;
glm::vec3 translation;
uint32_t transformFlags;
int32_t skin;
bool hasAnimation;
glm::vec3& getFrameScaleAnimation() { return *(glm::vec3*)frameTransform; }
glm::quat& getFrameRotationAnimation() { return *(glm::quat*)(&frameTransform[3]); }
glm::vec3& getFrameTranslationAnimation() { return *(glm::vec3*)(&frameTransform[7]); }
const glm::vec3& getFrameScaleAnimation() const { return *(glm::vec3*)frameTransform; }
const glm::quat& getFrameRotationAnimation() const { return *(glm::quat*)(&frameTransform[3]); }
const glm::vec3& getFrameTranslationAnimation() const { return *(glm::vec3*)(&frameTransform[7]); }
glm::vec3& getScale() { return scale; }
glm::quat& getRotate() { return rotation; }
glm::vec3& getTranslation() { return translation; }
const glm::vec3& getScale() const { return scale; }
const glm::quat& getRotate() const { return rotation; }
const glm::vec3& getTranslation() const { return translation; }
InternalData()
: objectIndex(static_cast<uint32_t>(-1)), materialIndex(static_cast<uint32_t>(-1)), parentIndex(static_cast<uint32_t>(-1)), scale(1.0f), translation(0.0f)
{
transformFlags = TransformFlags::Identity;
hasAnimation = false;
getFrameScaleAnimation() = scale;
getFrameRotationAnimation() = glm::quat();
getFrameTranslationAnimation() = translation;
}
};
public:
uint32_t getObjectId() const { return _data.objectIndex; }
const StringHash& getName() const { return _data.name; }
uint32_t getParentID() const { return _data.parentIndex; }
uint32_t getMaterialIndex() const { return _data.materialIndex; }
void setMaterialIndex(uint32_t materialId) { _data.materialIndex = materialId; }
const uint8_t* getUserData() const { return _data.userData.data(); }
const CustomData& getFormattedUserData() const { return _data.formattedUserData; }
uint32_t getUserDataSize() const { return static_cast<uint32_t>(_data.userData.size()); }
void setIndex(uint32_t index) { _data.objectIndex = index; }
void setName(const StringHash& name) { _data.name = name; }
void setParentID(uint32_t parentID) { _data.parentIndex = parentID; }
void setUserData(uint32_t size, const char* data)
{
_data.userData.resize(size);
memcpy(_data.userData.data(), data, size);
}
void setFormattedUserData(const CustomData& cd) { _data.formattedUserData = cd; }
InternalData& getInternalData() { return _data; }
const InternalData& getInternalData() const { return _data; }
private:
InternalData _data;
};
class Texture
{
public:
Texture() {}
Texture(const StringHash&& name) : _name(std::move(name)) {}
const pvr::StringHash& getName() const { return _name; }
pvr::StringHash& getName() { return _name; }
void setName(const StringHash& name) { this->_name = name; }
private:
pvr::StringHash _name;
};
class Material
{
public:
Material() : _defaultSemantics(*this) {}
enum BlendFunction
{
BlendFuncZero = 0,
BlendFuncOne,
BlendFuncFactor,
BlendFuncOneMinusBlendFactor,
BlendFuncSrcColor = 0x0300,
BlendFuncOneMinusSrcColor,
BlendFuncSrcAlpha,
BlendFuncOneMinusSrcAlpha,
BlendFuncDstAlpha,
BlendFuncOneMinusDstAlpha,
BlendFuncDstColor,
BlendFuncOneMinusDstColor,
BlendFuncSrcAlphaSaturate,
BlendFuncConstantColor = 0x8001,
BlendFuncOneMinusConstantColor,
BlendFuncConstantAlpha,
BlendFuncOneMinusConstantAlpha
};
enum BlendOperation
{
BlendOpAdd = 0x8006,
BlendOpMin,
BlendOpMax,
BlendOpSubtract = 0x800A,
BlendOpReverseSubtract
};
//"BLENDFUNCTION", BlendFunction
//"BLENDOP", BlendOperation
//"DIFFUSETEXTURE",
//"SPECULARTEXTURE",
//"NORMALTEXTURE",
//"EMISSIVETEXTURE",
//"GLOSSINESSTEXTURE",
//"OPACITYTEXTURE",
//"REFLECTIONTEXTURE",
//"REFRACTIONTEXTURE",
//"OPACITY",
//"AMBIENTCOLOR",
//"DIFFUSECOLOR",
//"SPECULARCOLOR",
//"SHININESS",
//"EFFECTFILE",
//"EFFECTNAME",
//"BLENDFUNCSRCCOLOR"
//"BLENDFUNCSRCALPHA"
//"BLENDFUNCDSTCOLOR"
//"BLENDFUNCDSTALPHA"
//"BLENDCOLOR"
//"BLENDFACTOR"
//"FLAGS"
//"USERDATA"
//-------- PBR COMMON SEMANTICS ---------
//"METALLICITY"
//"ROUGHNESS"
//"METALLICITYTEXTURE"
//"ROUGHNESSTEXTURE"
//-------- PBR POD SEMANTICS -------------
//"IOR"
//"FRESENEL"
//"SSSCATERING"
//"SSCATERINGDEPTH"
//"SSCATERINGCOLOR"
//"EMISSIONLUMINANCE"
//"EMISSIONKELVIN"
//"ANISTROPHY"
//-------- PBR GLTF SEMANTICS ------------
// "METALLICBASECOLOR"
// "EMISSIVECOLOR"
// "ALPHACUTOFF"
// "DOUBLESIDED"
// "NORMALTEXTURE"
// "OCCLUSIONTEXTURE"
//------- PBR SEMANTICS ----------
//"REFLECTIVITY"
//"EMISSION"
struct InternalData
{
std::map<StringHash, FreeValue> materialSemantics;
std::map<StringHash, uint32_t> textureIndices;
StringHash name;
StringHash effectFile;
StringHash effectName;
UInt8Buffer userData;
CustomData formattedUserData;
};
class PBRSemantics
{
public:
virtual ~PBRSemantics() {}
PBRSemantics(Material& mat) : _material(mat) {}
uint32_t getOcclusionTextureIndex() const { return _material.getTextureIndex("OCCLUSIONTEXTURE"); }
void setOcclusionTextureIndex(uint32_t index) { _material.setTextureIndex("OCCLUSIONTEXTURE", index); }
uint32_t getNormalTextureIndex() const { return _material.getTextureIndex("NORMALTEXTURE"); }
void setNormalTextureIndex(uint32_t index) { _material.setTextureIndex("NORMALTEXTURE", index); }
glm::vec3 getEmissiveColor() const { return _material.getMaterialAttributeWithDefault("EMISSIVECOLOR", glm::vec3(0.f)); }
void setEmissiveColor(const glm::vec3& color)
{
FreeValue value;
value.setValue(color);
_material.setMaterialAttribute("EMISSIVECOLOR", value);
}
void setEmissiveTextureIndex(uint32_t index) { _material.setTextureIndex("EMISSIVETEXTURE", index); }
uint32_t getEmissiveTextureIndex() const { return _material.getTextureIndex("EMISSIVETEXTURE"); }
void setRoughnessTextureIndex(uint32_t index) { _material.setTextureIndex("ROUGHNESSTEXTURE", index); }
uint32_t getRoughnessTextureIndex() { return _material.getTextureIndex("ROUGHNESSTEXTURE"); }
void setMetallicityTextureIndex(uint32_t index) { _material.setTextureIndex("METALLICITYTEXTURE", index); }
uint32_t getMetallicityTextureIndex() { return _material.getTextureIndex("METALLICITYTEXTURE"); }
protected:
Material& _material;
};
class PODMetallicRoughnessSemantics : public PBRSemantics
{
public:
PODMetallicRoughnessSemantics(Material& mat) : PBRSemantics(mat) {}
void setEmissionLuminance(float luminance) { _material.setMaterialAttribute("EMISSIONLUMINANCE", FreeValue(luminance)); }
float getEmissionLuminance() const { return _material.getMaterialAttributeWithDefault("EMISSIONLUMINANCE", 0.f); }
void setEmissionKelvin(float kelvin) { _material.setMaterialAttribute("EMISSIONKELVIN", kelvin); }
float getEmissionKelvin() const { return _material.getMaterialAttributeWithDefault("EMISSIONKELVIN", 1.f); }
};
enum class GLTFAlphaMode
{
Opaque, //< The alpha value is ignored and the rendered output is fully opaque.
Mask, //< The rendered output is either fully opaque or fully transparent depending on the alpha value and the specified alpha cutoff value.
Blend, //<The alpha value is used to composite the source and destination areas. The rendered output is combined with the background using the normal painting operation
//(i.e. the Porter and Duff over operator).
};
class GLTFMetallicRoughnessSemantics : public PBRSemantics
{
public:
GLTFMetallicRoughnessSemantics(Material& material) : PBRSemantics(material) {}
void setBaseColor(const glm::vec4& color)
{
FreeValue value;
value.setValue(color);
_material.setMaterialAttribute("METALLICBASECOLOR", value);
}
glm::vec4 getBaseColor() const { return _material.getMaterialAttributeWithDefault<glm::vec4>("METALLICBASECOLOR", glm::vec4(1.f)); }
void setBaseColorTextureIndex(uint32_t index) { _material.setTextureIndex("DIFFUSETEXTURE", index); }
uint32_t getBaseColorTextureIndex() const { return _material.getTextureIndex("DIFFUSETEXTURE"); }
void setMetallicity(float metallic)
{
FreeValue value;
value.setValue(metallic);
_material.setMaterialAttribute("METALLICITY", value);
}
float getMetallicity() const { return _material.getMaterialAttributeWithDefault<float>("METALLICITY", 0); }
void setRoughness(float roughness)
{
FreeValue value;
value.setValue(roughness);
_material.setMaterialAttribute("ROUGHNESS", value);
}
float getRoughness() const { return _material.getMaterialAttributeWithDefault<float>("ROUGHNESS", 0); }
float getAlphaCutOff() const { return _material.getMaterialAttributeWithDefault("ALPHACUTOFF", 0.5f); }
void setAlphaCutOff(float cutoff)
{
FreeValue val;
val.setValue(cutoff);
_material.setMaterialAttribute("ALPHACUTOFF", val);
}
bool isDoubleSided() const { return static_cast<bool>(_material.getMaterialAttributeWithDefault("DOUBLESIDED", 1)); }
void setDoubleSided(bool doubleSided)
{
FreeValue val;
val.setValue(static_cast<uint32_t>(doubleSided));
_material.setMaterialAttribute("DOUBLESIDED", val);
}
GLTFAlphaMode getAlphaMode()
{
return static_cast<GLTFAlphaMode>(_material.getMaterialAttributeWithDefault("ALPHAMODE", static_cast<uint32_t>(GLTFAlphaMode::Opaque)));
}
void setAlphaMode(GLTFAlphaMode alphaMode) const
{
FreeValue val;
val.setValue(static_cast<uint32_t>(alphaMode));
_material.setMaterialAttribute("ALPHAMODE", val);
}
};
class DefaultMaterialSemantics
{
public:
DefaultMaterialSemantics(const Material& material) : material(&material) {}
glm::vec3 getAmbient() const { return material->getMaterialAttributeWithDefault<glm::vec3>("AMBIENT", glm::vec3(0.f, 0.f, 0.f)); }
glm::vec3 getDiffuse() const { return material->getMaterialAttributeWithDefault<glm::vec3>("DIFFUSE", glm::vec3(1.f, 1.f, 1.f)); }
glm::vec3 getSpecular() const { return material->getMaterialAttributeWithDefault<glm::vec3>("SPECULAR", glm::vec3(0.f, 0.f, 0.f)); }
float getShininess() const { return material->getMaterialAttributeWithDefault<float>("SHININESS", 0.f); }
uint32_t getDiffuseTextureIndex() const
{
static const StringHash diffuseTexSemantic("DIFFUSETEXTURE");
return material->getTextureIndex(diffuseTexSemantic);
}
uint32_t getAmbientTextureIndex() const
{
static const StringHash diffuseTexSemantic("AMBIENTTEXTURE");
return material->getTextureIndex(diffuseTexSemantic);
}
uint32_t getSpecularColorTextureIndex() const
{
static const StringHash diffuseTexSemantic("SPECULARCOLORTEXTURE");
return material->getTextureIndex(diffuseTexSemantic);
}
uint32_t getSpecularLevelTextureIndex() const
{
static const StringHash diffuseTexSemantic("SPECULARLEVELTEXTURE");
return material->getTextureIndex(diffuseTexSemantic);
}
uint32_t getBumpMapTextureIndex() const
{
static const StringHash diffuseTexSemantic("NORMALTEXTURE");
return material->getTextureIndex(diffuseTexSemantic);
}
uint32_t getEmissiveTextureIndex() const
{
static const StringHash diffuseTexSemantic("EMISSIVETEXTURE");
return material->getTextureIndex(diffuseTexSemantic);
}
uint32_t getGlossinessTextureIndex() const
{
static const StringHash diffuseTexSemantic("GLOSSINESSTEXTURE");
return material->getTextureIndex(diffuseTexSemantic);
}
uint32_t getOpacityTextureIndex() const
{
static const StringHash diffuseTexSemantic("OPACITYTEXTURE");
return material->getTextureIndex(diffuseTexSemantic);
}
uint32_t getReflectionTextureIndex() const
{
static const StringHash diffuseTexSemantic("REFLECTIONTEXTURE");
return material->getTextureIndex(diffuseTexSemantic);
}
uint32_t getRefractionTextureIndex() const
{
static const StringHash diffuseTexSemantic("REFRACTIONTEXTURE");
return material->getTextureIndex(diffuseTexSemantic);
}
float getOpacity() const { return material->getMaterialAttributeWithDefault<float>("OPACITY", 1.f); }
BlendFunction getBlendSrcRGB() const { return material->getMaterialAttributeWithDefault<BlendFunction>("BLENDSRCCOLOR", BlendFunction::BlendFuncOne); }
BlendFunction getBlendSrcA() const { return material->getMaterialAttributeWithDefault<BlendFunction>("BLENDSRCALPHA", BlendFunction::BlendFuncOne); }
BlendFunction getBlendDstRGB() const { return material->getMaterialAttributeWithDefault<BlendFunction>("BLENDDSTCOLOR", BlendFunction::BlendFuncZero); }
BlendFunction getBlendDstA() const { return material->getMaterialAttributeWithDefault<BlendFunction>("BLENDDSTALPHA", BlendFunction::BlendFuncZero); }
BlendOperation getBlendOpRGB() const { return material->getMaterialAttributeWithDefault<BlendOperation>("BLENDOPCOLOR", BlendOperation::BlendOpAdd); }
BlendOperation getBlendOpA() const { return material->getMaterialAttributeWithDefault<BlendOperation>("BLENDOPALPHA", BlendOperation::BlendOpAdd); }
glm::vec4 getBlendColor() const { return material->getMaterialAttributeWithDefault<glm::vec4>("BLENDCOLOR", glm::vec4(0.f, 0.f, 0.f, 0.f)); }
glm::vec4 getBlendFactor() const { return material->getMaterialAttributeWithDefault<glm::vec4>("BLENDFACTOR", glm::vec4(0.f, 0.f, 0.f, 0.f)); }
private:
const Material* material;
};
public:
const DefaultMaterialSemantics& defaultSemantics() const { return _defaultSemantics; }
void setMaterialAttribute(const StringHash& semantic, const FreeValue& value) { _data.materialSemantics[semantic] = value; }
const FreeValue* getMaterialAttribute(const StringHash& semantic) const
{
auto it = _data.materialSemantics.find(semantic);
if (it != _data.materialSemantics.end()) { return &it->second; }
return nullptr;
}
template<typename Type>
const Type getMaterialAttributeWithDefault(const StringHash& semantic, const Type& defaultAttrib) const
{
auto* val = getMaterialAttribute(semantic);
if (val) { return val->interpretValueAs<Type>(); }
return defaultAttrib;
}
template<typename Type>
const Type* getMaterialAttributeAs(const StringHash& semantic) const
{
auto* val = getMaterialAttribute(semantic);
if (val) { return &val->interpretValueAs<Type>(); }
return NULL;
}
bool hasSemantic(const StringHash& semantic) const { return hasMaterialTexture(semantic) || hasMaterialAttribute(semantic); }
bool hasMaterialTexture(const StringHash& semantic) const { return getTextureIndex(semantic) != static_cast<uint32_t>(-1); }
bool hasMaterialAttribute(const StringHash& semantic) const { return getMaterialAttribute(semantic) != NULL; }
void setEffectName(const StringHash& name) { _data.effectName = name; }
void setEffectFile(const StringHash& name) { _data.effectFile = name; }
uint32_t getTextureIndex(const StringHash& semantic) const
{
auto it = _data.textureIndices.find(semantic);
return (it == _data.textureIndices.end()) ? -1 : it->second;
}
void setTextureIndex(const StringHash& semantic, uint32_t index) { _data.textureIndices[semantic] = index; }
const StringHash& getName() const { return this->_data.name; }
const StringHash& getEffectFile() const { return _data.effectFile; }
const StringHash& getEffectName() const { return _data.effectName; }
InternalData& getInternalData() { return _data; }
const InternalData& getInternalData() const { return _data; }
private:
UInt8Buffer userData;
InternalData _data;
DefaultMaterialSemantics _defaultSemantics;
};
struct InternalData
{
std::map<StringHash, FreeValue> semantics;
float clearColor[3];
float ambientColor[3];
std::vector<Mesh> meshes;
std::vector<Camera> cameras;
std::vector<Light> lights;
std::vector<Texture> textures;
std::vector<Material> materials;
std::vector<Node> nodes;
std::vector<Skeleton> skeletons;
std::vector<AnimationData> animationsData;
std::vector<AnimationInstance> animationInstances;
uint32_t numMeshNodes;
uint32_t numLightNodes;
uint32_t numCameraNodes;
uint32_t numFrames;
float currentFrame;
float FPS;
UInt8Buffer userData;
float units;
uint32_t flags;
std::shared_ptr<void> userDataPtr;
CustomData formattedUserData;
InternalData() : numMeshNodes(0), numLightNodes(0), numCameraNodes(0), numFrames(0), currentFrame(0), FPS(30), units(1), flags(0)
{
memset(clearColor, 0, sizeof(clearColor));
memset(ambientColor, 0, sizeof(ambientColor));
}
};
private:
std::vector<float> cachedFrame;
std::vector<glm::mat4x4> worldMatrixFrameN;
std::vector<glm::mat4x4> worldMatrixFrameZero;
InternalData _data;
public:
const FreeValue* getModelSemantic(const StringHash& semantic) const
{
auto it = _data.semantics.find(semantic);
if (it == _data.semantics.end()) { return NULL; }
return &it->second;
}
const std::shared_ptr<void>& getUserDataPtr() const { return this->_data.userDataPtr; }
std::shared_ptr<void> getUserDataPtr() { return this->_data.userDataPtr; }
void setUserDataPtr(const std::shared_ptr<void>& ptr) { _data.userDataPtr = ptr; }
public:
void releaseVertexData()
{
for (uint32_t i = 0; i < getNumMeshes(); ++i) { releaseVertexData(i); }
}
void releaseVertexData(uint32_t meshId)
{
Mesh& mesh = getMesh(meshId);
for (uint32_t i = 0; i < mesh.getNumDataElements(); ++i) { mesh.removeData(i); }
mesh.getFaces().setData(0, 0);
}
glm::vec3 getLightPosition(uint32_t lightId) const;
size_t getNumAnimationData() const { return _data.animationsData.size(); }
const AnimationData& getAnimationData(uint32_t index) const { return _data.animationsData[index]; }
const AnimationData* getAnimationData(const char* name) const
{
const auto& it =
std::find_if(_data.animationsData.begin(), _data.animationsData.end(), [&](const AnimationData& anim) { return strcmp(name, anim.getAnimationName().c_str()) == 0; });
if (it != _data.animationsData.end()) { return &(*it); }
return nullptr;
}
const AnimationInstance& getAnimationInstance(uint32_t index) const { return _data.animationInstances[index]; }
AnimationInstance& getAnimationInstance(uint32_t index) { return _data.animationInstances[index]; }
size_t getNumAnimationInstances() const { return _data.animationInstances.size(); }
size_t addAnimationInstance(const AnimationInstance& animationInstance)
{
_data.animationInstances.emplace_back(animationInstance);
return _data.animationInstances.size() - 1;
}
glm::mat4x4 getWorldMatrix(uint32_t nodeId) const;
glm::mat4x4 getWorldMatrixNoCache(uint32_t nodeId) const;
glm::mat4x4 getBoneWorldMatrix(uint32_t skinNodeID, uint32_t boneId) const;
glm::mat4x4 toWorldMatrix(uint32_t nodeId, const glm::mat4& localMatrix) const
{
uint32_t parentID = _data.nodes[nodeId].getParentID();
if (parentID == static_cast<uint32_t>(-1)) { return localMatrix; }
else
{
glm::mat4 parentWorld = getWorldMatrix(parentID);
return parentWorld * localMatrix;
}
}
const Skeleton& getSkeleton(uint32_t skeletonIndex) const { return _data.skeletons[skeletonIndex]; }
size_t getNumSkeletons() const { return _data.skeletons.size(); }
const float* getBackgroundColor() const { return _data.clearColor; }
uint32_t getNumCameras() const { return static_cast<uint32_t>(_data.cameras.size()); }
uint32_t getNumCameraNodes() const { return getNumCameras(); /* Will be changed at a future revision */ }
const Camera& getCamera(uint32_t cameraIndex) const
{
assertion(cameraIndex < getNumCameras(), "Invalid camera index");
return _data.cameras[cameraIndex];
}
Camera& getCamera(uint32_t cameraIndex)
{
assertion(cameraIndex < getNumCameras(), "Invalid camera index");
return _data.cameras[cameraIndex];
}
const Node& getCameraNode(uint32_t cameraNodeIndex) const
{
assertion(cameraNodeIndex < getNumCameraNodes(), "Invalid camera node index");
// Camera nodes are after the mesh and light nodes in the array
return getNode(getNodeIdFromCameraId(cameraNodeIndex));
}
Node& getCameraNode(uint32_t cameraNodeIndex)
{
assertion(cameraNodeIndex < getNumCameraNodes(), "Invalid camera node index");
// Camera nodes are after the mesh and light nodes in the array
return getNode(getNodeIdFromCameraId(cameraNodeIndex));
}
size_t getNumAnimations() const { return _data.animationsData.size(); }
uint32_t getNodeIdFromCameraId(uint32_t cameraNodeIndex) const
{
// Camera nodes are after the mesh and light nodes in the array
assertion(cameraNodeIndex < getNumCameraNodes(), "Invalid camera node index");
return getNumMeshNodes() + getNumLights() + cameraNodeIndex;
}
uint32_t getNumLights() const { return static_cast<uint32_t>(_data.lights.size()); }
uint32_t getNumLightNodes() const { return getNumLights(); /* Will be changed at a future revision */ }
const Light& getLight(uint32_t lightIndex) const
{
assertion(lightIndex < getNumLights(), "Invalid light index");
return _data.lights[lightIndex];
}
Light& getLight(uint32_t lightIndex)
{
assertion(lightIndex < getNumLights(), "Invalid light index");
return _data.lights[lightIndex];
}
const Node& getLightNode(uint32_t lightNodeIndex) const
{
assertion(lightNodeIndex < getNumLights(), "Invalid light node index");
// Light nodes are after the mesh nodes in the array
return getNode(getNodeIdFromLightNodeId(lightNodeIndex));
}
uint32_t getNodeIdFromLightNodeId(uint32_t lightNodeIndex) const
{
assertion(lightNodeIndex < getNumLightNodes(), "Invalid light node index");
// Light nodes are after the mesh nodes in the array
return getNumMeshNodes() + lightNodeIndex;
}
uint32_t getNumMeshes() const { return static_cast<uint32_t>(_data.meshes.size()); }
uint32_t getNumMeshNodes() const { return _data.numMeshNodes; }
const Mesh& getMesh(uint32_t meshIndex) const { return _data.meshes[meshIndex]; }
void allocateAnimationsData(uint32_t numAnimation) { _data.animationsData.resize(numAnimation); }
void allocateAnimationInstances(uint32_t numAnimation) { _data.animationInstances.resize(numAnimation); }
Mesh& getMesh(uint32_t index)
{
assertion(index < getNumMeshes(), "Invalid mesh index");
return _data.meshes[index];
}
const Node& getMeshNode(uint32_t meshIndex) const
{
assertion(meshIndex < getNumMeshNodes(), "Invalid mesh index");
// Mesh nodes are at the start of the array
return getNode(meshIndex);
}
Node& getMeshNode(uint32_t meshIndex)
{
assertion(meshIndex < getNumMeshNodes(), "Invalid mesh index");
// Mesh nodes are at the start of the array
return getNode(meshIndex);
}
void connectMeshWithMeshNode(uint32_t meshId, uint32_t meshNodeId) { getMeshNode(meshNodeId).setIndex(meshId); }
void connectMeshWithMeshNodes(uint32_t meshId, uint32_t beginMeshNodeId, uint32_t endMeshNodeId)
{
for (uint32_t i = beginMeshNodeId; i <= endMeshNodeId; ++i) { connectMeshWithMeshNode(meshId, i); }
}
void assignMaterialToMeshNodes(uint32_t materialIndex, uint32_t beginMeshNodeId, uint32_t endMeshNodeId)
{
for (uint32_t i = beginMeshNodeId; i <= endMeshNodeId; ++i) { getMeshNode(i).setMaterialIndex(materialIndex); }
}
uint32_t getNodeIdForMeshNodeId(uint32_t meshNodeIndex) const
{
debug_assertion(meshNodeIndex < getNumMeshNodes(), "invalid mesh node index");
// Camera nodes are after the mesh and light nodes in the array
return meshNodeIndex;
}
std::vector<Mesh>::iterator beginMeshes() { return _data.meshes.begin(); }
std::vector<Mesh>::iterator endMeshes() { return _data.meshes.end(); }
std::vector<Mesh>::const_iterator beginMeshes() const { return _data.meshes.begin(); }
std::vector<Mesh>::const_iterator endMeshes() const { return _data.meshes.end(); }
uint32_t getNumNodes() const { return static_cast<uint32_t>(_data.nodes.size()); }
const Node& getNode(uint32_t index) const { return _data.nodes[index]; }
Node& getNode(uint32_t index) { return _data.nodes[index]; }
uint32_t getNumTextures() const { return static_cast<uint32_t>(_data.textures.size()); }
const Texture& getTexture(uint32_t index) const { return _data.textures[index]; }
uint32_t getNumMaterials() const { return static_cast<uint32_t>(_data.materials.size()); }
const Material& getMaterial(uint32_t index) const { return _data.materials[index]; }
uint32_t addMaterial(const Material& material)
{
_data.materials.emplace_back(material);
return static_cast<uint32_t>(_data.materials.size() - 1);
}
Material& getMaterial(uint32_t index) { return _data.materials[index]; }
uint32_t getNumFrames() const { return _data.numFrames ? _data.numFrames : 1; }
float getCurrentFrame();
void setFPS(float fps) { _data.FPS = fps; }
float getFPS() const { return _data.FPS; }
void setUserData(uint32_t size, const char* data);
void allocCameras(uint32_t count);
void allocLights(uint32_t count);
void allocMeshes(uint32_t count);
void allocNodes(uint32_t count);
InternalData& getInternalData() { return _data; }
CustomData& getFormattedUserData() { return _data.formattedUserData; }
void getCameraProperties(uint32_t cameraIdx, float& fov, glm::vec3& from, glm::vec3& to, glm::vec3& up, float frameTimeInMs = 0.f) const;
void getCameraProperties(uint32_t cameraIdx, float& fov, glm::vec3& from, glm::vec3& to, glm::vec3& up, float& nearClip, float& farClip, float frameTimeInMs = 0.f) const;
void getLightDirection(uint32_t lightIdx, glm::vec3& direction) const;
void getLightPosition(uint32_t lightIdx, glm::vec3& position) const;
void getLightPosition(uint32_t lightIdx, glm::vec4& position) const;
void destroy() { _data = InternalData(); }
void allocMeshNodes(uint32_t no);
int32_t addTexture(const Texture& tex)
{
_data.textures.emplace_back(tex);
return static_cast<int32_t>(_data.textures.size()) - 1;
}
};
typedef Model::Material Material;
typedef Model::Node Node;
typedef Model::Mesh::VertexAttributeData VertexAttributeData;
typedef std::shared_ptr<Node> NodeHandle;
typedef std::shared_ptr<Material> MaterialHandle;
inline MeshHandle getMeshHandle(ModelHandle model, uint32_t meshId) { return std::shared_ptr<Mesh>(model, &model->getMesh(meshId)); }
inline MaterialHandle getMaterialHandle(ModelHandle model, uint32_t materialId) { return std::shared_ptr<Material>(model, &model->getMaterial(materialId)); }
inline LightHandle getLightHandle(ModelHandle model, uint32_t lightId) { return std::shared_ptr<Light>(model, &model->getLight(lightId)); }
inline CameraHandle getCameraHandle(ModelHandle model, uint32_t cameraId) { return std::shared_ptr<Camera>(model, &model->getCamera(cameraId)); }
inline NodeHandle getNodeHandle(ModelHandle model, uint32_t nodeId) { return std::shared_ptr<Node>(model, &model->getNode(nodeId)); }
} // namespace assets
} // namespace pvr