decouple assets from viewer to allow independent addition/removal/animation/etc
This commit is contained in:
1 parent
f2f158ad78
commit
ff1679198d
30 files changed
+1124
-993
No files matched your search
+408
-700
File diff suppressed because it is too large.
Load diff
+12
-92
@@ -30,6 +30,10 @@
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
#include "SceneAssetLoader.hpp"
|
||||
#include "SceneAsset.hpp"
|
||||
#include "SceneResources.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace filament;
|
||||
using namespace filament::math;
|
||||
@@ -39,55 +43,6 @@ using namespace camutils;
|
||||
|
||||
|
||||
namespace polyvox {
|
||||
|
||||
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t;
|
||||
|
||||
struct EmbeddedAnimationBuffer {
|
||||
EmbeddedAnimationBuffer(int animationIndex, float duration, bool loop) : animationIndex(animationIndex), duration(duration), loop(loop) {}
|
||||
bool hasStarted = false;
|
||||
int animationIndex;
|
||||
float duration = 0;
|
||||
time_point_t lastTime;
|
||||
bool loop;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct ResourceBuffer {
|
||||
ResourceBuffer(const void* data, const uint32_t size, const uint32_t id) : data(data), size(size), id(id) {};
|
||||
|
||||
ResourceBuffer& operator=(ResourceBuffer other)
|
||||
{
|
||||
data = other.data;
|
||||
size = other.size;
|
||||
id = other.id;
|
||||
return *this;
|
||||
}
|
||||
const void* data;
|
||||
uint32_t size;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
using LoadResource = std::function<ResourceBuffer(const char* uri)>;
|
||||
using FreeResource = std::function<void (ResourceBuffer)>;
|
||||
|
||||
struct MorphAnimationBuffer {
|
||||
|
||||
MorphAnimationBuffer(float* frameData,
|
||||
int numWeights,
|
||||
int numFrames,
|
||||
float frameLength) : frameData(frameData), numWeights(numWeights), numFrames(numFrames), frameLengthInMs(frameLength) {
|
||||
}
|
||||
|
||||
int frameIndex = -1;
|
||||
int numFrames;
|
||||
float frameLengthInMs;
|
||||
time_point_t startTime;
|
||||
|
||||
float* frameData;
|
||||
int numWeights;
|
||||
};
|
||||
|
||||
class FilamentViewer {
|
||||
public:
|
||||
FilamentViewer(void* layer, LoadResource loadResource, FreeResource freeResource);
|
||||
@@ -99,42 +54,16 @@ namespace polyvox {
|
||||
void loadIbl(const char* const iblUri);
|
||||
void removeIbl();
|
||||
|
||||
void loadGlb(const char* const uri);
|
||||
void loadGltf(const char* const uri, const char* relativeResourcePath);
|
||||
void removeAsset();
|
||||
SceneAsset* loadGlb(const char* const uri);
|
||||
SceneAsset* loadGltf(const char* const uri, const char* relativeResourcePath);
|
||||
void removeAsset(SceneAsset* asset);
|
||||
|
||||
void updateViewportAndCameraProjection(int height, int width, float scaleFactor);
|
||||
void render();
|
||||
unique_ptr<vector<string>> getTargetNames(const char* meshName);
|
||||
unique_ptr<vector<string>> getAnimationNames();
|
||||
|
||||
Manipulator<float>* manipulator;
|
||||
|
||||
|
||||
///
|
||||
/// Manually set the weights for all morph targets in the assets to the provided values.
|
||||
/// See [animateWeights] if you want to automatically
|
||||
///
|
||||
void applyWeights(float* weights, int count);
|
||||
|
||||
///
|
||||
/// Update the asset's morph target weights every "frame" (which is an arbitrary length of time, i.e. this is not the same as a frame at the framerate of the underlying rendering framework).
|
||||
/// Accordingly:
|
||||
/// length(data) = numWeights * numFrames
|
||||
/// total_animation_duration_in_ms = number_of_frames * frameLengthInMs
|
||||
///
|
||||
void animateWeights(float* data, int numWeights, int numFrames, float frameLengthInMs);
|
||||
|
||||
///
|
||||
/// Play an embedded animation (i.e. an animation node embedded in the GLTF asset). If [loop] is true, the animation will repeat indefinitely.
|
||||
///
|
||||
void playAnimation(int index, bool loop);
|
||||
|
||||
///
|
||||
/// Immediately stop the currently playing animation. NOOP if no animation is playing.
|
||||
///
|
||||
void stopAnimation();
|
||||
|
||||
bool setCamera(const char* nodeName);
|
||||
bool setCamera(SceneAsset* asset, const char* nodeName);
|
||||
void destroySwapChain();
|
||||
void createSwapChain(void* surface);
|
||||
|
||||
@@ -161,10 +90,10 @@ namespace polyvox {
|
||||
|
||||
SwapChain* _swapChain = nullptr;
|
||||
|
||||
Animator* _animator;
|
||||
vector<SceneAsset*> _assets;
|
||||
|
||||
AssetLoader* _assetLoader;
|
||||
FilamentAsset* _asset = nullptr;
|
||||
SceneAssetLoader* _sceneAssetLoader;
|
||||
NameComponentManager* _ncm;
|
||||
std::mutex mtx; // mutex to ensure thread safety when removing assets
|
||||
|
||||
@@ -184,24 +113,15 @@ namespace polyvox {
|
||||
|
||||
float _cameraFocalLength = 0.0f;
|
||||
|
||||
void updateMorphAnimation();
|
||||
void updateEmbeddedAnimation();
|
||||
|
||||
// animation flags;
|
||||
bool isAnimating;
|
||||
unique_ptr<MorphAnimationBuffer> _morphAnimationBuffer;
|
||||
unique_ptr<EmbeddedAnimationBuffer> _embeddedAnimationBuffer;
|
||||
|
||||
// these flags relate to the textured quad we use for rendering unlit background images
|
||||
Texture* _imageTexture = nullptr;
|
||||
Entity* _imageEntity = nullptr;
|
||||
VertexBuffer* _imageVb = nullptr;
|
||||
IndexBuffer* _imageIb = nullptr;
|
||||
Material* _imageMaterial = nullptr;
|
||||
TextureSampler _imageSampler;
|
||||
|
||||
ColorGrading *colorGrading = nullptr;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef POLYVOX_FILAMENT_LOG_H
|
||||
#define POLYVOX_FILAMENT_LOG_H
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <Foundation/Foundation.h>
|
||||
#elif defined __ANDROID__
|
||||
@@ -7,7 +12,7 @@
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
void Log(const char *fmt, ...) {
|
||||
static void Log(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
@@ -23,3 +28,5 @@ void Log(const char *fmt, ...) {
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,193 @@
|
||||
#include <chrono>
|
||||
#include "SceneResources.hpp"
|
||||
#include "SceneAsset.hpp"
|
||||
#include "Log.hpp"
|
||||
#include <gltfio/Animator.h>
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
#include <gltfio/TextureProvider.h>
|
||||
|
||||
#include <filament/TransformManager.h>
|
||||
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
namespace polyvox {
|
||||
|
||||
using namespace std;
|
||||
using namespace filament;
|
||||
using namespace filament::gltfio;
|
||||
using namespace utils;
|
||||
|
||||
SceneAsset::SceneAsset(FilamentAsset* asset, Engine* engine, NameComponentManager* ncm)
|
||||
: _asset(asset), _engine(engine), _ncm(ncm) {
|
||||
_animator = _asset->getAnimator();
|
||||
}
|
||||
|
||||
SceneAsset::~SceneAsset() { _asset = nullptr; }
|
||||
|
||||
void SceneAsset::applyWeights(float *weights, int count) {
|
||||
RenderableManager& rm = _engine->getRenderableManager();
|
||||
for (size_t i = 0, c = _asset->getEntityCount(); i != c; ++i) {
|
||||
auto inst = rm.getInstance(_asset->getEntities()[i]);
|
||||
rm.setMorphWeights(inst, weights, count);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneAsset::animateWeights(float *data, int numWeights, int numFrames,
|
||||
float frameLengthInMs) {
|
||||
Log("Making morph animation buffer with %d weights across %d frames and "
|
||||
"frame length %f ms ",
|
||||
numWeights, numFrames, frameLengthInMs);
|
||||
_morphAnimationBuffer = std::make_unique<MorphAnimationStatus>(
|
||||
data, numWeights, numFrames, frameLengthInMs);
|
||||
}
|
||||
|
||||
void SceneAsset::updateAnimations() {
|
||||
updateMorphAnimation();
|
||||
updateEmbeddedAnimation();
|
||||
}
|
||||
|
||||
void SceneAsset::updateMorphAnimation() {
|
||||
if (!_morphAnimationBuffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_morphAnimationBuffer->frameIndex == -1) {
|
||||
_morphAnimationBuffer->frameIndex++;
|
||||
_morphAnimationBuffer->startTime = high_resolution_clock::now();
|
||||
applyWeights(_morphAnimationBuffer->frameData,
|
||||
_morphAnimationBuffer->numWeights);
|
||||
} else {
|
||||
duration<double, std::milli> dur =
|
||||
high_resolution_clock::now() - _morphAnimationBuffer->startTime;
|
||||
int frameIndex =
|
||||
static_cast<int>(dur.count() / _morphAnimationBuffer->frameLengthInMs);
|
||||
|
||||
if (frameIndex > _morphAnimationBuffer->numFrames - 1) {
|
||||
duration<double, std::milli> dur =
|
||||
high_resolution_clock::now() - _morphAnimationBuffer->startTime;
|
||||
Log("Morph animation completed in %f ms (%d frames at framerate %f), "
|
||||
"final frame was %d",
|
||||
dur.count(), _morphAnimationBuffer->numFrames,
|
||||
1000 / _morphAnimationBuffer->frameLengthInMs,
|
||||
_morphAnimationBuffer->frameIndex);
|
||||
_morphAnimationBuffer = nullptr;
|
||||
} else if (frameIndex != _morphAnimationBuffer->frameIndex) {
|
||||
Log("Rendering frame %d (of a total %d)", frameIndex,
|
||||
_morphAnimationBuffer->numFrames);
|
||||
_morphAnimationBuffer->frameIndex = frameIndex;
|
||||
auto framePtrOffset = frameIndex * _morphAnimationBuffer->numWeights;
|
||||
applyWeights(_morphAnimationBuffer->frameData + framePtrOffset,
|
||||
_morphAnimationBuffer->numWeights);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneAsset::playAnimation(int index, bool loop) {
|
||||
if (index > _animator->getAnimationCount() - 1) {
|
||||
Log("Asset does not contain an animation at index %d", index);
|
||||
} else {
|
||||
_boneAnimationStatus = make_unique<BoneAnimationStatus>(
|
||||
index, _animator->getAnimationDuration(index), loop);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneAsset::stopAnimation() {
|
||||
// TODO - does this need to be threadsafe?
|
||||
_boneAnimationStatus = nullptr;
|
||||
}
|
||||
|
||||
void SceneAsset::updateEmbeddedAnimation() {
|
||||
if (!_boneAnimationStatus) {
|
||||
return;
|
||||
}
|
||||
|
||||
duration<double> dur = duration_cast<duration<double>>(
|
||||
high_resolution_clock::now() - _boneAnimationStatus->lastTime);
|
||||
float startTime = 0;
|
||||
if (!_boneAnimationStatus->hasStarted) {
|
||||
_boneAnimationStatus->hasStarted = true;
|
||||
_boneAnimationStatus->lastTime = high_resolution_clock::now();
|
||||
} else if (dur.count() >= _boneAnimationStatus->duration) {
|
||||
if (_boneAnimationStatus->loop) {
|
||||
_boneAnimationStatus->lastTime = high_resolution_clock::now();
|
||||
} else {
|
||||
_boneAnimationStatus = nullptr;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
startTime = dur.count();
|
||||
}
|
||||
|
||||
_animator->applyAnimation(_boneAnimationStatus->animationIndex, startTime);
|
||||
_animator->updateBoneMatrices();
|
||||
}
|
||||
|
||||
unique_ptr<vector<string>> SceneAsset::getAnimationNames() {
|
||||
size_t count = _animator->getAnimationCount();
|
||||
|
||||
Log("Found %d animations in asset.", count);
|
||||
|
||||
unique_ptr<vector<string>> names = make_unique<vector<string>>();
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
names->push_back(_animator->getAnimationName(i));
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
unique_ptr<vector<string>> SceneAsset::getTargetNames(const char *meshName) {
|
||||
if (!_asset) {
|
||||
Log("No asset, ignoring call.");
|
||||
return nullptr;
|
||||
}
|
||||
Log("Retrieving morph target names for mesh %s", meshName);
|
||||
unique_ptr<vector<string>> names = make_unique<vector<string>>();
|
||||
const Entity *entities = _asset->getEntities();
|
||||
RenderableManager &rm = _engine->getRenderableManager();
|
||||
for (int i = 0; i < _asset->getEntityCount(); i++) {
|
||||
Entity e = entities[i];
|
||||
auto inst = _ncm->getInstance(e);
|
||||
const char *name = _ncm->getName(inst);
|
||||
Log("Got entity instance name %s", name);
|
||||
if (strcmp(name, meshName) == 0) {
|
||||
size_t count = _asset->getMorphTargetCountAt(e);
|
||||
for (int j = 0; j < count; j++) {
|
||||
const char *morphName = _asset->getMorphTargetNameAt(e, j);
|
||||
names->push_back(morphName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
void SceneAsset::transformToUnitCube()
|
||||
{
|
||||
if (!_asset)
|
||||
{
|
||||
Log("No asset, cannot transform.");
|
||||
return;
|
||||
}
|
||||
auto &tm = _engine->getTransformManager();
|
||||
auto aabb = _asset->getBoundingBox();
|
||||
auto center = aabb.center();
|
||||
auto halfExtent = aabb.extent();
|
||||
auto maxExtent = max(halfExtent) * 2;
|
||||
auto scaleFactor = 2.0f / maxExtent;
|
||||
auto transform = math::mat4f::scaling(scaleFactor) * math::mat4f::translation(-center);
|
||||
tm.setTransform(tm.getInstance(_asset->getRoot()), transform);
|
||||
}
|
||||
|
||||
const utils::Entity* SceneAsset::getCameraEntities() {
|
||||
return _asset->getCameraEntities();
|
||||
}
|
||||
|
||||
size_t SceneAsset::getCameraEntityCount() {
|
||||
return _asset->getCameraEntityCount();
|
||||
}
|
||||
|
||||
} // namespace polyvox
|
||||
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/Renderer.h>
|
||||
#include <filament/Scene.h>
|
||||
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
|
||||
#include <utils/NameComponentManager.h>
|
||||
|
||||
#include "SceneResources.hpp"
|
||||
|
||||
|
||||
namespace polyvox {
|
||||
using namespace filament;
|
||||
using namespace filament::gltfio;
|
||||
using namespace utils;
|
||||
|
||||
using namespace std;
|
||||
class SceneAsset {
|
||||
friend class SceneAssetLoader;
|
||||
public:
|
||||
SceneAsset(FilamentAsset* asset, Engine* engine, NameComponentManager* ncm);
|
||||
~SceneAsset();
|
||||
|
||||
unique_ptr<vector<string>> getTargetNames(const char* meshName);
|
||||
unique_ptr<vector<string>> getAnimationNames();
|
||||
|
||||
///
|
||||
/// Update the bone/morph target animations to reflect the current frame (if applicable).
|
||||
///
|
||||
void updateAnimations();
|
||||
|
||||
///
|
||||
/// Immediately stop the currently playing animation. NOOP if no animation is playing.
|
||||
///
|
||||
void stopAnimation();
|
||||
|
||||
///
|
||||
/// Play an embedded animation (i.e. an animation node embedded in the GLTF asset). If [loop] is true, the animation will repeat indefinitely.
|
||||
///
|
||||
void playAnimation(int index, bool loop);
|
||||
|
||||
///
|
||||
/// Manually set the weights for all morph targets in the assets to the provided values.
|
||||
/// See [animateWeights] if you want to automatically
|
||||
///
|
||||
void applyWeights(float* weights, int count);
|
||||
|
||||
///
|
||||
/// Update the asset's morph target weights every "frame" (which is an arbitrary length of time, i.e. this is not the same as a frame at the framerate of the underlying rendering framework).
|
||||
/// Accordingly:
|
||||
/// length(data) = numWeights * numFrames
|
||||
/// total_animation_duration_in_ms = number_of_frames * frameLengthInMs
|
||||
///
|
||||
void animateWeights(float* data, int numWeights, int numFrames, float frameLengthInMs);
|
||||
|
||||
void transformToUnitCube();
|
||||
|
||||
const utils::Entity* getCameraEntities();
|
||||
|
||||
size_t getCameraEntityCount();
|
||||
|
||||
|
||||
private:
|
||||
FilamentAsset* _asset = nullptr;
|
||||
Engine* _engine = nullptr;
|
||||
NameComponentManager* _ncm;
|
||||
void updateMorphAnimation();
|
||||
void updateEmbeddedAnimation();
|
||||
|
||||
Animator* _animator;
|
||||
|
||||
// animation flags;
|
||||
bool isAnimating;
|
||||
unique_ptr<MorphAnimationStatus> _morphAnimationBuffer;
|
||||
unique_ptr<BoneAnimationStatus> _boneAnimationStatus;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
#include "SceneAssetLoader.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
#include <gltfio/Animator.h>
|
||||
|
||||
namespace polyvox {
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::gltfio;
|
||||
|
||||
SceneAssetLoader::SceneAssetLoader(LoadResource loadResource,
|
||||
FreeResource freeResource,
|
||||
AssetLoader *assetLoader,
|
||||
ResourceLoader *resourceLoader,
|
||||
NameComponentManager *ncm, Engine *engine,
|
||||
Scene *scene)
|
||||
: _loadResource(loadResource), _freeResource(freeResource),
|
||||
_assetLoader(assetLoader), _resourceLoader(resourceLoader), _ncm(ncm),
|
||||
_engine(engine), _scene(scene) {}
|
||||
|
||||
SceneAsset *SceneAssetLoader::fromGltf(const char *uri,
|
||||
const char *relativeResourcePath) {
|
||||
ResourceBuffer rbuf = _loadResource(uri);
|
||||
|
||||
// Parse the glTF file and create Filament entities.
|
||||
Log("Creating asset from JSON");
|
||||
FilamentAsset *asset =
|
||||
_assetLoader->createAssetFromJson((uint8_t *)rbuf.data, rbuf.size);
|
||||
Log("Created asset from JSON");
|
||||
|
||||
if (!asset) {
|
||||
Log("Unable to parse asset");
|
||||
return nullptr;
|
||||
}
|
||||
Log("Loading relative resources");
|
||||
|
||||
const char *const *const resourceUris = asset->getResourceUris();
|
||||
const size_t resourceUriCount = asset->getResourceUriCount();
|
||||
|
||||
Log("Loading %d resources for asset", resourceUriCount);
|
||||
|
||||
for (size_t i = 0; i < resourceUriCount; i++) {
|
||||
string uri =
|
||||
string(relativeResourcePath) + string("/") + string(resourceUris[i]);
|
||||
Log("Creating resource buffer for resource at %s", uri.c_str());
|
||||
ResourceBuffer buf = _loadResource(uri.c_str());
|
||||
|
||||
// using FunctionCallback = std::function<void(void*, unsigned int, void
|
||||
// *)>; auto cb = [&] (void * ptr, unsigned int len, void * misc) {
|
||||
// };
|
||||
// FunctionCallback fcb = cb;
|
||||
|
||||
ResourceLoader::BufferDescriptor b(buf.data, buf.size);
|
||||
_resourceLoader->addResourceData(resourceUris[i], std::move(b));
|
||||
_freeResource(buf);
|
||||
}
|
||||
|
||||
_resourceLoader->loadResources(asset);
|
||||
const Entity *entities = asset->getEntities();
|
||||
RenderableManager &rm = _engine->getRenderableManager();
|
||||
for (int i = 0; i < asset->getEntityCount(); i++) {
|
||||
Entity e = entities[i];
|
||||
auto inst = rm.getInstance(e);
|
||||
rm.setCulling(inst, false);
|
||||
}
|
||||
|
||||
asset->getAnimator()->updateBoneMatrices();
|
||||
|
||||
_scene->addEntities(asset->getEntities(), asset->getEntityCount());
|
||||
|
||||
Log("Loaded relative resources");
|
||||
asset->releaseSourceData();
|
||||
|
||||
Log("Load complete for GLTF at URI %s", uri);
|
||||
return new SceneAsset(asset, _engine, _ncm);
|
||||
}
|
||||
|
||||
SceneAsset *SceneAssetLoader::fromGlb(const char *uri) {
|
||||
Log("Loading GLB at URI %s", uri);
|
||||
|
||||
ResourceBuffer rbuf = _loadResource(uri);
|
||||
|
||||
FilamentAsset *asset = _assetLoader->createAssetFromBinary(
|
||||
(const uint8_t *)rbuf.data, rbuf.size);
|
||||
|
||||
if (!asset) {
|
||||
Log("Unknown error loading GLB asset.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int entityCount = asset->getEntityCount();
|
||||
|
||||
_scene->addEntities(asset->getEntities(), entityCount);
|
||||
|
||||
Log("Added %d entities to scene", entityCount);
|
||||
_resourceLoader->loadResources(asset);
|
||||
|
||||
const Entity *entities = asset->getEntities();
|
||||
RenderableManager &rm = _engine->getRenderableManager();
|
||||
for (int i = 0; i < asset->getEntityCount(); i++) {
|
||||
Entity e = entities[i];
|
||||
auto inst = rm.getInstance(e);
|
||||
// check this
|
||||
rm.setCulling(inst, false);
|
||||
}
|
||||
|
||||
_freeResource(rbuf);
|
||||
|
||||
asset->getAnimator()->updateBoneMatrices();
|
||||
|
||||
asset->releaseSourceData();
|
||||
|
||||
Log("Successfully loaded GLB.");
|
||||
return new SceneAsset(asset, _engine, _ncm);
|
||||
}
|
||||
|
||||
void SceneAssetLoader::remove(SceneAsset *asset) {
|
||||
_resourceLoader->evictResourceData();
|
||||
_scene->removeEntities(asset->_asset->getEntities(),
|
||||
asset->_asset->getEntityCount());
|
||||
_assetLoader->destroyAsset(asset->_asset);
|
||||
}
|
||||
} // namespace polyvox
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <filament/Scene.h>
|
||||
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/FilamentAsset.h>
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
|
||||
#include "SceneResources.hpp"
|
||||
#include "SceneAsset.hpp"
|
||||
|
||||
namespace polyvox {
|
||||
using namespace filament;
|
||||
using namespace filament::gltfio;
|
||||
using namespace utils;
|
||||
|
||||
class SceneAssetLoader {
|
||||
public:
|
||||
SceneAssetLoader(
|
||||
LoadResource loadResource,
|
||||
FreeResource freeResource,
|
||||
AssetLoader* assetLoader,
|
||||
ResourceLoader* resourceLoader,
|
||||
NameComponentManager* ncm,
|
||||
Engine* engine,
|
||||
Scene* scene);
|
||||
SceneAsset* fromGltf(const char* uri, const char* relativeResourcePath);
|
||||
SceneAsset* fromGlb(const char* uri);
|
||||
void remove(SceneAsset* asset);
|
||||
|
||||
private:
|
||||
LoadResource _loadResource;
|
||||
FreeResource _freeResource;
|
||||
AssetLoader* _assetLoader;
|
||||
ResourceLoader* _resourceLoader;
|
||||
NameComponentManager* _ncm;
|
||||
Scene* _scene;
|
||||
Engine* _engine;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace polyvox {
|
||||
|
||||
//
|
||||
// Pairs a memory buffer with an ID that can be used to unload the backing asset if needed.
|
||||
// Use this when you want to load an asset from a resource that requires more than just `free` on the underlying buffer.
|
||||
// e.g.
|
||||
// ```
|
||||
// uint64_t id = get_next_resource_id();
|
||||
// AAsset *asset = AAssetManager_open(am, name, AASSET_MODE_BUFFER);
|
||||
// off_t length = AAsset_getLength(asset);
|
||||
// const void * buffer = AAsset_getBuffer(asset);
|
||||
// uint8_t *buf = new uint8_t[length ];
|
||||
// memcpy(buf,buffer, length);
|
||||
// ResourceBuffer rb(buf, length, id);
|
||||
// ...
|
||||
// ...
|
||||
// (elsewhere)
|
||||
// AAsset* asset = get_asset_from_id(rb.id);
|
||||
// AAsset_close(asset);
|
||||
// free_asset_id(rb.id);
|
||||
//
|
||||
struct ResourceBuffer {
|
||||
ResourceBuffer(const void* data, const uint32_t size, const uint32_t id) : data(data), size(size), id(id) {};
|
||||
|
||||
ResourceBuffer& operator=(ResourceBuffer other)
|
||||
{
|
||||
data = other.data;
|
||||
size = other.size;
|
||||
id = other.id;
|
||||
return *this;
|
||||
}
|
||||
const void* data;
|
||||
uint32_t size;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
//
|
||||
// Typedef for any function that loads a resource into a ResourceBuffer from an asset URI.
|
||||
//
|
||||
using LoadResource = std::function<ResourceBuffer(const char* uri)>;
|
||||
|
||||
//
|
||||
// Typedef for any function that frees a ResourceBuffer.
|
||||
//
|
||||
using FreeResource = std::function<void (ResourceBuffer)>;
|
||||
|
||||
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t;
|
||||
|
||||
//
|
||||
// Holds the current state of a bone animation embeded in a GLTF asset.
|
||||
//
|
||||
struct BoneAnimationStatus {
|
||||
BoneAnimationStatus(int animationIndex, float duration, bool loop) : animationIndex(animationIndex), duration(duration), loop(loop) {}
|
||||
bool hasStarted = false;
|
||||
int animationIndex;
|
||||
float duration = 0;
|
||||
time_point_t lastTime;
|
||||
bool loop;
|
||||
};
|
||||
|
||||
//
|
||||
// Holds the current state of a morph-target animation in a GLTF asset.
|
||||
//
|
||||
struct MorphAnimationStatus {
|
||||
|
||||
MorphAnimationStatus(float* frameData,
|
||||
int numWeights,
|
||||
int numFrames,
|
||||
float frameLength) : frameData(frameData), numWeights(numWeights), numFrames(numFrames), frameLengthInMs(frameLength) {
|
||||
}
|
||||
|
||||
int frameIndex = -1;
|
||||
int numFrames;
|
||||
float frameLengthInMs;
|
||||
time_point_t startTime;
|
||||
|
||||
float* frameData;
|
||||
int numWeights;
|
||||
};
|
||||
}
|
||||
@@ -7,11 +7,11 @@ using namespace std;
|
||||
|
||||
namespace polyvox {
|
||||
|
||||
class streambuf : public std::streambuf
|
||||
class StreamBufferAdapter : public std::streambuf
|
||||
{
|
||||
public:
|
||||
streambuf(const char *begin, const char *end);
|
||||
~streambuf() {
|
||||
StreamBufferAdapter(const char *begin, const char *end);
|
||||
~StreamBufferAdapter() {
|
||||
|
||||
}
|
||||
streamsize size();
|
||||
@@ -26,16 +26,16 @@ class streambuf : public std::streambuf
|
||||
|
||||
};
|
||||
|
||||
streambuf::streambuf(const char *begin, const char *end)
|
||||
StreamBufferAdapter::StreamBufferAdapter(const char *begin, const char *end)
|
||||
{
|
||||
setg((char*)begin, (char*)begin, (char*)end);
|
||||
}
|
||||
|
||||
streamsize streambuf::size() {
|
||||
streamsize StreamBufferAdapter::size() {
|
||||
return egptr() - eback();
|
||||
}
|
||||
|
||||
streambuf::int_type streambuf::underflow()
|
||||
streambuf::int_type StreamBufferAdapter::underflow()
|
||||
{
|
||||
if (gptr() == egptr()) {
|
||||
return traits_type::eof();
|
||||
@@ -43,7 +43,7 @@ streambuf::int_type streambuf::underflow()
|
||||
return *(gptr());
|
||||
}
|
||||
|
||||
streambuf::int_type streambuf::uflow()
|
||||
streambuf::int_type StreamBufferAdapter::uflow()
|
||||
{
|
||||
if (gptr() == egptr()) {
|
||||
return traits_type::eof();
|
||||
@@ -53,7 +53,7 @@ streambuf::int_type streambuf::uflow()
|
||||
return *(gptr());
|
||||
}
|
||||
|
||||
streambuf::int_type streambuf::pbackfail(int_type ch)
|
||||
streambuf::int_type StreamBufferAdapter::pbackfail(int_type ch)
|
||||
{
|
||||
if (gptr() == eback() || (ch != traits_type::eof() && ch != gptr()[-1]))
|
||||
return traits_type::eof();
|
||||
@@ -61,12 +61,12 @@ streambuf::int_type streambuf::pbackfail(int_type ch)
|
||||
return *(gptr());
|
||||
}
|
||||
|
||||
streamsize streambuf::showmanyc()
|
||||
streamsize StreamBufferAdapter::showmanyc()
|
||||
{
|
||||
return egptr() - gptr();
|
||||
}
|
||||
|
||||
streampos streambuf::seekoff(streamoff off, ios_base::seekdir way, ios_base::openmode which = ios_base::in) {
|
||||
streampos StreamBufferAdapter::seekoff(streamoff off, ios_base::seekdir way, ios_base::openmode which = ios_base::in) {
|
||||
if(way == ios_base::beg) {
|
||||
setg(eback(), eback()+off, egptr());
|
||||
} else if(way == ios_base::cur) {
|
||||
@@ -77,7 +77,7 @@ streampos streambuf::seekoff(streamoff off, ios_base::seekdir way, ios_base::ope
|
||||
return gptr() - eback();
|
||||
}
|
||||
|
||||
streampos streambuf::seekpos(streampos sp, ios_base::openmode which = ios_base::in) {
|
||||
streampos StreamBufferAdapter::seekpos(streampos sp, ios_base::openmode which = ios_base::in) {
|
||||
return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,15 @@
|
||||
|
||||
namespace polyvox {
|
||||
|
||||
class streambuf : public std::streambuf
|
||||
//
|
||||
// A generic adapter to expose any contiguous section of memory as a std::streambuf.
|
||||
// Mostly for Android/iOS assets which may not be able to be directly loaded as streams.
|
||||
//
|
||||
class StreamBufferAdapter : public std::streambuf
|
||||
{
|
||||
public:
|
||||
streambuf(const char *begin, const char *end);
|
||||
~streambuf() {
|
||||
StreamBufferAdapter(const char *begin, const char *end);
|
||||
~StreamBufferAdapter() {
|
||||
|
||||
}
|
||||
streamsize size();
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user