add createGeometry
This commit is contained in:
@@ -131,6 +131,7 @@ namespace polyvox
|
|||||||
void setRecording(bool recording);
|
void setRecording(bool recording);
|
||||||
void setRecordingOutputDirectory(const char* path);
|
void setRecordingOutputDirectory(const char* path);
|
||||||
|
|
||||||
|
EntityId createGeometry(float* vertices, uint32_t numVertices, uint16_t* indices, uint32_t numIndices, const char* materialPath);
|
||||||
|
|
||||||
AssetManager *const getAssetManager()
|
AssetManager *const getAssetManager()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -184,6 +184,8 @@ extern "C"
|
|||||||
FLUTTER_PLUGIN_EXPORT void ios_dummy();
|
FLUTTER_PLUGIN_EXPORT void ios_dummy();
|
||||||
FLUTTER_PLUGIN_EXPORT void flutter_filament_free(void *ptr);
|
FLUTTER_PLUGIN_EXPORT void flutter_filament_free(void *ptr);
|
||||||
FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId);
|
FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId);
|
||||||
|
FLUTTER_PLUGIN_EXPORT EntityId create_geometry(void *const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ FLUTTER_PLUGIN_EXPORT void set_post_processing_ffi(void* const viewer, bool enab
|
|||||||
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 reset_to_rest_pose_ffi(void* const assetManager, EntityId entityId);
|
||||||
FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi();
|
FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi();
|
||||||
|
FLUTTER_PLUGIN_EXPORT EntityId create_geometry_ffi(void* const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include <filament/Skybox.h>
|
#include <filament/Skybox.h>
|
||||||
#include <filament/TransformManager.h>
|
#include <filament/TransformManager.h>
|
||||||
#include <filament/VertexBuffer.h>
|
#include <filament/VertexBuffer.h>
|
||||||
|
#include <filament/IndexBuffer.h>
|
||||||
#include <filament/View.h>
|
#include <filament/View.h>
|
||||||
#include <filament/Viewport.h>
|
#include <filament/Viewport.h>
|
||||||
|
|
||||||
@@ -61,7 +62,6 @@
|
|||||||
#include <imageio/ImageEncoder.h>
|
#include <imageio/ImageEncoder.h>
|
||||||
#include <image/ColorTransform.h>
|
#include <image/ColorTransform.h>
|
||||||
|
|
||||||
|
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
|
|
||||||
#include <math/mat4.h>
|
#include <math/mat4.h>
|
||||||
@@ -109,11 +109,6 @@ namespace polyvox
|
|||||||
// const float kAperture = 1.0f;
|
// const float kAperture = 1.0f;
|
||||||
// const float kShutterSpeed = 1.0f;
|
// const float kShutterSpeed = 1.0f;
|
||||||
// const float kSensitivity = 50.0f;
|
// const float kSensitivity = 50.0f;
|
||||||
struct Vertex
|
|
||||||
{
|
|
||||||
filament::math::float2 position;
|
|
||||||
uint32_t color;
|
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr float4 sFullScreenTriangleVertices[3] = {
|
static constexpr float4 sFullScreenTriangleVertices[3] = {
|
||||||
{-1.0f, -1.0f, 1.0f, 1.0f},
|
{-1.0f, -1.0f, 1.0f, 1.0f},
|
||||||
@@ -161,25 +156,25 @@ namespace polyvox
|
|||||||
setToneMapping(ToneMapping::ACES);
|
setToneMapping(ToneMapping::ACES);
|
||||||
Log("Set tone mapping");
|
Log("Set tone mapping");
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
Log("Bloom is disabled on WebGL builds as it causes instability with certain drivers");
|
Log("Bloom is disabled on WebGL builds as it causes instability with certain drivers");
|
||||||
decltype(_view->getBloomOptions()) opts;
|
decltype(_view->getBloomOptions()) opts;
|
||||||
opts.enabled = false;
|
opts.enabled = false;
|
||||||
_view->setBloomOptions(opts);
|
_view->setBloomOptions(opts);
|
||||||
|
|
||||||
_view->setAmbientOcclusionOptions({.enabled=false});
|
_view->setAmbientOcclusionOptions({.enabled = false});
|
||||||
|
|
||||||
_view->setDynamicResolutionOptions({.enabled=false});
|
_view->setDynamicResolutionOptions({.enabled = false});
|
||||||
|
|
||||||
_view->setDithering(filament::Dithering::NONE);
|
_view->setDithering(filament::Dithering::NONE);
|
||||||
_view->setAntiAliasing(filament::AntiAliasing::NONE);
|
_view->setAntiAliasing(filament::AntiAliasing::NONE);
|
||||||
_view->setShadowingEnabled(false);
|
_view->setShadowingEnabled(false);
|
||||||
_view->setScreenSpaceRefractionEnabled(false);
|
_view->setScreenSpaceRefractionEnabled(false);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
setBloom(0.6f);
|
setBloom(0.6f);
|
||||||
Log("Set bloom");
|
Log("Set bloom");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_view->setScene(_scene);
|
_view->setScene(_scene);
|
||||||
_view->setCamera(_mainCamera);
|
_view->setCamera(_mainCamera);
|
||||||
@@ -276,7 +271,7 @@ namespace polyvox
|
|||||||
.culling(false)
|
.culling(false)
|
||||||
.build(*_engine, imageEntity);
|
.build(*_engine, imageEntity);
|
||||||
_imageEntity = &imageEntity;
|
_imageEntity = &imageEntity;
|
||||||
_scene->addEntity(imageEntity);
|
// _scene->addEntity(imageEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::setPostProcessing(bool enabled)
|
void FilamentViewer::setPostProcessing(bool enabled)
|
||||||
@@ -286,14 +281,14 @@ namespace polyvox
|
|||||||
|
|
||||||
void FilamentViewer::setBloom(float strength)
|
void FilamentViewer::setBloom(float strength)
|
||||||
{
|
{
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
Log("Bloom is disabled on WebGL builds as it causes instability with certain drivers. setBloom will be ignored");
|
Log("Bloom is disabled on WebGL builds as it causes instability with certain drivers. setBloom will be ignored");
|
||||||
#else
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::setToneMapping(ToneMapping toneMapping)
|
void FilamentViewer::setToneMapping(ToneMapping toneMapping)
|
||||||
@@ -787,11 +782,13 @@ namespace polyvox
|
|||||||
Log("Set lens projection to focal length %f, near %f and far %f", _cameraFocalLength, _near, _far);
|
Log("Set lens projection to focal length %f, near %f and far %f", _cameraFocalLength, _near, _far);
|
||||||
}
|
}
|
||||||
|
|
||||||
double FilamentViewer::getCameraCullingNear() {
|
double FilamentViewer::getCameraCullingNear()
|
||||||
|
{
|
||||||
Camera &cam = _view->getCamera();
|
Camera &cam = _view->getCamera();
|
||||||
return cam.getNear();
|
return cam.getNear();
|
||||||
}
|
}
|
||||||
double FilamentViewer::getCameraCullingFar() {
|
double FilamentViewer::getCameraCullingFar()
|
||||||
|
{
|
||||||
Camera &cam = _view->getCamera();
|
Camera &cam = _view->getCamera();
|
||||||
return cam.getCullingFar();
|
return cam.getCullingFar();
|
||||||
}
|
}
|
||||||
@@ -952,11 +949,11 @@ namespace polyvox
|
|||||||
_scene->setIndirectLight(nullptr);
|
_scene->setIndirectLight(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::rotateIbl(const math::mat3f & matrix) {
|
void FilamentViewer::rotateIbl(const math::mat3f &matrix)
|
||||||
_indirectLight->setRotation(matrix);
|
{
|
||||||
|
_indirectLight->setRotation(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FilamentViewer::loadIbl(const char *const iblPath, float intensity)
|
void FilamentViewer::loadIbl(const char *const iblPath, float intensity)
|
||||||
{
|
{
|
||||||
removeIbl();
|
removeIbl();
|
||||||
@@ -1005,7 +1002,6 @@ namespace polyvox
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FilamentViewer::render(
|
void FilamentViewer::render(
|
||||||
uint64_t frameTimeInNanos,
|
uint64_t frameTimeInNanos,
|
||||||
void *pixelBuffer,
|
void *pixelBuffer,
|
||||||
@@ -1029,7 +1025,8 @@ namespace polyvox
|
|||||||
auto now = std::chrono::high_resolution_clock::now();
|
auto now = std::chrono::high_resolution_clock::now();
|
||||||
auto secsSinceLastFpsCheck = float(std::chrono::duration_cast<std::chrono::seconds>(now - _fpsCounterStartTime).count());
|
auto secsSinceLastFpsCheck = float(std::chrono::duration_cast<std::chrono::seconds>(now - _fpsCounterStartTime).count());
|
||||||
|
|
||||||
if(secsSinceLastFpsCheck >= 1) {
|
if (secsSinceLastFpsCheck >= 1)
|
||||||
|
{
|
||||||
auto fps = _frameCount / secsSinceLastFpsCheck;
|
auto fps = _frameCount / secsSinceLastFpsCheck;
|
||||||
Log("%ffps (_frameCount %d, secs since last check %f)", fps, _frameCount, secsSinceLastFpsCheck);
|
Log("%ffps (_frameCount %d, secs since last check %f)", fps, _frameCount, secsSinceLastFpsCheck);
|
||||||
// Log("1 sec average for asset animation update %f", _elapsed / _frameCount);
|
// Log("1 sec average for asset animation update %f", _elapsed / _frameCount);
|
||||||
@@ -1046,9 +1043,10 @@ namespace polyvox
|
|||||||
_cumulativeAnimationUpdateTime += tmr.elapsed();
|
_cumulativeAnimationUpdateTime += tmr.elapsed();
|
||||||
|
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
@@ -1069,109 +1067,119 @@ namespace polyvox
|
|||||||
// }
|
// }
|
||||||
// else
|
// else
|
||||||
// {
|
// {
|
||||||
// Render the scene, unless the renderer wants to skip the frame.
|
// Render the scene, unless the renderer wants to skip the frame.
|
||||||
bool beginFrame = _renderer->beginFrame(_swapChain, frameTimeInNanos);
|
bool beginFrame = _renderer->beginFrame(_swapChain, frameTimeInNanos);
|
||||||
|
|
||||||
if (beginFrame)
|
if (beginFrame)
|
||||||
|
{
|
||||||
|
_renderer->render(_view);
|
||||||
|
_frameCount++;
|
||||||
|
|
||||||
|
if (_recording)
|
||||||
{
|
{
|
||||||
_renderer->render(_view);
|
Viewport const &vp = _view->getViewport();
|
||||||
_frameCount++;
|
size_t pixelBufferSize = vp.width * vp.height * 4;
|
||||||
|
auto *pixelBuffer = new uint8_t[pixelBufferSize];
|
||||||
|
auto callback = [](void *buf, size_t size, void *data)
|
||||||
|
{
|
||||||
|
auto frameCallbackData = (FrameCallbackData *)data;
|
||||||
|
auto viewer = (FilamentViewer *)frameCallbackData->viewer;
|
||||||
|
viewer->savePng(buf, size, frameCallbackData->frameNumber);
|
||||||
|
delete frameCallbackData;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto now = std::chrono::high_resolution_clock::now();
|
||||||
|
auto elapsed = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - _recordingStartTime).count());
|
||||||
|
|
||||||
if(_recording) {
|
auto frameNumber = uint32_t(floor(elapsed / _frameInterval));
|
||||||
Viewport const &vp = _view->getViewport();
|
|
||||||
size_t pixelBufferSize = vp.width * vp.height * 4;
|
|
||||||
auto* pixelBuffer = new uint8_t[pixelBufferSize];
|
|
||||||
auto callback = [](void *buf, size_t size, void *data) {
|
|
||||||
auto frameCallbackData = (FrameCallbackData*)data;
|
|
||||||
auto viewer = (FilamentViewer*)frameCallbackData->viewer;
|
|
||||||
viewer->savePng(buf, size, frameCallbackData->frameNumber);
|
|
||||||
delete frameCallbackData;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto now = std::chrono::high_resolution_clock::now();
|
auto userData = new FrameCallbackData{this, frameNumber};
|
||||||
auto elapsed = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - _recordingStartTime).count());
|
|
||||||
|
|
||||||
auto frameNumber = uint32_t(floor(elapsed / _frameInterval));
|
auto pbd = Texture::PixelBufferDescriptor(
|
||||||
|
pixelBuffer, pixelBufferSize,
|
||||||
|
Texture::Format::RGBA,
|
||||||
|
Texture::Type::UBYTE, nullptr, callback, userData);
|
||||||
|
|
||||||
auto userData = new FrameCallbackData { this, frameNumber };
|
_renderer->readPixels(_rt, 0, 0, vp.width, vp.height, std::move(pbd));
|
||||||
|
|
||||||
auto pbd = Texture::PixelBufferDescriptor(
|
|
||||||
pixelBuffer, pixelBufferSize,
|
|
||||||
Texture::Format::RGBA,
|
|
||||||
Texture::Type::UBYTE, nullptr, callback, userData);
|
|
||||||
|
|
||||||
_renderer->readPixels(_rt, 0, 0, vp.width, vp.height, std::move(pbd));
|
|
||||||
}
|
|
||||||
_renderer->endFrame();
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
_engine->execute();
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
_skippedFrames++;
|
|
||||||
}
|
}
|
||||||
|
_renderer->endFrame();
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
_engine->execute();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_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)
|
||||||
delete[] static_cast<uint8_t*>(buf);
|
{
|
||||||
|
delete[] static_cast<uint8_t *>(buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Viewport const &vp = _view->getViewport();
|
Viewport const &vp = _view->getViewport();
|
||||||
|
|
||||||
std::packaged_task<void()> lambda([=]() mutable {
|
std::packaged_task<void()> lambda([=]() mutable
|
||||||
|
{
|
||||||
|
int digits = 6;
|
||||||
|
std::ostringstream stringStream;
|
||||||
|
stringStream << _recordingOutputDirectory << "/output_";
|
||||||
|
stringStream << std::setfill('0') << std::setw(digits);
|
||||||
|
stringStream << std::to_string(frameNumber);
|
||||||
|
stringStream << ".png";
|
||||||
|
|
||||||
int digits = 6;
|
std::string filename = stringStream.str();
|
||||||
std::ostringstream stringStream;
|
|
||||||
stringStream << _recordingOutputDirectory << "/output_";
|
|
||||||
stringStream << std::setfill('0') << std::setw(digits);
|
|
||||||
stringStream << std::to_string(frameNumber);
|
|
||||||
stringStream << ".png";
|
|
||||||
|
|
||||||
std::string filename = stringStream.str();
|
ofstream wf(filename, ios::out | ios::binary);
|
||||||
|
|
||||||
ofstream wf(filename, ios::out | ios::binary);
|
LinearImage image(toLinearWithAlpha<uint8_t>(vp.width, vp.height, vp.width * 4,
|
||||||
|
static_cast<uint8_t *>(buf)));
|
||||||
|
|
||||||
LinearImage image(toLinearWithAlpha<uint8_t>(vp.width, vp.height, vp.width * 4,
|
auto result = image::ImageEncoder::encode(
|
||||||
static_cast<uint8_t*>(buf)));
|
wf, image::ImageEncoder::Format::PNG, image, std::string(""), std::string(""));
|
||||||
|
|
||||||
auto result = image::ImageEncoder::encode(
|
delete[] static_cast<uint8_t *>(buf);
|
||||||
wf, image::ImageEncoder::Format::PNG, image, std::string(""), std::string("")
|
|
||||||
);
|
|
||||||
|
|
||||||
delete[] static_cast<uint8_t*>(buf);
|
if (!result)
|
||||||
|
{
|
||||||
|
Log("Failed to encode");
|
||||||
|
}
|
||||||
|
|
||||||
if(!result) {
|
wf.close();
|
||||||
Log("Failed to encode");
|
if (!wf.good())
|
||||||
}
|
{
|
||||||
|
Log("Write failed!");
|
||||||
wf.close();
|
}
|
||||||
if(!wf.good()) {
|
});
|
||||||
Log("Write failed!");
|
_tp->add_task(lambda);
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
_tp->add_task(lambda);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::setRecordingOutputDirectory(const char* path) {
|
void FilamentViewer::setRecordingOutputDirectory(const char *path)
|
||||||
|
{
|
||||||
_recordingOutputDirectory = std::string(path);
|
_recordingOutputDirectory = std::string(path);
|
||||||
auto outputDirAsPath = std::filesystem::path(path);
|
auto outputDirAsPath = std::filesystem::path(path);
|
||||||
if(!std::filesystem::is_directory(outputDirAsPath)) {
|
if (!std::filesystem::is_directory(outputDirAsPath))
|
||||||
|
{
|
||||||
std::filesystem::create_directories(outputDirAsPath);
|
std::filesystem::create_directories(outputDirAsPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilamentViewer::setRecording(bool recording) {
|
void FilamentViewer::setRecording(bool recording)
|
||||||
|
{
|
||||||
std::lock_guard lock(_recordingMutex);
|
std::lock_guard lock(_recordingMutex);
|
||||||
this->_recording = recording;
|
this->_recording = recording;
|
||||||
if(recording) {
|
if (recording)
|
||||||
|
{
|
||||||
_tp = new flutter_filament::ThreadPool(8);
|
_tp = new flutter_filament::ThreadPool(8);
|
||||||
_recordingStartTime = std::chrono::high_resolution_clock::now();
|
_recordingStartTime = std::chrono::high_resolution_clock::now();
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
delete _tp;
|
delete _tp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1284,7 +1292,7 @@ namespace polyvox
|
|||||||
matrix[13],
|
matrix[13],
|
||||||
matrix[14],
|
matrix[14],
|
||||||
matrix[15]);
|
matrix[15]);
|
||||||
cam.setCustomProjection(projectionMatrix,projectionMatrix, near, far);
|
cam.setCustomProjection(projectionMatrix, projectionMatrix, near, far);
|
||||||
}
|
}
|
||||||
|
|
||||||
const math::mat4 FilamentViewer::getCameraModelMatrix()
|
const math::mat4 FilamentViewer::getCameraModelMatrix()
|
||||||
@@ -1320,7 +1328,7 @@ namespace polyvox
|
|||||||
void FilamentViewer::_createManipulator()
|
void FilamentViewer::_createManipulator()
|
||||||
{
|
{
|
||||||
Camera &cam = _view->getCamera();
|
Camera &cam = _view->getCamera();
|
||||||
|
|
||||||
math::double3 home = cam.getPosition();
|
math::double3 home = cam.getPosition();
|
||||||
math::double3 up = cam.getUpVector();
|
math::double3 up = cam.getUpVector();
|
||||||
auto fv = cam.getForwardVector();
|
auto fv = cam.getForwardVector();
|
||||||
@@ -1330,7 +1338,7 @@ namespace polyvox
|
|||||||
|
|
||||||
_manipulator = Manipulator<double>::Builder()
|
_manipulator = Manipulator<double>::Builder()
|
||||||
.viewport(vp.width, vp.height)
|
.viewport(vp.width, vp.height)
|
||||||
.upVector(up.x, up.y, up.z)
|
.upVector(up.x, up.y, up.z)
|
||||||
.zoomSpeed(_zoomSpeed)
|
.zoomSpeed(_zoomSpeed)
|
||||||
.targetPosition(target[0], target[1], target[2])
|
.targetPosition(target[0], target[1], target[2])
|
||||||
// only applicable to Mode::ORBIT
|
// only applicable to Mode::ORBIT
|
||||||
@@ -1441,4 +1449,69 @@ namespace polyvox
|
|||||||
{ *entityId = Entity::smuggle(result.renderable); });
|
{ *entityId = Entity::smuggle(result.renderable); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityId FilamentViewer::createGeometry(float *vertices, uint32_t numVertices, uint16_t *indices, uint32_t numIndices, const char* materialPath)
|
||||||
|
{
|
||||||
|
|
||||||
|
float *verticesCopy = (float*)malloc(numVertices * sizeof(float));
|
||||||
|
memcpy(verticesCopy, vertices, numVertices * sizeof(float));
|
||||||
|
VertexBuffer::BufferDescriptor::Callback vertexCallback = [](void *buf, size_t,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
free((void*)buf);
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t *indicesCopy = (uint16_t*)malloc(numIndices * sizeof(uint16_t));
|
||||||
|
memcpy(indicesCopy, indices, numIndices * sizeof(uint16_t));
|
||||||
|
IndexBuffer::BufferDescriptor::Callback indexCallback = [](void *buf, size_t,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
free((void*)buf);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto vb = VertexBuffer::Builder().vertexCount(numVertices).bufferCount(1).attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3).build(*_engine);
|
||||||
|
|
||||||
|
vb->setBufferAt(*_engine, 0, VertexBuffer::BufferDescriptor(verticesCopy, vb->getVertexCount() * sizeof(filament::math::float3), 0, vertexCallback));
|
||||||
|
|
||||||
|
auto ib = IndexBuffer::Builder().indexCount(numIndices).bufferType(IndexBuffer::IndexType::USHORT).build(*_engine);
|
||||||
|
ib->setBuffer(*_engine, IndexBuffer::BufferDescriptor(indicesCopy, ib->getIndexCount() * sizeof(uint16_t), 0, indexCallback));
|
||||||
|
|
||||||
|
filament::Material* mat = nullptr;
|
||||||
|
if(materialPath) {
|
||||||
|
auto matData = _resourceLoaderWrapper->load(materialPath);
|
||||||
|
auto mat = Material::Builder().package(matData.data, matData.size).build(*_engine);
|
||||||
|
_resourceLoaderWrapper->free(matData);
|
||||||
|
}
|
||||||
|
|
||||||
|
float minX, minY, minZ = 0.0f;
|
||||||
|
float maxX, maxY, maxZ = 0.0f;
|
||||||
|
|
||||||
|
for(int i = 0; i < numVertices; i+=3) {
|
||||||
|
minX = std::min(vertices[i], minX);
|
||||||
|
minY = std::min(vertices[i+1], minY);
|
||||||
|
minZ = std::min(vertices[i+2], minZ);
|
||||||
|
maxX = std::max(vertices[i], maxX);
|
||||||
|
maxY = std::max(vertices[i+1], maxY);
|
||||||
|
maxZ = std::max(vertices[i+2], maxZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto renderable = utils::EntityManager::get().create();
|
||||||
|
RenderableManager::Builder builder = RenderableManager::Builder(1);
|
||||||
|
builder
|
||||||
|
.boundingBox({{minX, minY, minZ}, {maxX, maxY, maxZ}})
|
||||||
|
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES,
|
||||||
|
vb, ib, 0, numIndices)
|
||||||
|
.culling(false)
|
||||||
|
.receiveShadows(false)
|
||||||
|
.castShadows(false);
|
||||||
|
if(mat) {
|
||||||
|
builder.material(0, mat->getDefaultInstance()).build(*_engine, renderable);
|
||||||
|
}
|
||||||
|
auto result = builder.build(*_engine, renderable);
|
||||||
|
|
||||||
|
_scene->addEntity(renderable);
|
||||||
|
Log("Created geometry with result %d", result);
|
||||||
|
|
||||||
|
return Entity::smuggle(renderable);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace polyvox
|
} // namespace polyvox
|
||||||
|
|||||||
@@ -540,4 +540,10 @@ extern "C"
|
|||||||
FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId) {
|
FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId) {
|
||||||
((AssetManager*)assetManager)->addCollisionComponent(entityId);
|
((AssetManager*)assetManager)->addCollisionComponent(entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT EntityId create_geometry(void *const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath) {
|
||||||
|
return ((FilamentViewer*)viewer)->createGeometry(vertices, (size_t)numVertices, indices, numIndices, materialPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -554,4 +554,15 @@ FLUTTER_PLUGIN_EXPORT void add_bone_animation_ffi(
|
|||||||
}
|
}
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi() { Log("Dummy called"); }
|
FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi() { Log("Dummy called"); }
|
||||||
|
|
||||||
|
FLUTTER_PLUGIN_EXPORT EntityId create_geometry_ffi(void* const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath) {
|
||||||
|
std::packaged_task<EntityId()> lambda(
|
||||||
|
[=] {
|
||||||
|
return create_geometry(viewer, vertices, numVertices, indices, numIndices, materialPath);
|
||||||
|
});
|
||||||
|
auto fut = _rl->add_task(lambda);
|
||||||
|
fut.wait();
|
||||||
|
return fut.get();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -545,4 +545,10 @@ abstract class FilamentController {
|
|||||||
/// If there is a collision between the controlled entity and [collidableEntity], the transform will not be updated.
|
/// If there is a collision between the controlled entity and [collidableEntity], the transform will not be updated.
|
||||||
///
|
///
|
||||||
Future addCollisionComponent(FilamentEntity collidableEntity);
|
Future addCollisionComponent(FilamentEntity collidableEntity);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Creates a (renderable) entity with the specified geometry and adds to the scene.
|
||||||
|
///
|
||||||
|
Future createGeometry(
|
||||||
|
List<double> vertices, List<int> indices, String? materialPath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
|
||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
import 'dart:developer' as dev;
|
import 'dart:developer' as dev;
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -1367,4 +1366,39 @@ class FilamentControllerFFI extends FilamentController {
|
|||||||
|
|
||||||
add_collision_component(_assetManager!, entity);
|
add_collision_component(_assetManager!, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<FilamentEntity> createGeometry(
|
||||||
|
List<double> vertices, List<int> indices, String? materialPath) async {
|
||||||
|
if (_viewer == null) {
|
||||||
|
throw Exception("Viewer must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
final materialPathPtr =
|
||||||
|
materialPath?.toNativeUtf8(allocator: allocator) ?? nullptr;
|
||||||
|
final vertexPtr = allocator<Float>(vertices.length);
|
||||||
|
final indicesPtr = allocator<Uint16>(indices.length);
|
||||||
|
for (int i = 0; i < vertices.length; i++) {
|
||||||
|
vertexPtr.elementAt(i).value = vertices[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < indices.length; i++) {
|
||||||
|
indicesPtr.elementAt(i).value = indices[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
var entity = create_geometry_ffi(_viewer!, vertexPtr, vertices.length,
|
||||||
|
indicesPtr, indices.length, materialPathPtr.cast<Char>());
|
||||||
|
if (entity == _FILAMENT_ASSET_ERROR) {
|
||||||
|
throw Exception("Failed to create geometry");
|
||||||
|
}
|
||||||
|
|
||||||
|
_entities.add(entity);
|
||||||
|
_onLoadController.sink.add(entity);
|
||||||
|
|
||||||
|
allocator.free(materialPathPtr);
|
||||||
|
allocator.free(vertexPtr);
|
||||||
|
allocator.free(indicesPtr);
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -835,6 +835,19 @@ external void add_collision_component(
|
|||||||
int entityId,
|
int entityId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ffi.Native<
|
||||||
|
EntityId Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Float>,
|
||||||
|
ffi.Int, ffi.Pointer<ffi.Uint16>, ffi.Int, ffi.Pointer<ffi.Char>)>(
|
||||||
|
symbol: 'create_geometry', assetId: 'flutter_filament_plugin')
|
||||||
|
external int create_geometry(
|
||||||
|
ffi.Pointer<ffi.Void> viewer,
|
||||||
|
ffi.Pointer<ffi.Float> vertices,
|
||||||
|
int numVertices,
|
||||||
|
ffi.Pointer<ffi.Uint16> indices,
|
||||||
|
int numIndices,
|
||||||
|
ffi.Pointer<ffi.Char> materialPath,
|
||||||
|
);
|
||||||
|
|
||||||
@ffi.Native<
|
@ffi.Native<
|
||||||
ffi.Pointer<ffi.Void> Function(
|
ffi.Pointer<ffi.Void> Function(
|
||||||
ffi.Pointer<ffi.Void>,
|
ffi.Pointer<ffi.Void>,
|
||||||
@@ -1284,6 +1297,19 @@ external void reset_to_rest_pose_ffi(
|
|||||||
symbol: 'ios_dummy_ffi', assetId: 'flutter_filament_plugin')
|
symbol: 'ios_dummy_ffi', assetId: 'flutter_filament_plugin')
|
||||||
external void ios_dummy_ffi();
|
external void ios_dummy_ffi();
|
||||||
|
|
||||||
|
@ffi.Native<
|
||||||
|
EntityId Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Float>,
|
||||||
|
ffi.Int, ffi.Pointer<ffi.Uint16>, ffi.Int, ffi.Pointer<ffi.Char>)>(
|
||||||
|
symbol: 'create_geometry_ffi', assetId: 'flutter_filament_plugin')
|
||||||
|
external int create_geometry_ffi(
|
||||||
|
ffi.Pointer<ffi.Void> viewer,
|
||||||
|
ffi.Pointer<ffi.Float> vertices,
|
||||||
|
int numVertices,
|
||||||
|
ffi.Pointer<ffi.Uint16> indices,
|
||||||
|
int numIndices,
|
||||||
|
ffi.Pointer<ffi.Char> materialPath,
|
||||||
|
);
|
||||||
|
|
||||||
final class __mbstate_t extends ffi.Union {
|
final class __mbstate_t extends ffi.Union {
|
||||||
@ffi.Array.multi([128])
|
@ffi.Array.multi([128])
|
||||||
external ffi.Array<ffi.Char> __mbstate8;
|
external ffi.Array<ffi.Char> __mbstate8;
|
||||||
|
|||||||
Reference in New Issue
Block a user