merge in changes from web/js branch by hand (bone animation updates)
This commit is contained in:
@@ -83,7 +83,9 @@ namespace polyvox
|
|||||||
const char *const boneName,
|
const char *const boneName,
|
||||||
const char **const meshName,
|
const char **const meshName,
|
||||||
int numMeshTargets,
|
int numMeshTargets,
|
||||||
float frameLengthInMs);
|
float frameLengthInMs,
|
||||||
|
bool isModelSpace);
|
||||||
|
void resetBones(EntityId entityId);
|
||||||
void playAnimation(EntityId e, int index, bool loop, bool reverse, bool replaceActive, float crossfade = 0.3f);
|
void playAnimation(EntityId e, int index, bool loop, bool reverse, bool replaceActive, float crossfade = 0.3f);
|
||||||
void stopAnimation(EntityId e, int index);
|
void stopAnimation(EntityId e, int index);
|
||||||
void setMorphTargetWeights(const char *const entityName, float *weights, int count);
|
void setMorphTargetWeights(const char *const entityName, float *weights, int count);
|
||||||
@@ -95,6 +97,8 @@ namespace polyvox
|
|||||||
utils::Entity findChildEntityByName(
|
utils::Entity findChildEntityByName(
|
||||||
EntityId entityId,
|
EntityId entityId,
|
||||||
const char *entityName);
|
const char *entityName);
|
||||||
|
int getEntityCount(EntityId entity, bool renderableOnly);
|
||||||
|
const char* getEntityNameAt(EntityId entity, int index, bool renderableOnly);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AssetLoader *_assetLoader = nullptr;
|
AssetLoader *_assetLoader = nullptr;
|
||||||
@@ -117,11 +121,5 @@ namespace polyvox
|
|||||||
|
|
||||||
inline void updateTransform(SceneAsset &asset);
|
inline void updateTransform(SceneAsset &asset);
|
||||||
|
|
||||||
void updateBoneTransformFromAnimationBuffer(
|
|
||||||
const BoneAnimation& animation,
|
|
||||||
int frameNumber,
|
|
||||||
FilamentAsset *asset
|
|
||||||
);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ namespace polyvox
|
|||||||
|
|
||||||
void loadIbl(const char *const iblUri, float intensity);
|
void loadIbl(const char *const iblUri, float intensity);
|
||||||
void removeIbl();
|
void removeIbl();
|
||||||
|
void rotateIbl(const math::mat3f & matrix);
|
||||||
|
|
||||||
|
|
||||||
void removeAsset(EntityId asset);
|
void removeAsset(EntityId asset);
|
||||||
void clearAssets();
|
void clearAssets();
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
#endif /* __STDBOOL_H */
|
#endif /* __STDBOOL_H */
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#if defined(__APPLE__) || defined(__EMSCRIPTEN__)
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -67,6 +67,7 @@ extern "C"
|
|||||||
FLUTTER_PLUGIN_EXPORT void set_bloom(const void *const viewer, float strength);
|
FLUTTER_PLUGIN_EXPORT void set_bloom(const void *const viewer, float strength);
|
||||||
FLUTTER_PLUGIN_EXPORT void load_skybox(const void *const viewer, const char *skyboxPath);
|
FLUTTER_PLUGIN_EXPORT void load_skybox(const void *const viewer, const char *skyboxPath);
|
||||||
FLUTTER_PLUGIN_EXPORT void load_ibl(const void *const viewer, const char *iblPath, float intensity);
|
FLUTTER_PLUGIN_EXPORT void load_ibl(const void *const viewer, const char *iblPath, float intensity);
|
||||||
|
FLUTTER_PLUGIN_EXPORT void rotate_ibl(const void *const viewer, float* rotationMatrix);
|
||||||
FLUTTER_PLUGIN_EXPORT void remove_skybox(const void *const viewer);
|
FLUTTER_PLUGIN_EXPORT void remove_skybox(const void *const viewer);
|
||||||
FLUTTER_PLUGIN_EXPORT void remove_ibl(const void *const viewer);
|
FLUTTER_PLUGIN_EXPORT void remove_ibl(const void *const viewer);
|
||||||
FLUTTER_PLUGIN_EXPORT EntityId add_light(const void *const viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows);
|
FLUTTER_PLUGIN_EXPORT EntityId add_light(const void *const viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows);
|
||||||
@@ -113,6 +114,10 @@ extern "C"
|
|||||||
int numMorphTargets,
|
int numMorphTargets,
|
||||||
int numFrames,
|
int numFrames,
|
||||||
float frameLengthInMs);
|
float frameLengthInMs);
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT void reset_to_rest_pose(
|
||||||
|
void *assetManager,
|
||||||
|
EntityId asset);
|
||||||
FLUTTER_PLUGIN_EXPORT void add_bone_animation(
|
FLUTTER_PLUGIN_EXPORT void add_bone_animation(
|
||||||
void *assetManager,
|
void *assetManager,
|
||||||
EntityId asset,
|
EntityId asset,
|
||||||
@@ -121,7 +126,8 @@ extern "C"
|
|||||||
const char *const boneName,
|
const char *const boneName,
|
||||||
const char **const meshNames,
|
const char **const meshNames,
|
||||||
int numMeshTargets,
|
int numMeshTargets,
|
||||||
float frameLengthInMs);
|
float frameLengthInMs,
|
||||||
|
bool isModelSpace);
|
||||||
FLUTTER_PLUGIN_EXPORT bool set_bone_transform(
|
FLUTTER_PLUGIN_EXPORT bool set_bone_transform(
|
||||||
void *assetManager,
|
void *assetManager,
|
||||||
EntityId asset,
|
EntityId asset,
|
||||||
@@ -171,6 +177,8 @@ extern "C"
|
|||||||
FLUTTER_PLUGIN_EXPORT void pick(void *const viewer, int x, int y, EntityId *entityId);
|
FLUTTER_PLUGIN_EXPORT void pick(void *const viewer, int x, int y, EntityId *entityId);
|
||||||
FLUTTER_PLUGIN_EXPORT const char *get_name_for_entity(void *const assetManager, const EntityId entityId);
|
FLUTTER_PLUGIN_EXPORT const char *get_name_for_entity(void *const assetManager, const EntityId entityId);
|
||||||
FLUTTER_PLUGIN_EXPORT const EntityId find_child_entity_by_name(void *const assetManager, const EntityId parent, const char* name);
|
FLUTTER_PLUGIN_EXPORT const EntityId find_child_entity_by_name(void *const assetManager, const EntityId parent, const char* name);
|
||||||
|
FLUTTER_PLUGIN_EXPORT int get_entity_count(void *const assetManager, const EntityId target, bool renderableOnly);
|
||||||
|
FLUTTER_PLUGIN_EXPORT const char* get_entity_name_at(void *const assetManager, const EntityId target, int index, bool renderableOnly);
|
||||||
FLUTTER_PLUGIN_EXPORT void set_recording(void *const viewer, bool recording);
|
FLUTTER_PLUGIN_EXPORT void set_recording(void *const viewer, bool recording);
|
||||||
FLUTTER_PLUGIN_EXPORT void set_recording_output_directory(void *const viewer, const char* outputDirectory);
|
FLUTTER_PLUGIN_EXPORT void set_recording_output_directory(void *const viewer, const char* outputDirectory);
|
||||||
FLUTTER_PLUGIN_EXPORT void ios_dummy();
|
FLUTTER_PLUGIN_EXPORT void ios_dummy();
|
||||||
|
|||||||
@@ -64,14 +64,34 @@ FLUTTER_PLUGIN_EXPORT void set_morph_target_weights_ffi(void* const assetManager
|
|||||||
const float *const morphData,
|
const float *const morphData,
|
||||||
int numWeights
|
int numWeights
|
||||||
);
|
);
|
||||||
|
FLUTTER_PLUGIN_EXPORT bool set_morph_animation_ffi(
|
||||||
|
void *assetManager,
|
||||||
|
EntityId asset,
|
||||||
|
const char *const entityName,
|
||||||
|
const float *const morphData,
|
||||||
|
const int *const morphIndices,
|
||||||
|
int numMorphTargets,
|
||||||
|
int numFrames,
|
||||||
|
float frameLengthInMs);
|
||||||
FLUTTER_PLUGIN_EXPORT bool set_bone_transform_ffi(
|
FLUTTER_PLUGIN_EXPORT bool set_bone_transform_ffi(
|
||||||
void *assetManager,
|
void *assetManager,
|
||||||
EntityId asset,
|
EntityId asset,
|
||||||
const char *entityName,
|
const char *entityName,
|
||||||
const float *const transform,
|
const float *const transform,
|
||||||
const char *boneName);
|
const char *boneName);
|
||||||
|
FLUTTER_PLUGIN_EXPORT void add_bone_animation_ffi(
|
||||||
|
void *assetManager,
|
||||||
|
EntityId asset,
|
||||||
|
const float *const frameData,
|
||||||
|
int numFrames,
|
||||||
|
const char *const boneName,
|
||||||
|
const char **const meshNames,
|
||||||
|
int numMeshTargets,
|
||||||
|
float frameLengthInMs,
|
||||||
|
bool isModelSpace);
|
||||||
FLUTTER_PLUGIN_EXPORT void set_post_processing_ffi(void* const viewer, bool enabled);
|
FLUTTER_PLUGIN_EXPORT void set_post_processing_ffi(void* const viewer, bool enabled);
|
||||||
FLUTTER_PLUGIN_EXPORT void pick_ffi(void* const viewer, int x, int y, EntityId* entityId);
|
FLUTTER_PLUGIN_EXPORT void pick_ffi(void* const viewer, int x, int y, EntityId* entityId);
|
||||||
|
FLUTTER_PLUGIN_EXPORT void reset_to_rest_pose_ffi(void* const assetManager, EntityId entityId);
|
||||||
FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi();
|
FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -62,17 +62,17 @@ namespace polyvox {
|
|||||||
// Use this to construct a dynamic (i.e. non-glTF embedded) bone/joint animation.
|
// Use this to construct a dynamic (i.e. non-glTF embedded) bone/joint animation.
|
||||||
//
|
//
|
||||||
struct BoneAnimation : AnimationStatus {
|
struct BoneAnimation : AnimationStatus {
|
||||||
uint8_t boneIndex;
|
size_t boneIndex;
|
||||||
vector<utils::Entity> meshTargets;
|
vector<utils::Entity> meshTargets;
|
||||||
size_t skinIndex = 0;
|
size_t skinIndex = 0;
|
||||||
int lengthInFrames;
|
int lengthInFrames;
|
||||||
float frameLengthInMs = 0;
|
float frameLengthInMs = 0;
|
||||||
vector<math::quatf> frameData;
|
vector<math::mat4f> frameData;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceneAsset {
|
struct SceneAsset {
|
||||||
FilamentAsset* asset = nullptr;
|
FilamentAsset* asset = nullptr;
|
||||||
|
vector<math::mat4f> initialJointTransforms;
|
||||||
vector<GltfAnimation> gltfAnimations;
|
vector<GltfAnimation> gltfAnimations;
|
||||||
vector<MorphAnimation> morphAnimations;
|
vector<MorphAnimation> morphAnimations;
|
||||||
vector<BoneAnimation> boneAnimations;
|
vector<BoneAnimation> boneAnimations;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ namespace polyvox
|
|||||||
EntityManager &em = EntityManager::get();
|
EntityManager &em = EntityManager::get();
|
||||||
|
|
||||||
_assetLoader = AssetLoader::create({_engine, _ubershaderProvider, _ncm, &em});
|
_assetLoader = AssetLoader::create({_engine, _ubershaderProvider, _ncm, &em});
|
||||||
_gltfResourceLoader->addTextureProvider("image/ktx2", _ktxDecoder);
|
_gltfResourceLoader->addTextureProvider ("image/ktx2", _ktxDecoder);
|
||||||
_gltfResourceLoader->addTextureProvider("image/png", _stbDecoder);
|
_gltfResourceLoader->addTextureProvider("image/png", _stbDecoder);
|
||||||
_gltfResourceLoader->addTextureProvider("image/jpeg", _stbDecoder);
|
_gltfResourceLoader->addTextureProvider("image/jpeg", _stbDecoder);
|
||||||
}
|
}
|
||||||
@@ -121,6 +121,19 @@ namespace polyvox
|
|||||||
_gltfResourceLoader->addResourceData(resourceUris[i], std::move(b));
|
_gltfResourceLoader->addResourceData(resourceUris[i], std::move(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
if (!_gltfResourceLoader->asyncBeginLoad(asset)) {
|
||||||
|
Log("Unknown error loading glTF asset");
|
||||||
|
_resourceLoaderWrapper->free(rbuf);
|
||||||
|
for(auto& rb : resourceBuffers) {
|
||||||
|
_resourceLoaderWrapper->free(rb);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while(_gltfResourceLoader->asyncGetLoadProgress() < 1.0f) {
|
||||||
|
_gltfResourceLoader->asyncUpdateLoad();
|
||||||
|
}
|
||||||
|
#else
|
||||||
// load resources synchronously
|
// load resources synchronously
|
||||||
if (!_gltfResourceLoader->loadResources(asset))
|
if (!_gltfResourceLoader->loadResources(asset))
|
||||||
{
|
{
|
||||||
@@ -132,6 +145,7 @@ namespace polyvox
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
_scene->addEntities(asset->getEntities(), asset->getEntityCount());
|
_scene->addEntities(asset->getEntities(), asset->getEntityCount());
|
||||||
|
|
||||||
@@ -143,6 +157,17 @@ namespace polyvox
|
|||||||
|
|
||||||
SceneAsset sceneAsset(asset);
|
SceneAsset sceneAsset(asset);
|
||||||
|
|
||||||
|
const auto joints = inst->getJointsAt(0);
|
||||||
|
|
||||||
|
TransformManager &transformManager = _engine->getTransformManager();
|
||||||
|
|
||||||
|
for(int i = 0; i < inst->getJointCountAt(0); i++) {
|
||||||
|
const auto joint = joints[i];
|
||||||
|
const auto& jointTransformInstance = transformManager.getInstance(joint);
|
||||||
|
const auto& jointTransform = transformManager.getTransform(jointTransformInstance);
|
||||||
|
sceneAsset.initialJointTransforms.push_back(jointTransform);
|
||||||
|
}
|
||||||
|
|
||||||
utils::Entity e = EntityManager::get().create();
|
utils::Entity e = EntityManager::get().create();
|
||||||
|
|
||||||
EntityId eid = Entity::smuggle(e);
|
EntityId eid = Entity::smuggle(e);
|
||||||
@@ -166,7 +191,7 @@ namespace polyvox
|
|||||||
|
|
||||||
ResourceBuffer rbuf = _resourceLoaderWrapper->load(uri);
|
ResourceBuffer rbuf = _resourceLoaderWrapper->load(uri);
|
||||||
|
|
||||||
Log("Loaded GLB of size %d at URI %s", rbuf.size, uri);
|
Log("Loaded GLB data (%d bytes) from URI %s", rbuf.size, uri);
|
||||||
|
|
||||||
FilamentAsset *asset = _assetLoader->createAsset(
|
FilamentAsset *asset = _assetLoader->createAsset(
|
||||||
(const uint8_t *)rbuf.data, rbuf.size);
|
(const uint8_t *)rbuf.data, rbuf.size);
|
||||||
@@ -181,12 +206,23 @@ namespace polyvox
|
|||||||
|
|
||||||
_scene->addEntities(asset->getEntities(), entityCount);
|
_scene->addEntities(asset->getEntities(), entityCount);
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
if (!_gltfResourceLoader->asyncBeginLoad(asset)) {
|
||||||
|
Log("Unknown error loading glb asset");
|
||||||
|
_resourceLoaderWrapper->free(rbuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while(_gltfResourceLoader->asyncGetLoadProgress() < 1.0f) {
|
||||||
|
_gltfResourceLoader->asyncUpdateLoad();
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!_gltfResourceLoader->loadResources(asset))
|
if (!_gltfResourceLoader->loadResources(asset))
|
||||||
{
|
{
|
||||||
Log("Unknown error loading glb asset");
|
Log("Unknown error loading glb asset");
|
||||||
_resourceLoaderWrapper->free(rbuf);
|
_resourceLoaderWrapper->free(rbuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
auto lights = asset->getLightEntities();
|
auto lights = asset->getLightEntities();
|
||||||
_scene->addEntities(lights, asset->getLightEntityCount());
|
_scene->addEntities(lights, asset->getLightEntityCount());
|
||||||
@@ -203,6 +239,17 @@ namespace polyvox
|
|||||||
|
|
||||||
SceneAsset sceneAsset(asset);
|
SceneAsset sceneAsset(asset);
|
||||||
|
|
||||||
|
const auto joints = inst->getJointsAt(0);
|
||||||
|
|
||||||
|
TransformManager &transformManager = _engine->getTransformManager();
|
||||||
|
|
||||||
|
for(int i = 0; i < inst->getJointCountAt(0); i++) {
|
||||||
|
const auto joint = joints[i];
|
||||||
|
const auto& jointTransformInstance = transformManager.getInstance(joint);
|
||||||
|
const auto& jointTransform = transformManager.getTransform(jointTransformInstance);
|
||||||
|
sceneAsset.initialJointTransforms.push_back(jointTransform);
|
||||||
|
}
|
||||||
|
|
||||||
utils::Entity e = EntityManager::get().create();
|
utils::Entity e = EntityManager::get().create();
|
||||||
EntityId eid = Entity::smuggle(e);
|
EntityId eid = Entity::smuggle(e);
|
||||||
|
|
||||||
@@ -278,7 +325,6 @@ namespace polyvox
|
|||||||
|
|
||||||
void AssetManager::updateAnimations()
|
void AssetManager::updateAnimations()
|
||||||
{
|
{
|
||||||
|
|
||||||
std::lock_guard lock(_animationMutex);
|
std::lock_guard lock(_animationMutex);
|
||||||
RenderableManager &rm = _engine->getRenderableManager();
|
RenderableManager &rm = _engine->getRenderableManager();
|
||||||
|
|
||||||
@@ -287,7 +333,7 @@ namespace polyvox
|
|||||||
for (auto &asset : _assets)
|
for (auto &asset : _assets)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int i = asset.gltfAnimations.size() - 1; i >= 0; i--) {
|
for (int i = ((int)asset.gltfAnimations.size()) - 1; i >= 0; i--) {
|
||||||
|
|
||||||
auto animationStatus = asset.gltfAnimations[i];
|
auto animationStatus = asset.gltfAnimations[i];
|
||||||
|
|
||||||
@@ -295,12 +341,15 @@ namespace polyvox
|
|||||||
|
|
||||||
if (!animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs)
|
if (!animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs)
|
||||||
{
|
{
|
||||||
|
asset.asset->getInstance()->getAnimator()->applyAnimation(animationStatus.index, animationStatus.durationInSecs - 0.001);
|
||||||
|
asset.asset->getInstance()->getAnimator()->updateBoneMatrices();
|
||||||
asset.gltfAnimations.erase(asset.gltfAnimations.begin() + i);
|
asset.gltfAnimations.erase(asset.gltfAnimations.begin() + i);
|
||||||
asset.fadeGltfAnimationIndex = -1;
|
asset.fadeGltfAnimationIndex = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
asset.asset->getInstance()->getAnimator()->applyAnimation(animationStatus.index, elapsedInSecs);
|
asset.asset->getInstance()->getAnimator()->applyAnimation(animationStatus.index, elapsedInSecs);
|
||||||
|
|
||||||
if (asset.fadeGltfAnimationIndex != -1 && elapsedInSecs < asset.fadeDuration)
|
if (asset.fadeGltfAnimationIndex != -1 && elapsedInSecs < asset.fadeDuration)
|
||||||
{
|
{
|
||||||
// cross-fade
|
// cross-fade
|
||||||
@@ -354,19 +403,45 @@ namespace polyvox
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float frameLengthInMs = animationStatus.frameLengthInMs;
|
float elapsedFrames = elapsedInSecs * 1000.0f / animationStatus.frameLengthInMs;
|
||||||
|
|
||||||
int frameNumber = static_cast<int>(elapsedInSecs * 1000.0f / frameLengthInMs) % animationStatus.lengthInFrames;
|
int currFrame = static_cast<int>(elapsedFrames) % animationStatus.lengthInFrames;
|
||||||
|
float delta = elapsedFrames - currFrame;
|
||||||
|
int nextFrame = currFrame;
|
||||||
|
auto restLocalTransform = asset.initialJointTransforms[animationStatus.boneIndex];
|
||||||
|
|
||||||
// offset from the end if reverse
|
// offset from the end if reverse
|
||||||
if (animationStatus.reverse)
|
if (animationStatus.reverse)
|
||||||
{
|
{
|
||||||
frameNumber = animationStatus.lengthInFrames - frameNumber;
|
currFrame = animationStatus.lengthInFrames - currFrame;
|
||||||
|
if(currFrame > 0) {
|
||||||
|
nextFrame = currFrame - 1;
|
||||||
|
} else {
|
||||||
|
nextFrame = 0;
|
||||||
}
|
}
|
||||||
updateBoneTransformFromAnimationBuffer(
|
} else {
|
||||||
animationStatus,
|
if(currFrame < animationStatus.lengthInFrames - 1) {
|
||||||
frameNumber,
|
nextFrame = currFrame + 1;
|
||||||
asset.asset);
|
} else {
|
||||||
|
nextFrame = currFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// simple linear interpolation
|
||||||
|
math::mat4f curr = (1 - delta) * (restLocalTransform * animationStatus.frameData[currFrame]);
|
||||||
|
math::mat4f next = delta * (restLocalTransform * animationStatus.frameData[nextFrame]);
|
||||||
|
math::mat4f localTransform = curr + next;
|
||||||
|
|
||||||
|
auto filamentInstance = asset.asset->getInstance();
|
||||||
|
TransformManager &transformManager = _engine->getTransformManager();
|
||||||
|
|
||||||
|
const Entity joint = filamentInstance->getJointsAt(animationStatus.skinIndex)[animationStatus.boneIndex];
|
||||||
|
|
||||||
|
auto jointTransform = transformManager.getInstance(joint);
|
||||||
|
|
||||||
|
transformManager.setTransform(jointTransform, localTransform);
|
||||||
|
|
||||||
|
asset.asset->getInstance()->getAnimator()->updateBoneMatrices();
|
||||||
|
|
||||||
if (animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs)
|
if (animationStatus.loop && elapsedInSecs >= animationStatus.durationInSecs)
|
||||||
{
|
{
|
||||||
@@ -381,7 +456,6 @@ namespace polyvox
|
|||||||
// - or is it better to add an option for "streaming" mode where we can just return a reference to a mat4 and then update the values directly?
|
// - or is it better to add an option for "streaming" mode where we can just return a reference to a mat4 and then update the values directly?
|
||||||
bool AssetManager::setBoneTransform(EntityId entityId, const char *entityName, int32_t skinIndex, const char* boneName, math::mat4f localTransform)
|
bool AssetManager::setBoneTransform(EntityId entityId, const char *entityName, int32_t skinIndex, const char* boneName, math::mat4f localTransform)
|
||||||
{
|
{
|
||||||
|
|
||||||
std::lock_guard lock(_animationMutex);
|
std::lock_guard lock(_animationMutex);
|
||||||
|
|
||||||
const auto &pos = _entityIdLookup.find(entityId);
|
const auto &pos = _entityIdLookup.find(entityId);
|
||||||
@@ -436,7 +510,6 @@ namespace polyvox
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
utils::Entity joint = filamentInstance->getJointsAt(skinIndex)[boneIndex];
|
utils::Entity joint = filamentInstance->getJointsAt(skinIndex)[boneIndex];
|
||||||
|
|
||||||
if (joint.isNull())
|
if (joint.isNull())
|
||||||
@@ -447,8 +520,8 @@ namespace polyvox
|
|||||||
|
|
||||||
const auto& inverseBindMatrix = filamentInstance->getInverseBindMatricesAt(skinIndex)[boneIndex];
|
const auto& inverseBindMatrix = filamentInstance->getInverseBindMatricesAt(skinIndex)[boneIndex];
|
||||||
|
|
||||||
auto jointTransformInstance = transformManager.getInstance(joint);
|
auto jointTransform = transformManager.getInstance(joint);
|
||||||
auto globalJointTransform = transformManager.getWorldTransform(jointTransformInstance);
|
auto globalJointTransform = transformManager.getWorldTransform(jointTransform);
|
||||||
|
|
||||||
auto inverseGlobalTransform = inverse(
|
auto inverseGlobalTransform = inverse(
|
||||||
transformManager.getWorldTransform(
|
transformManager.getWorldTransform(
|
||||||
@@ -467,47 +540,6 @@ namespace polyvox
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetManager::updateBoneTransformFromAnimationBuffer(
|
|
||||||
const BoneAnimation& animation,
|
|
||||||
int frameNumber,
|
|
||||||
FilamentAsset *asset)
|
|
||||||
{
|
|
||||||
auto filamentInstance = asset->getInstance();
|
|
||||||
TransformManager &transformManager = _engine->getTransformManager();
|
|
||||||
|
|
||||||
RenderableManager &rm = _engine->getRenderableManager();
|
|
||||||
|
|
||||||
auto boneIndex = animation.boneIndex;
|
|
||||||
|
|
||||||
math::mat4f localTransform(animation.frameData[frameNumber]);
|
|
||||||
|
|
||||||
const auto& inverseBindMatrix = filamentInstance->getInverseBindMatricesAt(animation.skinIndex)[boneIndex];
|
|
||||||
|
|
||||||
for(const auto& meshTarget : animation.meshTargets) {
|
|
||||||
|
|
||||||
const Entity joint = filamentInstance->getJointsAt(animation.skinIndex)[animation.boneIndex];
|
|
||||||
|
|
||||||
auto jointInstance = transformManager.getInstance(joint);
|
|
||||||
auto globalJointTransform = transformManager.getWorldTransform(jointInstance);
|
|
||||||
|
|
||||||
|
|
||||||
auto inverseGlobalTransform = inverse(
|
|
||||||
transformManager.getWorldTransform(
|
|
||||||
transformManager.getInstance(meshTarget)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const auto boneTransform = inverseGlobalTransform * globalJointTransform * localTransform * inverseBindMatrix;
|
|
||||||
const auto &renderableInstance = rm.getInstance(meshTarget);
|
|
||||||
rm.setBones(
|
|
||||||
renderableInstance,
|
|
||||||
&boneTransform,
|
|
||||||
1,
|
|
||||||
boneIndex
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssetManager::remove(EntityId entityId)
|
void AssetManager::remove(EntityId entityId)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(_animationMutex);
|
std::lock_guard lock(_animationMutex);
|
||||||
@@ -716,13 +748,45 @@ namespace polyvox
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetManager::resetBones(EntityId entityId) {
|
||||||
|
std::lock_guard lock(_animationMutex);
|
||||||
|
|
||||||
|
const auto &pos = _entityIdLookup.find(entityId);
|
||||||
|
if (pos == _entityIdLookup.end())
|
||||||
|
{
|
||||||
|
Log("ERROR: asset not found for entity.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto &asset = _assets[pos->second];
|
||||||
|
|
||||||
|
auto filamentInstance = asset.asset->getInstance();
|
||||||
|
filamentInstance->getAnimator()->resetBoneMatrices();
|
||||||
|
|
||||||
|
auto skinCount = filamentInstance->getSkinCount();
|
||||||
|
|
||||||
|
TransformManager &transformManager = _engine->getTransformManager();
|
||||||
|
|
||||||
|
for(int skinIndex = 0; skinIndex < skinCount; skinIndex++) {
|
||||||
|
for(int i =0; i < filamentInstance->getJointCountAt(skinIndex);i++) {
|
||||||
|
const Entity joint = filamentInstance->getJointsAt(skinIndex)[i];
|
||||||
|
auto restLocalTransform = asset.initialJointTransforms[i];
|
||||||
|
auto jointTransform = transformManager.getInstance(joint);
|
||||||
|
transformManager.setTransform(jointTransform, restLocalTransform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filamentInstance->getAnimator()->updateBoneMatrices();
|
||||||
|
filamentInstance->getAnimator()->resetBoneMatrices();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool AssetManager::addBoneAnimation(EntityId entityId,
|
bool AssetManager::addBoneAnimation(EntityId entityId,
|
||||||
const float *const frameData,
|
const float *const frameData,
|
||||||
int numFrames,
|
int numFrames,
|
||||||
const char *const boneName,
|
const char *const boneName,
|
||||||
const char **const meshNames,
|
const char **const meshNames,
|
||||||
int numMeshTargets,
|
int numMeshTargets,
|
||||||
float frameLengthInMs)
|
float frameLengthInMs,
|
||||||
|
bool isModelSpace)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(_animationMutex);
|
std::lock_guard lock(_animationMutex);
|
||||||
|
|
||||||
@@ -734,8 +798,6 @@ namespace polyvox
|
|||||||
}
|
}
|
||||||
auto &asset = _assets[pos->second];
|
auto &asset = _assets[pos->second];
|
||||||
|
|
||||||
asset.asset->getInstance()->getAnimator()->resetBoneMatrices();
|
|
||||||
|
|
||||||
auto filamentInstance = asset.asset->getInstance();
|
auto filamentInstance = asset.asset->getInstance();
|
||||||
|
|
||||||
size_t skinCount = filamentInstance->getSkinCount();
|
size_t skinCount = filamentInstance->getSkinCount();
|
||||||
@@ -768,14 +830,50 @@ namespace polyvox
|
|||||||
}
|
}
|
||||||
|
|
||||||
animation.frameData.clear();
|
animation.frameData.clear();
|
||||||
|
const auto& tm = _engine->getTransformManager();
|
||||||
|
const auto& inverseBindMatrix = filamentInstance->getInverseBindMatricesAt(skinIndex)[animation.boneIndex];
|
||||||
|
const auto& bindMatrix = inverse(inverseBindMatrix);
|
||||||
|
math::float3 trans;
|
||||||
|
math::quatf rot;
|
||||||
|
math::float3 scale;
|
||||||
|
decomposeMatrix(inverseBindMatrix, &trans, &rot, &scale);
|
||||||
|
math::float3 btrans;
|
||||||
|
math::quatf brot;
|
||||||
|
math::float3 bscale;
|
||||||
|
decomposeMatrix(bindMatrix, &btrans, &brot, &bscale);
|
||||||
|
// Log("Bind matrix for bone %s is \n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", boneName, bindMatrix[0][0],bindMatrix[1][0],bindMatrix[2][0],bindMatrix[3][0],
|
||||||
|
// bindMatrix[0][1],bindMatrix[1][1],bindMatrix[2][1],bindMatrix[3][1],
|
||||||
|
// bindMatrix[0][2],bindMatrix[1][2],bindMatrix[2][2],bindMatrix[3][2],
|
||||||
|
// bindMatrix[0][3],bindMatrix[1][3],bindMatrix[2][3],bindMatrix[3][3]);
|
||||||
for(int i = 0; i < numFrames; i++) {
|
for(int i = 0; i < numFrames; i++) {
|
||||||
animation.frameData.push_back(math::quatf(
|
math::mat4f frame(
|
||||||
frameData[i*4],
|
frameData[i*16],
|
||||||
frameData[(i*4)+1],
|
frameData[(i*16)+1],
|
||||||
frameData[(i*4)+2],
|
frameData[(i*16)+2],
|
||||||
frameData[(i*4)+3]
|
frameData[(i*16)+3],
|
||||||
));
|
frameData[(i*16)+4],
|
||||||
|
frameData[(i*16)+5],
|
||||||
|
frameData[(i*16)+6],
|
||||||
|
frameData[(i*16)+7],
|
||||||
|
frameData[(i*16)+8],
|
||||||
|
frameData[(i*16)+9],
|
||||||
|
frameData[(i*16)+10],
|
||||||
|
frameData[(i*16)+11],
|
||||||
|
frameData[(i*16)+12],
|
||||||
|
frameData[(i*16)+13],
|
||||||
|
frameData[(i*16)+14],
|
||||||
|
frameData[(i*16)+15]);
|
||||||
|
// if(i == numFrames - 1) { Log("Model transform for bone %s is \n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", boneName,
|
||||||
|
// frame[0][0],frame[1][0],frame[2][0],frame[3][0],
|
||||||
|
// frame[0][1],frame[1][1],frame[2][1],frame[3][1],
|
||||||
|
// frame[0][2],frame[1][2],frame[2][2],frame[3][2],
|
||||||
|
// frame[0][3],frame[1][3],frame[2][3],frame[3][3]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if(isModelSpace) {
|
||||||
|
frame = (math::mat4f(rot) * frame) * math::mat4f(brot);
|
||||||
|
}
|
||||||
|
animation.frameData.push_back(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
animation.frameLengthInMs = frameLengthInMs;
|
animation.frameLengthInMs = frameLengthInMs;
|
||||||
@@ -789,7 +887,6 @@ namespace polyvox
|
|||||||
Log("Mesh target %s for bone animation could not be found", meshNames[i]);
|
Log("Mesh target %s for bone animation could not be found", meshNames[i]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Log("Added mesh target %s", meshNames[i]);
|
|
||||||
animation.meshTargets.push_back(entity);
|
animation.meshTargets.push_back(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,6 +895,7 @@ namespace polyvox
|
|||||||
animation.durationInSecs = (frameLengthInMs * numFrames) / 1000.0f;
|
animation.durationInSecs = (frameLengthInMs * numFrames) / 1000.0f;
|
||||||
animation.lengthInFrames = numFrames;
|
animation.lengthInFrames = numFrames;
|
||||||
animation.frameLengthInMs = frameLengthInMs;
|
animation.frameLengthInMs = frameLengthInMs;
|
||||||
|
animation.skinIndex = 0;
|
||||||
asset.boneAnimations.push_back(animation);
|
asset.boneAnimations.push_back(animation);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1172,4 +1270,63 @@ namespace polyvox
|
|||||||
return _ncm->getName(nameInstance);
|
return _ncm->getName(nameInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AssetManager::getEntityCount(EntityId entityId, bool renderableOnly) {
|
||||||
|
const auto &pos = _entityIdLookup.find(entityId);
|
||||||
|
if (pos == _entityIdLookup.end())
|
||||||
|
{
|
||||||
|
Log("ERROR: asset not found for entity.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto &asset = _assets[pos->second];
|
||||||
|
if(renderableOnly) {
|
||||||
|
int count = 0;
|
||||||
|
const auto& rm = _engine->getRenderableManager();
|
||||||
|
const Entity *entities = asset.asset->getEntities();
|
||||||
|
for(int i=0; i < asset.asset->getEntityCount(); i++) {
|
||||||
|
if(rm.hasComponent(entities[i])) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
return asset.asset->getEntityCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* AssetManager::getEntityNameAt(EntityId entityId, int index, bool renderableOnly) {
|
||||||
|
const auto &pos = _entityIdLookup.find(entityId);
|
||||||
|
if (pos == _entityIdLookup.end())
|
||||||
|
{
|
||||||
|
Log("ERROR: asset not found for entity.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto &asset = _assets[pos->second];
|
||||||
|
int found = -1;
|
||||||
|
|
||||||
|
if(renderableOnly) {
|
||||||
|
int count = 0;
|
||||||
|
const auto& rm = _engine->getRenderableManager();
|
||||||
|
const Entity *entities = asset.asset->getEntities();
|
||||||
|
for(int i=0; i < asset.asset->getEntityCount(); i++) {
|
||||||
|
if(rm.hasComponent(entities[i])) {
|
||||||
|
if(count == index) {
|
||||||
|
found = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
found = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(found >= asset.asset->getEntityCount()) {
|
||||||
|
Log("ERROR: index %d greater than number of child entities.", found);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const utils::Entity entity = asset.asset->getEntities()[found];
|
||||||
|
auto inst = _ncm->getInstance(entity);
|
||||||
|
return _ncm->getName(inst);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace polyvox
|
} // namespace polyvox
|
||||||
|
|||||||
@@ -25,6 +25,9 @@
|
|||||||
|
|
||||||
#include <backend/DriverEnums.h>
|
#include <backend/DriverEnums.h>
|
||||||
#include <backend/platforms/OpenGLPlatform.h>
|
#include <backend/platforms/OpenGLPlatform.h>
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
#include <backend/platforms/PlatformWebGL.h>
|
||||||
|
#endif
|
||||||
#include <filament/ColorGrading.h>
|
#include <filament/ColorGrading.h>
|
||||||
#include <filament/Engine.h>
|
#include <filament/Engine.h>
|
||||||
#include <filament/IndexBuffer.h>
|
#include <filament/IndexBuffer.h>
|
||||||
@@ -131,6 +134,8 @@ namespace polyvox
|
|||||||
#elif TARGET_OS_OSX
|
#elif TARGET_OS_OSX
|
||||||
ASSERT_POSTCONDITION(platform == nullptr, "Custom Platform not supported on macOS");
|
ASSERT_POSTCONDITION(platform == nullptr, "Custom Platform not supported on macOS");
|
||||||
_engine = Engine::create(Engine::Backend::METAL);
|
_engine = Engine::create(Engine::Backend::METAL);
|
||||||
|
#elif defined(__EMSCRIPTEN__)
|
||||||
|
_engine = Engine::create(Engine::Backend::OPENGL, (backend::Platform *)new filament::backend::PlatformWebGL(), (void *)sharedContext, nullptr);
|
||||||
#else
|
#else
|
||||||
_engine = Engine::create(Engine::Backend::OPENGL, (backend::Platform *)platform, (void *)sharedContext, nullptr);
|
_engine = Engine::create(Engine::Backend::OPENGL, (backend::Platform *)platform, (void *)sharedContext, nullptr);
|
||||||
#endif
|
#endif
|
||||||
@@ -154,11 +159,27 @@ namespace polyvox
|
|||||||
Log("View created");
|
Log("View created");
|
||||||
|
|
||||||
setToneMapping(ToneMapping::ACES);
|
setToneMapping(ToneMapping::ACES);
|
||||||
|
|
||||||
Log("Set tone mapping");
|
Log("Set tone mapping");
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
Log("Bloom is disabled on WebGL builds as it causes instability with certain drivers");
|
||||||
|
decltype(_view->getBloomOptions()) opts;
|
||||||
|
opts.enabled = false;
|
||||||
|
_view->setBloomOptions(opts);
|
||||||
|
|
||||||
|
_view->setAmbientOcclusionOptions({.enabled=false});
|
||||||
|
|
||||||
|
_view->setDynamicResolutionOptions({.enabled=false});
|
||||||
|
|
||||||
|
_view->setDithering(filament::Dithering::NONE);
|
||||||
|
_view->setAntiAliasing(filament::AntiAliasing::NONE);
|
||||||
|
_view->setShadowingEnabled(false);
|
||||||
|
_view->setScreenSpaceRefractionEnabled(false);
|
||||||
|
|
||||||
|
#else
|
||||||
setBloom(0.6f);
|
setBloom(0.6f);
|
||||||
Log("Set bloom");
|
Log("Set bloom");
|
||||||
|
#endif
|
||||||
|
|
||||||
_view->setScene(_scene);
|
_view->setScene(_scene);
|
||||||
_view->setCamera(_mainCamera);
|
_view->setCamera(_mainCamera);
|
||||||
@@ -215,7 +236,7 @@ namespace polyvox
|
|||||||
.package(IMAGE_IMAGE_DATA, IMAGE_IMAGE_SIZE)
|
.package(IMAGE_IMAGE_DATA, IMAGE_IMAGE_SIZE)
|
||||||
.build(*_engine);
|
.build(*_engine);
|
||||||
_imageMaterial->setDefaultParameter("showImage", 0);
|
_imageMaterial->setDefaultParameter("showImage", 0);
|
||||||
_imageMaterial->setDefaultParameter("backgroundColor", RgbaType::sRGB, float4(0.5f, 0.5f, 0.5f, 1.0f));
|
_imageMaterial->setDefaultParameter("backgroundColor", RgbaType::sRGB, float4(1.0f, 1.0f, 1.0f, 0.0f));
|
||||||
_imageMaterial->setDefaultParameter("image", _imageTexture, _imageSampler);
|
_imageMaterial->setDefaultParameter("image", _imageTexture, _imageSampler);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
@@ -265,10 +286,14 @@ namespace polyvox
|
|||||||
|
|
||||||
void FilamentViewer::setBloom(float strength)
|
void FilamentViewer::setBloom(float strength)
|
||||||
{
|
{
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
Log("Bloom is disabled on WebGL builds as it causes instability with certain drivers. setBloom will be ignored");
|
||||||
|
#else
|
||||||
decltype(_view->getBloomOptions()) opts;
|
decltype(_view->getBloomOptions()) opts;
|
||||||
opts.enabled = true;
|
opts.enabled = true;
|
||||||
opts.strength = strength;
|
opts.strength = strength;
|
||||||
_view->setBloomOptions(opts);
|
_view->setBloomOptions(opts);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::setToneMapping(ToneMapping toneMapping)
|
void FilamentViewer::setToneMapping(ToneMapping toneMapping)
|
||||||
@@ -481,6 +506,7 @@ namespace polyvox
|
|||||||
|
|
||||||
void FilamentViewer::setBackgroundColor(const float r, const float g, const float b, const float a)
|
void FilamentViewer::setBackgroundColor(const float r, const float g, const float b, const float a)
|
||||||
{
|
{
|
||||||
|
Log("Setting background color to rgba(%f,%f,%f,%f)", r, g, b, a);
|
||||||
_imageMaterial->setDefaultParameter("showImage", 0);
|
_imageMaterial->setDefaultParameter("showImage", 0);
|
||||||
_imageMaterial->setDefaultParameter("backgroundColor", RgbaType::sRGB, float4(r, g, b, a));
|
_imageMaterial->setDefaultParameter("backgroundColor", RgbaType::sRGB, float4(r, g, b, a));
|
||||||
_imageMaterial->setDefaultParameter("transform", _imageScale);
|
_imageMaterial->setDefaultParameter("transform", _imageScale);
|
||||||
@@ -926,6 +952,11 @@ namespace polyvox
|
|||||||
_scene->setIndirectLight(nullptr);
|
_scene->setIndirectLight(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FilamentViewer::rotateIbl(const math::mat3f & matrix) {
|
||||||
|
_indirectLight->setRotation(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FilamentViewer::loadIbl(const char *const iblPath, float intensity)
|
void FilamentViewer::loadIbl(const char *const iblPath, float intensity)
|
||||||
{
|
{
|
||||||
removeIbl();
|
removeIbl();
|
||||||
@@ -994,9 +1025,10 @@ namespace polyvox
|
|||||||
if (_frameCount == 60)
|
if (_frameCount == 60)
|
||||||
{
|
{
|
||||||
// Log("1 sec average for asset animation update %f", _elapsed / 60);
|
// Log("1 sec average for asset animation update %f", _elapsed / 60);
|
||||||
|
Log("Skipped frames : %d", _skippedFrames);
|
||||||
_elapsed = 0;
|
_elapsed = 0;
|
||||||
_frameCount = 0;
|
_frameCount = 0;
|
||||||
Log("Skipped frames : %d", _skippedFrames);
|
_skippedFrames = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer tmr;
|
Timer tmr;
|
||||||
@@ -1007,16 +1039,33 @@ namespace polyvox
|
|||||||
_frameCount++;
|
_frameCount++;
|
||||||
|
|
||||||
// if a manipulator is active, update the active camera orientation
|
// if a manipulator is active, update the active camera orientation
|
||||||
if (_manipulator)
|
if(_manipulator) {
|
||||||
{
|
|
||||||
math::double3 eye, target, upward;
|
math::double3 eye, target, upward;
|
||||||
Camera &cam = _view->getCamera();
|
Camera& cam =_view->getCamera();
|
||||||
_manipulator->getLookAt(&eye, &target, &upward);
|
_manipulator->getLookAt(&eye, &target, &upward);
|
||||||
cam.lookAt(eye, target, upward);
|
cam.lookAt(eye, target, upward);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // TODO - this was an experiment but probably useful to keep for debugging
|
||||||
|
// // if pixelBuffer is provided, we will copy the framebuffer into the pixelBuffer.
|
||||||
|
// if (pixelBuffer)
|
||||||
|
// {
|
||||||
|
// auto pbd = Texture::PixelBufferDescriptor(
|
||||||
|
// pixelBuffer, size_t(1024 * 768 * 4),
|
||||||
|
// Texture::Format::RGBA,
|
||||||
|
// Texture::Type::BYTE, nullptr, callback, data);
|
||||||
|
|
||||||
|
// _renderer->beginFrame(_swapChain, 0);
|
||||||
|
// _renderer->render(_view);
|
||||||
|
// _renderer->readPixels(0, 0, 1024, 768, std::move(pbd));
|
||||||
|
// _renderer->endFrame();
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
// Render the scene, unless the renderer wants to skip the frame.
|
// Render the scene, unless the renderer wants to skip the frame.
|
||||||
if (_renderer->beginFrame(_swapChain, frameTimeInNanos))
|
bool beginFrame = _renderer->beginFrame(_swapChain, frameTimeInNanos);
|
||||||
|
|
||||||
|
if (beginFrame)
|
||||||
{
|
{
|
||||||
_renderer->render(_view);
|
_renderer->render(_view);
|
||||||
|
|
||||||
@@ -1045,15 +1094,16 @@ namespace polyvox
|
|||||||
|
|
||||||
_renderer->readPixels(_rt, 0, 0, vp.width, vp.height, std::move(pbd));
|
_renderer->readPixels(_rt, 0, 0, vp.width, vp.height, std::move(pbd));
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderer->endFrame();
|
_renderer->endFrame();
|
||||||
}
|
#ifdef __EMSCRIPTEN__
|
||||||
else
|
_engine->execute();
|
||||||
{
|
#endif
|
||||||
|
} else {
|
||||||
_skippedFrames++;
|
_skippedFrames++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FilamentViewer::savePng(void* buf, size_t size, int frameNumber) {
|
void FilamentViewer::savePng(void* buf, size_t size, int frameNumber) {
|
||||||
std::lock_guard lock(_recordingMutex);
|
std::lock_guard lock(_recordingMutex);
|
||||||
if(!_recording) {
|
if(!_recording) {
|
||||||
|
|||||||
@@ -76,6 +76,19 @@ extern "C"
|
|||||||
((FilamentViewer *)viewer)->loadIbl(iblPath, intensity);
|
((FilamentViewer *)viewer)->loadIbl(iblPath, intensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT void rotate_ibl(const void *const viewer, float* rotationMatrix) {
|
||||||
|
math::mat3f matrix(rotationMatrix[0], rotationMatrix[1],
|
||||||
|
rotationMatrix[2],
|
||||||
|
rotationMatrix[3],
|
||||||
|
rotationMatrix[4],
|
||||||
|
rotationMatrix[5],
|
||||||
|
rotationMatrix[6],
|
||||||
|
rotationMatrix[7],
|
||||||
|
rotationMatrix[8]);
|
||||||
|
|
||||||
|
((FilamentViewer*)viewer)->rotateIbl(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT void remove_skybox(const void *const viewer)
|
FLUTTER_PLUGIN_EXPORT void remove_skybox(const void *const viewer)
|
||||||
{
|
{
|
||||||
((FilamentViewer *)viewer)->removeSkybox();
|
((FilamentViewer *)viewer)->removeSkybox();
|
||||||
@@ -330,6 +343,10 @@ extern "C"
|
|||||||
return ((AssetManager *)assetManager)->setMorphAnimationBuffer(asset, entityName, morphData, morphIndices, numMorphTargets, numFrames, frameLengthInMs);
|
return ((AssetManager *)assetManager)->setMorphAnimationBuffer(asset, entityName, morphData, morphIndices, numMorphTargets, numFrames, frameLengthInMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT void reset_to_rest_pose(void *assetManager, EntityId entityId) {
|
||||||
|
((AssetManager*)assetManager)->resetBones(entityId);
|
||||||
|
}
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT void add_bone_animation(
|
FLUTTER_PLUGIN_EXPORT void add_bone_animation(
|
||||||
void *assetManager,
|
void *assetManager,
|
||||||
EntityId asset,
|
EntityId asset,
|
||||||
@@ -338,9 +355,10 @@ extern "C"
|
|||||||
const char *const boneName,
|
const char *const boneName,
|
||||||
const char **const meshNames,
|
const char **const meshNames,
|
||||||
int numMeshTargets,
|
int numMeshTargets,
|
||||||
float frameLengthInMs)
|
float frameLengthInMs,
|
||||||
|
bool isModelSpace)
|
||||||
{
|
{
|
||||||
((AssetManager *)assetManager)->addBoneAnimation(asset, frameData, numFrames, boneName, meshNames, numMeshTargets, frameLengthInMs);
|
((AssetManager *)assetManager)->addBoneAnimation(asset, frameData, numFrames, boneName, meshNames, numMeshTargets, frameLengthInMs, isModelSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT void set_post_processing(void *const viewer, bool enabled)
|
FLUTTER_PLUGIN_EXPORT void set_post_processing(void *const viewer, bool enabled)
|
||||||
@@ -492,6 +510,15 @@ extern "C"
|
|||||||
return ((AssetManager *)assetManager)->getNameForEntity(entityId);
|
return ((AssetManager *)assetManager)->getNameForEntity(entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT int get_entity_count(void *const assetManager, const EntityId target, bool renderableOnly) {
|
||||||
|
return ((AssetManager *)assetManager)->getEntityCount(target, renderableOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT const char* get_entity_name_at(void *const assetManager, const EntityId target, int index, bool renderableOnly) {
|
||||||
|
return ((AssetManager *)assetManager)->getEntityNameAt(target, index, renderableOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT void set_recording(void *const viewer, bool recording) {
|
FLUTTER_PLUGIN_EXPORT void set_recording(void *const viewer, bool recording) {
|
||||||
((FilamentViewer*)viewer)->setRecording(recording);
|
((FilamentViewer*)viewer)->setRecording(recording);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,31 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
#define GL_GLEXT_PROTOTYPES
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glext.h>
|
||||||
|
|
||||||
|
#include <emscripten/emscripten.h>
|
||||||
|
#include <emscripten/html5.h>
|
||||||
|
#include <emscripten/threading.h>
|
||||||
|
#include <emscripten/val.h>
|
||||||
|
|
||||||
using namespace polyvox;
|
using namespace polyvox;
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
#include <emscripten/threading.h>
|
||||||
|
#include <emscripten/val.h>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
extern FLUTTER_PLUGIN_EXPORT EMSCRIPTEN_WEBGL_CONTEXT_HANDLE flutter_filament_web_create_gl_context();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
class RenderLoop {
|
class RenderLoop {
|
||||||
public:
|
public:
|
||||||
@@ -63,8 +86,20 @@ public:
|
|||||||
void (*renderCallback)(void *), void *const owner) {
|
void (*renderCallback)(void *), void *const owner) {
|
||||||
_renderCallback = renderCallback;
|
_renderCallback = renderCallback;
|
||||||
_renderCallbackOwner = owner;
|
_renderCallbackOwner = owner;
|
||||||
std::packaged_task<FilamentViewer *()> lambda([&]() mutable {
|
std::packaged_task<FilamentViewer *()> lambda([=]() mutable {
|
||||||
return new FilamentViewer(context, loader, platform, uberArchivePath);
|
#ifdef __EMSCRIPTEN__
|
||||||
|
auto emContext = flutter_filament_web_create_gl_context();
|
||||||
|
|
||||||
|
auto success = emscripten_webgl_make_context_current((EMSCRIPTEN_WEBGL_CONTEXT_HANDLE)emContext);
|
||||||
|
if(success != EMSCRIPTEN_RESULT_SUCCESS) {
|
||||||
|
std::cout << "Failed to make context current." << std::endl;
|
||||||
|
return (FilamentViewer*)nullptr;
|
||||||
|
}
|
||||||
|
_viewer = new FilamentViewer((void* const) emContext, loader, platform, uberArchivePath);
|
||||||
|
#else
|
||||||
|
_viewer = new FilamentViewer(context, loader, platform, uberArchivePath);
|
||||||
|
#endif
|
||||||
|
return _viewer;
|
||||||
});
|
});
|
||||||
auto fut = add_task(lambda);
|
auto fut = add_task(lambda);
|
||||||
fut.wait();
|
fut.wait();
|
||||||
@@ -90,10 +125,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void doRender() {
|
void doRender() {
|
||||||
|
auto now = std::chrono::high_resolution_clock::now();
|
||||||
|
auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
|
||||||
render(_viewer, 0, nullptr, nullptr, nullptr);
|
render(_viewer, 0, nullptr, nullptr, nullptr);
|
||||||
|
_lastRenderTime = std::chrono::high_resolution_clock::now();
|
||||||
if(_renderCallback) {
|
if(_renderCallback) {
|
||||||
_renderCallback(_renderCallbackOwner);
|
_renderCallback(_renderCallbackOwner);
|
||||||
}
|
}
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
emscripten_webgl_commit_frame();
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFrameIntervalInMilliseconds(float frameIntervalInMilliseconds) {
|
void setFrameIntervalInMilliseconds(float frameIntervalInMilliseconds) {
|
||||||
@@ -121,6 +163,7 @@ private:
|
|||||||
std::thread *_t = nullptr;
|
std::thread *_t = nullptr;
|
||||||
std::condition_variable _cond;
|
std::condition_variable _cond;
|
||||||
std::deque<std::function<void()>> _tasks;
|
std::deque<std::function<void()>> _tasks;
|
||||||
|
std::chrono::steady_clock::time_point _lastRenderTime = std::chrono::high_resolution_clock::now();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -453,6 +496,25 @@ void set_morph_target_weights_ffi(void *const assetManager,
|
|||||||
fut.wait();
|
fut.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool set_morph_animation_ffi(
|
||||||
|
void *assetManager,
|
||||||
|
EntityId asset,
|
||||||
|
const char *const entityName,
|
||||||
|
const float *const morphData,
|
||||||
|
const int *const morphIndices,
|
||||||
|
int numMorphTargets,
|
||||||
|
int numFrames,
|
||||||
|
float frameLengthInMs) {
|
||||||
|
std::packaged_task<bool()> lambda(
|
||||||
|
[&] {
|
||||||
|
return set_morph_animation(assetManager, asset, entityName, morphData, morphIndices, numMorphTargets, numFrames, frameLengthInMs);
|
||||||
|
});
|
||||||
|
auto fut = _rl->add_task(lambda);
|
||||||
|
fut.wait();
|
||||||
|
return fut.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT bool set_bone_transform_ffi(
|
FLUTTER_PLUGIN_EXPORT bool set_bone_transform_ffi(
|
||||||
void *assetManager,
|
void *assetManager,
|
||||||
EntityId asset,
|
EntityId asset,
|
||||||
@@ -466,5 +528,31 @@ FLUTTER_PLUGIN_EXPORT bool set_bone_transform_ffi(
|
|||||||
return fut.get();
|
return fut.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT void reset_to_rest_pose_ffi(void* const assetManager, EntityId entityId) {
|
||||||
|
std::packaged_task<void()> lambda(
|
||||||
|
[&] { return reset_to_rest_pose(assetManager, entityId); });
|
||||||
|
auto fut = _rl->add_task(lambda);
|
||||||
|
fut.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT void add_bone_animation_ffi(
|
||||||
|
void *assetManager,
|
||||||
|
EntityId asset,
|
||||||
|
const float *const frameData,
|
||||||
|
int numFrames,
|
||||||
|
const char *const boneName,
|
||||||
|
const char **const meshNames,
|
||||||
|
int numMeshTargets,
|
||||||
|
float frameLengthInMs,
|
||||||
|
bool isModelSpace) {
|
||||||
|
|
||||||
|
std::packaged_task<void()> lambda(
|
||||||
|
[=] {
|
||||||
|
add_bone_animation(assetManager, asset, frameData, numFrames, boneName, meshNames, numMeshTargets, frameLengthInMs, isModelSpace);
|
||||||
|
});
|
||||||
|
auto fut = _rl->add_task(lambda);
|
||||||
|
fut.wait();
|
||||||
|
}
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi() { Log("Dummy called"); }
|
FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi() { Log("Dummy called"); }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user