Compare commits
No commits in common. "2de6bc82b7c28123062dbdd7c63d7db0959ae1b7" and "762268387e6e5da36dc23e23c1cd46cef184941a" have entirely different histories.
2de6bc82b7
...
762268387e
47 changed files with 181 additions and 428 deletions
|
|
@ -19,6 +19,5 @@ file(GLOB APP_SOURCES "./applications/*.cpp")
|
||||||
add_executable(3DEditorApp ${APP_SOURCES})
|
add_executable(3DEditorApp ${APP_SOURCES})
|
||||||
target_link_libraries(3DEditorApp ${PROJECT_NAME})
|
target_link_libraries(3DEditorApp ${PROJECT_NAME})
|
||||||
|
|
||||||
file(COPY "../RasterRender/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
file(COPY "rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
||||||
file(COPY "../Graphics/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
file(COPY "rsc/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
||||||
file(COPY "../3DScene/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
|
||||||
|
|
|
||||||
|
|
@ -37,4 +37,4 @@ void Editor::denoise() {
|
||||||
if (device.getError(errorMessage) != oidn::Error::None) {
|
if (device.getError(errorMessage) != oidn::Error::None) {
|
||||||
std::cerr << "Error: " << errorMessage << std::endl;
|
std::cerr << "Error: " << errorMessage << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -24,10 +24,7 @@ Editor::Editor() {
|
||||||
void Editor::renderViewport() {
|
void Editor::renderViewport() {
|
||||||
switch (mRenderType) {
|
switch (mRenderType) {
|
||||||
case RenderType::RASTER:
|
case RenderType::RASTER:
|
||||||
mRasterRenderer.beginRender(mScene, mScene.mRenderSettings.size);
|
mRasterRenderer.render(mScene, mScene.mRenderSettings.size);
|
||||||
mRasterRenderer.renderDefault(mScene);
|
|
||||||
if (mActive) mRasterRenderer.renderOutline(mScene.mCamera, *mActive);
|
|
||||||
mRasterRenderer.endRender();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RenderType::PATH_TRACER:
|
case RenderType::PATH_TRACER:
|
||||||
|
|
@ -57,7 +54,6 @@ uint4 Editor::getViewportTexID() {
|
||||||
|
|
||||||
void Editor::loadDefaults() {
|
void Editor::loadDefaults() {
|
||||||
mScene.load("rsc/scene/script.lua");
|
mScene.load("rsc/scene/script.lua");
|
||||||
mResetCamera = mScene.mCamera;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setViewportSize(const Vec2F& size) {
|
void Editor::setViewportSize(const Vec2F& size) {
|
||||||
|
|
@ -77,7 +73,6 @@ Editor::~Editor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::renderPathFrame() {
|
void Editor::renderPathFrame() {
|
||||||
mScene.updateCache();
|
|
||||||
mPathRenderer.render(mScene, mPathTracerBuffers, mScene.mRenderSettings);
|
mPathRenderer.render(mScene, mPathTracerBuffers, mScene.mRenderSettings);
|
||||||
sendBuffersToGPU();
|
sendBuffersToGPU();
|
||||||
}
|
}
|
||||||
|
|
@ -121,20 +116,5 @@ void Editor::navigationZoom(halnf factor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::navigationReset() {
|
void Editor::navigationReset() {
|
||||||
mScene.mCamera = mResetCamera;
|
mScene.mCamera.lookAtPoint({ 0, 0, 0 }, { 1, 5, 1 }, { 0, 0, 1 });
|
||||||
// mScene.mCamera.lookAtPoint({ 0, 0, 0 }, { 1, 5, 1 }, { 0, 0, 1 });
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Editor::selectObject(const Vec2F& screenPos) {
|
|
||||||
mScene.updateCache();
|
|
||||||
|
|
||||||
auto dir = (mScene.mCamera.project(screenPos) - mScene.mCamera.getPos()).normalize();
|
|
||||||
Ray ray = Ray( dir, mScene.mCamera.getPos() );
|
|
||||||
|
|
||||||
auto rayCastData = mScene.castRay(ray, 1000);
|
|
||||||
mActive = rayCastData.obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object* Editor::getActiveObject() { return mActive; }
|
|
||||||
|
|
||||||
Scene* Editor::getScene() { return &mScene; }
|
|
||||||
|
|
@ -28,10 +28,6 @@ namespace tp {
|
||||||
void navigationZoom(halnf factor);
|
void navigationZoom(halnf factor);
|
||||||
void navigationReset();
|
void navigationReset();
|
||||||
|
|
||||||
void selectObject(const Vec2F& screenPos);
|
|
||||||
Object* getActiveObject();
|
|
||||||
|
|
||||||
Scene* getScene();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sendBuffersToGPU();
|
void sendBuffersToGPU();
|
||||||
|
|
@ -40,8 +36,6 @@ namespace tp {
|
||||||
private:
|
private:
|
||||||
Scene mScene;
|
Scene mScene;
|
||||||
|
|
||||||
Camera mResetCamera;
|
|
||||||
|
|
||||||
RenderType mRenderType = RenderType::RASTER;
|
RenderType mRenderType = RenderType::RASTER;
|
||||||
|
|
||||||
RasterRender mRasterRenderer;
|
RasterRender mRasterRenderer;
|
||||||
|
|
@ -49,7 +43,5 @@ namespace tp {
|
||||||
|
|
||||||
RayTracer::OutputBuffers mPathTracerBuffers;
|
RayTracer::OutputBuffers mPathTracerBuffers;
|
||||||
uint4 mPathRenderTexture = 0;
|
uint4 mPathRenderTexture = 0;
|
||||||
|
|
||||||
Object* mActive = nullptr;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -66,13 +66,11 @@ namespace tp {
|
||||||
mNavigationOrbit.setText("Orbit");
|
mNavigationOrbit.setText("Orbit");
|
||||||
mNavigationZoom.setText("Zoom");
|
mNavigationZoom.setText("Zoom");
|
||||||
mNavigationReset.setText("Reset");
|
mNavigationReset.setText("Reset");
|
||||||
mNavigationSelect.setText("Select");
|
|
||||||
|
|
||||||
mNavigationMenu.addToMenu(&mNavigationPan);
|
mNavigationMenu.addToMenu(&mNavigationPan);
|
||||||
mNavigationMenu.addToMenu(&mNavigationOrbit);
|
mNavigationMenu.addToMenu(&mNavigationOrbit);
|
||||||
mNavigationMenu.addToMenu(&mNavigationZoom);
|
mNavigationMenu.addToMenu(&mNavigationZoom);
|
||||||
mNavigationMenu.addToMenu(&mNavigationReset);
|
mNavigationMenu.addToMenu(&mNavigationReset);
|
||||||
mNavigationMenu.addToMenu(&mNavigationSelect);
|
|
||||||
|
|
||||||
mNavigationMenu.setText("Navigation");
|
mNavigationMenu.setText("Navigation");
|
||||||
}
|
}
|
||||||
|
|
@ -87,25 +85,16 @@ namespace tp {
|
||||||
mNavigationOrbit.setAction( [this]() { mNavigationType = ORBIT; });
|
mNavigationOrbit.setAction( [this]() { mNavigationType = ORBIT; });
|
||||||
mNavigationPan.setAction( [this]() { mNavigationType = PAN; });
|
mNavigationPan.setAction( [this]() { mNavigationType = PAN; });
|
||||||
mNavigationZoom.setAction( [this](){ mNavigationType = ZOOM; });
|
mNavigationZoom.setAction( [this](){ mNavigationType = ZOOM; });
|
||||||
mNavigationSelect.setAction( [this](){ mNavigationType = SELECT; });
|
|
||||||
mNavigationReset.setAction( [this]() { mEditor->navigationReset(); });
|
mNavigationReset.setAction( [this]() { mEditor->navigationReset(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void process(const EventHandler& events) override {
|
void process(const EventHandler& events) override {
|
||||||
DockWidget::process(events);
|
DockWidget::process(events);
|
||||||
|
|
||||||
if (auto obj = mEditor->getActiveObject()) { // dummy rotate active object
|
|
||||||
auto rotator = obj->mTopology.Basis.rotatorDir({1, 1, 1}, 0.1);
|
|
||||||
obj->mTopology.Basis = rotator * obj->mTopology.Basis;
|
|
||||||
}
|
|
||||||
|
|
||||||
mEditor->getScene()->updateCache();
|
|
||||||
|
|
||||||
const auto& activeArea = mViewport.getArea();
|
|
||||||
|
|
||||||
auto pointer = events.getPointer();
|
auto pointer = events.getPointer();
|
||||||
auto pointerPrev = events.getPointerPrev();
|
auto pointerPrev = events.getPointerPrev();
|
||||||
auto pointerRelative = (((pointer - activeArea.pos) / activeArea.size) - 0.5f) * 2;
|
|
||||||
|
const auto& activeArea = mViewport.getArea();
|
||||||
|
|
||||||
if (activeArea.isInside(pointer) && events.isDown(InputID::MOUSE1)) {
|
if (activeArea.isInside(pointer) && events.isDown(InputID::MOUSE1)) {
|
||||||
switch (mNavigationType) {
|
switch (mNavigationType) {
|
||||||
|
|
@ -113,13 +102,13 @@ namespace tp {
|
||||||
|
|
||||||
case PAN:
|
case PAN:
|
||||||
{
|
{
|
||||||
|
auto pointerRelative = (((pointer - activeArea.pos) / activeArea.size) - 0.5f) * 2;
|
||||||
auto prevPointerRelative = (((pointerPrev - activeArea.pos) / activeArea.size) - 0.5f) * 2;
|
auto prevPointerRelative = (((pointerPrev - activeArea.pos) / activeArea.size) - 0.5f) * 2;
|
||||||
mEditor->navigationPan(prevPointerRelative, pointerRelative);
|
mEditor->navigationPan(prevPointerRelative, pointerRelative);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ZOOM: mEditor->navigationZoom(1 + (events.getPointerDelta().y / activeArea.size.y)); break;
|
case ZOOM: mEditor->navigationZoom(1 + (events.getPointerDelta().y / activeArea.size.y)); break;
|
||||||
case SELECT: mEditor->selectObject(pointerRelative * -1); break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -140,14 +129,13 @@ namespace tp {
|
||||||
ButtonWidget mRenderDeNoise;
|
ButtonWidget mRenderDeNoise;
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
enum NavigationType { SELECT, ORBIT, PAN, ZOOM } mNavigationType = ORBIT;
|
enum NavigationType { ORBIT, PAN, ZOOM } mNavigationType = ORBIT;
|
||||||
|
|
||||||
FloatingMenu mNavigationMenu;
|
FloatingMenu mNavigationMenu;
|
||||||
ButtonWidget mNavigationPan;
|
ButtonWidget mNavigationPan;
|
||||||
ButtonWidget mNavigationOrbit;
|
ButtonWidget mNavigationOrbit;
|
||||||
ButtonWidget mNavigationZoom;
|
ButtonWidget mNavigationZoom;
|
||||||
ButtonWidget mNavigationReset;
|
ButtonWidget mNavigationReset;
|
||||||
ButtonWidget mNavigationSelect;
|
|
||||||
|
|
||||||
RGBA mBaseColor;
|
RGBA mBaseColor;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,9 @@
|
||||||
Meshes = "meshes.obj"
|
Meshes = "meshes.obj"
|
||||||
|
|
||||||
Camera = {
|
Camera = {
|
||||||
pos = { 0, 5, 0 },
|
pos = { 0.5, 4.5, 0.2 },
|
||||||
target = { 0, 0, 0 },
|
size_x = 600,
|
||||||
up = { 0, 0, 1 },
|
size_y = 800,
|
||||||
size = { 600, 800 },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Lights = {
|
Lights = {
|
||||||
11
3DEditor/rsc/shaders/default.vert
Normal file
11
3DEditor/rsc/shaders/default.vert
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 Point;
|
||||||
|
|
||||||
|
uniform vec4 Origin;
|
||||||
|
uniform mat4 Basis;
|
||||||
|
uniform mat4 Camera;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = Camera * vec4(Point.xyz, 1.0);
|
||||||
|
}
|
||||||
|
|
@ -7,61 +7,6 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
tp::Vec3F tp::Scene::getVec3(lua_State* state, const char* name) {
|
|
||||||
int stackSize = lua_gettop(state);
|
|
||||||
|
|
||||||
// Access the "pos" field and validate it
|
|
||||||
lua_getfield(state, -1, name);
|
|
||||||
if (!lua_istable(state, -1) || lua_rawlen(state, -1) != 3) {
|
|
||||||
throw IOError(std::string("Invalid vec3 named ") + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the values from the table
|
|
||||||
float pos[3];
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
lua_rawgeti(state, -1, i + 1);
|
|
||||||
if (lua_isnumber(state, -1)) {
|
|
||||||
pos[i] = lua_tonumber(state, -1);
|
|
||||||
} else {
|
|
||||||
throw IOError("vec3 values must be numbers");
|
|
||||||
}
|
|
||||||
lua_pop(state, 1); // pop number
|
|
||||||
}
|
|
||||||
lua_pop(state, 1); // pop vec3
|
|
||||||
|
|
||||||
ASSERT(stackSize == lua_gettop(state))
|
|
||||||
|
|
||||||
return { pos[0], pos[1], pos[2] };
|
|
||||||
}
|
|
||||||
|
|
||||||
tp::Vec2F tp::Scene::getVec2(lua_State* state, const char* name) {
|
|
||||||
int stackSize = lua_gettop(state);
|
|
||||||
|
|
||||||
// Access the "pos" field and validate it
|
|
||||||
lua_getfield(state, -1, name);
|
|
||||||
if (!lua_istable(state, -1) || lua_rawlen(state, -1) != 2) {
|
|
||||||
throw IOError(std::string("Invalid vec2 named ") + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the values from the table
|
|
||||||
float pos[2];
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
lua_rawgeti(state, -1, i + 1);
|
|
||||||
if (lua_isnumber(state, -1)) {
|
|
||||||
pos[i] = lua_tonumber(state, -1);
|
|
||||||
} else {
|
|
||||||
throw IOError("vec3 values must be numbers");
|
|
||||||
}
|
|
||||||
lua_pop(state, 1); // pop number
|
|
||||||
}
|
|
||||||
lua_pop(state, 1); // pop vec3
|
|
||||||
|
|
||||||
ASSERT(stackSize == lua_gettop(state))
|
|
||||||
|
|
||||||
return { pos[0], pos[1] };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to read a Lua table representing RenderSettings
|
// Function to read a Lua table representing RenderSettings
|
||||||
int readRenderSettings(lua_State* L, tp::RenderSettings& settings) {
|
int readRenderSettings(lua_State* L, tp::RenderSettings& settings) {
|
||||||
|
|
@ -108,8 +53,23 @@ int readRenderSettings(lua_State* L, tp::RenderSettings& settings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to read a Lua table representing a light
|
// Function to read a Lua table representing a light
|
||||||
int tp::Scene::readLight(lua_State* L, tp::PointLight* light) {
|
int readLight(lua_State* L, tp::PointLight* light) {
|
||||||
light->pos = getVec3(L, "pos");
|
lua_getfield(L, -1, "pos"); // Get the "pos" field from the light table
|
||||||
|
if (!lua_istable(L, -1)) {
|
||||||
|
printf("Light is missing the 'pos' table.\n");
|
||||||
|
return 0; // Error
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
lua_rawgeti(L, -1, i + 1); // Index is 1-based in Lua
|
||||||
|
if (!lua_isnumber(L, -1)) {
|
||||||
|
printf("Light 'pos' field is not a number at index %d.\n", i);
|
||||||
|
lua_pop(L, 2); // Pop both the number and the 'pos' table
|
||||||
|
return 0; // Error
|
||||||
|
}
|
||||||
|
light->pos[i] = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1); // Pop the number
|
||||||
|
}
|
||||||
|
lua_pop(L, 1); // Pop the 'pos' table
|
||||||
|
|
||||||
lua_getfield(L, -1, "intensity"); // Get the "intensity" field from the light table
|
lua_getfield(L, -1, "intensity"); // Get the "intensity" field from the light table
|
||||||
if (!lua_isnumber(L, -1)) {
|
if (!lua_isnumber(L, -1)) {
|
||||||
|
|
@ -161,29 +121,66 @@ bool tp::Scene::loadLuaFormat(const std::string& scenePath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- camera
|
// --- camera
|
||||||
{
|
|
||||||
lua_getglobal(L, "Camera");
|
// Access Camera table
|
||||||
if (!lua_istable(L, -1)) {
|
lua_getglobal(L, "Camera");
|
||||||
printf("Camera is not a table.\n");
|
if (!lua_istable(L, -1)) {
|
||||||
|
printf("Camera is not a table.\n");
|
||||||
|
lua_close(L);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify you are inside the "Camera" table
|
||||||
|
int cameraTableIndex = lua_gettop(L); // Get the index of the "Camera" table
|
||||||
|
|
||||||
|
// Access the "pos" field and validate it
|
||||||
|
lua_getfield(L, cameraTableIndex, "pos");
|
||||||
|
if (!lua_istable(L, -1) || lua_rawlen(L, -1) != 3) {
|
||||||
|
printf("Invalid 'pos' field in Camera table.\n");
|
||||||
|
lua_close(L);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the values from the table
|
||||||
|
float pos[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
lua_rawgeti(L, -1, i + 1);
|
||||||
|
if (lua_isnumber(L, -1)) {
|
||||||
|
pos[i] = lua_tonumber(L, -1);
|
||||||
|
} else {
|
||||||
|
printf("Invalid 'pos' field value at index %d.\n", i + 1);
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3F camPos = getVec3(L, "pos");
|
|
||||||
Vec3F camTarget = getVec3(L, "target");
|
|
||||||
Vec3F camUp = getVec3(L, "up");
|
|
||||||
Vec2F camSize = getVec2(L, "size");
|
|
||||||
|
|
||||||
mRenderSettings.size = camSize;
|
|
||||||
|
|
||||||
mCamera.lookAtPoint(camTarget, camPos, camUp);
|
|
||||||
mCamera.setFOV(3.14 / 4);
|
|
||||||
mCamera.setFar(100);
|
|
||||||
mCamera.setRatio((tp::halnf) camSize.y / (tp::halnf) camSize.x);
|
|
||||||
|
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Access the "size_x" field and validate it
|
||||||
|
lua_getfield(L, cameraTableIndex, "size_x");
|
||||||
|
if (!lua_isnumber(L, -1)) {
|
||||||
|
printf("Invalid or missing 'size_x' field in Camera table.\n");
|
||||||
|
lua_close(L);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int size_x = lua_tointeger(L, -1);
|
||||||
|
lua_pop(L, 1); // Pop the 'size_x' value from the stack
|
||||||
|
|
||||||
|
// Access the "size_y" field and validate it
|
||||||
|
lua_getfield(L, cameraTableIndex, "size_y");
|
||||||
|
if (!lua_isnumber(L, -1)) {
|
||||||
|
printf("Invalid or missing 'size_y' field in Camera table.\n");
|
||||||
|
lua_close(L);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int size_y = lua_tointeger(L, -1);
|
||||||
|
|
||||||
|
mRenderSettings.size = { (tp::halnf) size_x, (tp::halnf) size_y };
|
||||||
|
|
||||||
|
mCamera.lookAtPoint({ 0, 0, 0 }, { pos[0], pos[1], pos[2] }, { 0, 0, 1 });
|
||||||
|
mCamera.setFOV(3.14 / 4);
|
||||||
|
mCamera.setFar(100);
|
||||||
|
mCamera.setRatio((tp::halnf) size_y / (tp::halnf) size_x);
|
||||||
|
|
||||||
// ---------- LIGHTS
|
// ---------- LIGHTS
|
||||||
{
|
{
|
||||||
lua_getglobal(L, "Lights");
|
lua_getglobal(L, "Lights");
|
||||||
|
|
|
||||||
|
|
@ -48,39 +48,4 @@ bool tp::Scene::loadOBJFormat(const std::string& objetsPath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return mObjects.size();
|
return mObjects.size();
|
||||||
}
|
|
||||||
|
|
||||||
const tp::RayCastData& tp::Scene::castRay(const Ray& ray, alnf farVal) {
|
|
||||||
auto& out = mRayCastData;
|
|
||||||
|
|
||||||
out.hit = false;
|
|
||||||
out.obj = nullptr;
|
|
||||||
|
|
||||||
farVal *= farVal;
|
|
||||||
|
|
||||||
for (auto obj : mObjects) {
|
|
||||||
for (auto trig : obj->mCache.TrigCaches) {
|
|
||||||
if (trig->castRay(ray)) {
|
|
||||||
|
|
||||||
auto dist = (TrigCache::getHitPos() - ray.pos).length2();
|
|
||||||
|
|
||||||
if (farVal > dist && dist > EPSILON) {
|
|
||||||
out.trig = &trig.data();
|
|
||||||
out.hitPos = TrigCache::getHitPos();
|
|
||||||
out.obj = &obj.data();
|
|
||||||
out.hit = true;
|
|
||||||
|
|
||||||
farVal = dist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mRayCastData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tp::Scene::updateCache() {
|
|
||||||
for (auto obj : mObjects) {
|
|
||||||
obj->mCache.updateCache();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,13 +2,5 @@
|
||||||
#include "Scene.hpp"
|
#include "Scene.hpp"
|
||||||
|
|
||||||
bool tp::Scene::load(const std::string& scenePath) {
|
bool tp::Scene::load(const std::string& scenePath) {
|
||||||
try {
|
return loadLuaFormat(scenePath);
|
||||||
auto res = loadLuaFormat(scenePath);
|
|
||||||
if (!res) throw IOError("Failed loading lua script");
|
|
||||||
} catch (const IOError& err) {
|
|
||||||
printf("Failed loading scene : %s\n", err.description.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct lua_State;
|
|
||||||
|
|
||||||
namespace tp {
|
namespace tp {
|
||||||
struct RenderSettings {
|
struct RenderSettings {
|
||||||
uhalni depth = 2;
|
uhalni depth = 2;
|
||||||
|
|
@ -44,22 +42,7 @@ namespace tp {
|
||||||
halnf intensity = 1.f;
|
halnf intensity = 1.f;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RayCastData {
|
|
||||||
Object* obj = nullptr;
|
|
||||||
TrigCache* trig = nullptr;
|
|
||||||
Vec3F hitPos = { 0, 0, 0 };
|
|
||||||
bool hit = false;
|
|
||||||
bool inv = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Scene {
|
class Scene {
|
||||||
struct IOError : public std::exception {
|
|
||||||
explicit IOError(std::string in) :
|
|
||||||
description(std::move(in)) {}
|
|
||||||
|
|
||||||
std::string description;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Scene() = default;
|
Scene() = default;
|
||||||
|
|
||||||
|
|
@ -68,23 +51,11 @@ namespace tp {
|
||||||
bool loadLuaFormat(const std::string& scenePath);
|
bool loadLuaFormat(const std::string& scenePath);
|
||||||
bool loadOBJFormat(const std::string& objectsPath);
|
bool loadOBJFormat(const std::string& objectsPath);
|
||||||
|
|
||||||
const RayCastData& castRay(const Ray& ray, alnf farVal);
|
|
||||||
|
|
||||||
void updateCache();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Vec3F getVec3(lua_State* state, const char* name);
|
|
||||||
Vec2F getVec2(lua_State* state, const char* name);
|
|
||||||
|
|
||||||
int readLight(lua_State* L, tp::PointLight* light);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Buffer<Object> mObjects;
|
Buffer<Object> mObjects;
|
||||||
Buffer<PointLight> mLights;
|
Buffer<PointLight> mLights;
|
||||||
Camera mCamera;
|
Camera mCamera;
|
||||||
|
|
||||||
RenderSettings mRenderSettings;
|
RenderSettings mRenderSettings;
|
||||||
|
|
||||||
RayCastData mRayCastData;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,5 +19,5 @@ target_link_libraries(Example${PROJECT_NAME} ${PROJECT_NAME} ${BINDINGS_LIBS})
|
||||||
target_include_directories(Example${PROJECT_NAME} PRIVATE ${BINDINGS_INCLUDE})
|
target_include_directories(Example${PROJECT_NAME} PRIVATE ${BINDINGS_INCLUDE})
|
||||||
|
|
||||||
|
|
||||||
file(COPY "../Graphics/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
file(COPY "examples/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
||||||
|
|
||||||
|
|
|
||||||
BIN
Graphics/examples/Font.ttf
Normal file
BIN
Graphics/examples/Font.ttf
Normal file
Binary file not shown.
|
|
@ -27,7 +27,7 @@ Canvas::Canvas(Window* window) {
|
||||||
|
|
||||||
mContext->vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
|
mContext->vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
|
||||||
|
|
||||||
if (nvgCreateFont(mContext->vg, "default", "rsc/Font.ttf") == -1) {
|
if (nvgCreateFont(mContext->vg, "default", "Font.ttf") == -1) {
|
||||||
ASSERT(!"Cant create NVG font")
|
ASSERT(!"Cant create NVG font")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ DebugGUI::DebugGUI(Window* window) {
|
||||||
ImGui_ImplOpenGL3_Init("#version 330");
|
ImGui_ImplOpenGL3_Init("#version 330");
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.Fonts->AddFontFromFileTTF("rsc/Font.ttf", 20.f);
|
io.Fonts->AddFontFromFileTTF("Font.ttf", 20.f);
|
||||||
|
|
||||||
io.ConfigInputTrickleEventQueue = false;
|
io.ConfigInputTrickleEventQueue = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ namespace tp {
|
||||||
[[nodiscard]] halnf getPointerPressure() const;
|
[[nodiscard]] halnf getPointerPressure() const;
|
||||||
|
|
||||||
void setEnableKeyEvents(bool);
|
void setEnableKeyEvents(bool);
|
||||||
[[nodiscard]] bool isKeyEventsEnabled() const { return mEnableKeyEvents; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void processEventUnguarded();
|
void processEventUnguarded();
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ void Camera::lookAtPoint(const Vec3F& aTarget, const Vec3F& aPos, Vec3F aUp) {
|
||||||
}
|
}
|
||||||
mPos = aPos;
|
mPos = aPos;
|
||||||
mTarget = aTarget;
|
mTarget = aTarget;
|
||||||
Vec3F f = (mTarget - mPos).normalize();
|
Vec3F f = (mPos - mTarget).normalize();
|
||||||
mUp = f * (aUp.normalize() * f);
|
mUp = f * (aUp.normalize() * f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,20 +117,16 @@ void Camera::rotate(halnf angleX, halnf angleY) {
|
||||||
Vec3F wup(0, 0, 1);
|
Vec3F wup(0, 0, 1);
|
||||||
mPos -= mTarget;
|
mPos -= mTarget;
|
||||||
|
|
||||||
Mat3F rotZ = Mat3F::rotatorDir(wup, angleX);
|
mat3f rotZ = mat3f::rotatorDir(wup, angleX);
|
||||||
mPos = rotZ * mPos;
|
mPos = rotZ * mPos;
|
||||||
mUp = rotZ * mUp;
|
mUp = rotZ * mUp;
|
||||||
|
|
||||||
Vec3F f = mPos.unitV();
|
Vec3F f = mPos.unitV();
|
||||||
Vec3F s = mUp * f;
|
Vec3F s = mUp * f;
|
||||||
|
|
||||||
mPos = Mat3F::rotatorDir(s, -angleY) * mPos;
|
mPos = mat3f::rotatorDir(s, -angleY) * mPos;
|
||||||
|
|
||||||
mPos += mTarget;
|
mPos += mTarget;
|
||||||
|
|
||||||
lookAtPoint(mTarget, mPos, mUp);
|
lookAtPoint(mTarget, mPos, mUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::setPos(Vec3F pos) {
|
|
||||||
mPos = pos;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ namespace tp {
|
||||||
void setRatio(halnf ratio);
|
void setRatio(halnf ratio);
|
||||||
void setFOV(halnf fov);
|
void setFOV(halnf fov);
|
||||||
void setFar(halnf far);
|
void setFar(halnf far);
|
||||||
void setPos(Vec3F pos);
|
|
||||||
|
|
||||||
[[nodiscard]] const Vec3F& getPos() const;
|
[[nodiscard]] const Vec3F& getPos() const;
|
||||||
[[nodiscard]] const Vec3F& getTarget() const;
|
[[nodiscard]] const Vec3F& getTarget() const;
|
||||||
|
|
|
||||||
|
|
@ -465,7 +465,7 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matrix Properties
|
// Matrix Properties
|
||||||
MVec transform(const MVec& in) const { return MVec(i.x * in.x + i.y * in.y, j.x * in.x + j.y * in.y); }
|
MVec transform(const MVec& in) const { return MVec(i.x * in.x + i.y * in.y, j.x * in.y + j.y * in.x); }
|
||||||
|
|
||||||
Mat transform(const Mat& in) const {
|
Mat transform(const Mat& in) const {
|
||||||
Mat out;
|
Mat out;
|
||||||
|
|
@ -495,8 +495,8 @@ namespace tp {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
using Mat3 = Mat<Type, 3, 3>;
|
using mat3 = Mat<Type, 3, 3>;
|
||||||
using Mat3F = Mat3<halnf>;
|
using mat3f = mat3<halnf>;
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
class Mat<Type, 3, 3> {
|
class Mat<Type, 3, 3> {
|
||||||
|
|
@ -647,22 +647,22 @@ namespace tp {
|
||||||
|
|
||||||
Mat inv() { return cofactors() /= det(); }
|
Mat inv() { return cofactors() /= det(); }
|
||||||
|
|
||||||
Mat rotatorX(alnf angle) const {
|
Mat rotatorX(alnf angle) {
|
||||||
alnf cosA = (alnf) cos(angle);
|
alnf cosA = (alnf) cos(angle);
|
||||||
alnf sinA = (alnf) sin(angle);
|
alnf sinA = (alnf) sin(angle);
|
||||||
return { { 1, 0, 0 }, { 0, cosA, -sinA }, { 0, sinA, cosA } };
|
return { { 1, 0, 0 }, { 0, cosA, -sinA }, { 0, sinA, cosA } };
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat rotatorY(alnf angle) const {
|
Mat rotatorY(alnf angle) {
|
||||||
alnf cosA = (alnf) cos(angle);
|
alnf cosA = (alnf) cos(angle);
|
||||||
alnf sinA = (alnf) sin(angle);
|
alnf sinA = (alnf) sin(angle);
|
||||||
return { { cosA, 0, sinA }, { 0, 1, 0 }, { -sinA, 0, cosA } };
|
return { { cosA, 0, sinA }, { 0, 1, 0 }, { -sinA, 0, cosA } };
|
||||||
}
|
}
|
||||||
|
|
||||||
static Mat rotatorZ(alnf angle) {
|
Mat rotatorZ(alnf angle) {
|
||||||
Type cosA = (Type) cos(angle);
|
alnf cosA = (alnf) cos(angle);
|
||||||
Type sinA = (Type) sin(angle);
|
alnf sinA = (alnf) sin(angle);
|
||||||
return { vec{ cosA, -sinA, 0 }, vec{ sinA, cosA, 0 }, vec{ 0, 0, 1 } };
|
return { { cosA, -sinA, 0 }, { sinA, cosA, 0 }, { 0, 0, 1 } };
|
||||||
}
|
}
|
||||||
|
|
||||||
static Mat rotatorDir(vec dir, alnf angle) {
|
static Mat rotatorDir(vec dir, alnf angle) {
|
||||||
|
|
@ -707,14 +707,4 @@ namespace tp {
|
||||||
|
|
||||||
Type det() { return Type(); }
|
Type det() { return Type(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
Mat<Type, 4, 4> toMat4(const Mat<Type, 3, 3>& in) {
|
|
||||||
Mat<Type, 4, 4> out;
|
|
||||||
out[0] = { in[0][0], in[0][1], in[0][2], 0 };
|
|
||||||
out[1] = { in[1][0], in[1][1], in[1][2], 0 };
|
|
||||||
out[2] = { in[2][0], in[2][1], in[2][2], 0 };
|
|
||||||
out[3] = { Type(0), Type(0), Type(0), Type(1) };
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace tp {
|
||||||
|
|
||||||
struct Topology {
|
struct Topology {
|
||||||
Vec3F Origin = { 0, 0, 0 };
|
Vec3F Origin = { 0, 0, 0 };
|
||||||
Mat3F Basis = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
|
mat3f Basis = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
|
||||||
|
|
||||||
Buffer<Vec3F> Points;
|
Buffer<Vec3F> Points;
|
||||||
Buffer<Vec3F> Normals;
|
Buffer<Vec3F> Normals;
|
||||||
|
|
|
||||||
|
|
@ -110,13 +110,6 @@ namespace tp {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec& operator=(Type val) {
|
|
||||||
for (ualni i = 0; i < tSize; i++) {
|
|
||||||
get(i) = val;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void assign(Type val) {
|
void assign(Type val) {
|
||||||
for (ualni i = 0; i < tSize; i++) {
|
for (ualni i = 0; i < tSize; i++) {
|
||||||
get(i) = val;
|
get(i) = val;
|
||||||
|
|
@ -583,14 +576,4 @@ namespace tp {
|
||||||
|
|
||||||
using Vec4F = Vec4<halnf>;
|
using Vec4F = Vec4<halnf>;
|
||||||
using Vec4I = Vec4<halni>;
|
using Vec4I = Vec4<halni>;
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
Vec<Type, 4> toVec4(const Vec<Type, 3>& in) {
|
|
||||||
Vec<Type, 4> out;
|
|
||||||
out[0] = in[0];
|
|
||||||
out[1] = in[1];
|
|
||||||
out[2] = in[2];
|
|
||||||
out[3] = 0;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +102,7 @@ void RenderBuffer::setViewport(const RectF& viewport) {
|
||||||
|
|
||||||
void RenderBuffer::clear() {
|
void RenderBuffer::clear() {
|
||||||
AssertGL(glClearColor(mClearCol.r, mClearCol.g, mClearCol.b, mClearCol.a));
|
AssertGL(glClearColor(mClearCol.r, mClearCol.g, mClearCol.b, mClearCol.a));
|
||||||
AssertGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
|
AssertGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderBuffer::endDraw() {
|
void RenderBuffer::endDraw() {
|
||||||
|
|
|
||||||
|
|
@ -3,42 +3,26 @@
|
||||||
|
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
|
|
||||||
RasterRender::RasterRender() {
|
RasterRender::RasterRender() :
|
||||||
|
mRenderBuffer({ 100, 100 })
|
||||||
|
{
|
||||||
mDefaultShader.load("rsc/shaders/default.vert", nullptr, "rsc/shaders/default.frag", true);
|
mDefaultShader.load("rsc/shaders/default.vert", nullptr, "rsc/shaders/default.frag", true);
|
||||||
mSolidShader.load("rsc/shaders/default.vert", nullptr, "rsc/shaders/solid.frag", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterRender::~RasterRender() {}
|
RasterRender::~RasterRender() {}
|
||||||
|
|
||||||
void RasterRender::resize(const Vec2<tp::ualni>& size) {
|
|
||||||
auto sizeF = Vec2F(size.x, size.y);
|
|
||||||
mRenderBuffer.resize(sizeF);
|
|
||||||
mTempBuffer.resize(sizeF);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint4 RasterRender::getRenderBufferID() { return mRenderBuffer.texId(); }
|
uint4 RasterRender::getRenderBufferID() { return mRenderBuffer.texId(); }
|
||||||
|
|
||||||
Vec2F RasterRender::getBufferSize() { return mRenderBuffer.getSize(); }
|
Vec2F RasterRender::getBufferSize() { return mRenderBuffer.getSize(); }
|
||||||
|
|
||||||
void RasterRender::bindCameraShaderAttributes(const Mat4F& cameraMat) {
|
void RasterRender::render(const Scene& geometry, const Vec2<ualni>& size) {
|
||||||
static auto camera = (GLint) mDefaultShader.getu("Camera");
|
|
||||||
glUniformMatrix4fv(camera, 1, true, &cameraMat[0][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterRender::bindObjectShaderAttributes(const Object& object) {
|
for (auto object : geometry.mObjects) {
|
||||||
static auto origin = (GLint) mDefaultShader.getu("Origin");
|
if (!object->mGUPBuffers) {
|
||||||
static auto basis = (GLint) mDefaultShader.getu("Basis");
|
object->mGUPBuffers = new ObjectBuffers(&object.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Mat4F basisMat = toMat4(object.mTopology.Basis);
|
|
||||||
Vec4F originPoint = toVec4(object.mTopology.Origin);
|
|
||||||
|
|
||||||
basisMat = basisMat.transpose();
|
|
||||||
|
|
||||||
glUniform4fv(origin, 1, &originPoint[0]);
|
|
||||||
glUniformMatrix4fv(basis, 1, false, &basisMat[0][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterRender::renderDefault(const Scene& geometry) {
|
|
||||||
mRenderBuffer.mClearCol = { 0.0f, 0.0f, 0.0f, 0.f };
|
mRenderBuffer.mClearCol = { 0.0f, 0.0f, 0.0f, 0.f };
|
||||||
|
|
||||||
mRenderBuffer.beginDraw();
|
mRenderBuffer.beginDraw();
|
||||||
|
|
@ -53,21 +37,24 @@ void RasterRender::renderDefault(const Scene& geometry) {
|
||||||
// glPolygonMode(GL_FRONT, GL_LINE);
|
// glPolygonMode(GL_FRONT, GL_LINE);
|
||||||
// glPolygonMode(GL_BACK, GL_LINE);
|
// glPolygonMode(GL_BACK, GL_LINE);
|
||||||
|
|
||||||
// auto rotator = Mat3F::rotatorZ(alnf(0.001));
|
|
||||||
|
|
||||||
bindCameraShaderAttributes(cameraMat);
|
|
||||||
|
|
||||||
for (auto object : geometry.mObjects) {
|
for (auto object : geometry.mObjects) {
|
||||||
// object->mTopology.Origin += 0.01;
|
|
||||||
// object->mTopology.Basis = rotator * object->mTopology.Basis;
|
|
||||||
|
|
||||||
bindObjectShaderAttributes(object.data());
|
static auto origin = (GLint) mDefaultShader.getu("Origin");
|
||||||
|
static auto basis = (GLint) mDefaultShader.getu("Basis");
|
||||||
|
static auto camera = (GLint) mDefaultShader.getu("Camera");
|
||||||
|
|
||||||
|
Mat4F basisMat;
|
||||||
|
Vec4F originPoint;
|
||||||
|
|
||||||
|
glUniform4fv(origin, 1, &originPoint[0]);
|
||||||
|
glUniformMatrix4fv(basis, 1, false, &basisMat[0][0]);
|
||||||
|
glUniformMatrix4fv(camera, 1, true, &cameraMat[0][0]);
|
||||||
|
|
||||||
object->mGUPBuffers->drawCall();
|
object->mGUPBuffers->drawCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
mDefaultShader.unbind();
|
mDefaultShader.unbind();
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
|
|
||||||
// glPolygonMode(GL_FRONT, GL_FILL);
|
// glPolygonMode(GL_FRONT, GL_FILL);
|
||||||
// glPolygonMode(GL_BACK, GL_FILL);
|
// glPolygonMode(GL_BACK, GL_FILL);
|
||||||
|
|
@ -75,37 +62,4 @@ void RasterRender::renderDefault(const Scene& geometry) {
|
||||||
mRenderBuffer.endDraw();
|
mRenderBuffer.endDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterRender::renderOutline(const Camera& camera, const Object& object) {
|
|
||||||
mRenderBuffer.beginDraw();
|
|
||||||
|
|
||||||
// glEnable(GL_STENCIL_TEST);
|
|
||||||
|
|
||||||
mSolidShader.bind();
|
|
||||||
|
|
||||||
bindCameraShaderAttributes(camera.calculateTransformationMatrix());
|
|
||||||
bindObjectShaderAttributes(object);
|
|
||||||
|
|
||||||
object.mGUPBuffers->drawCall();
|
|
||||||
|
|
||||||
mSolidShader.unbind();
|
|
||||||
|
|
||||||
// glDisable(GL_STENCIL_TEST);
|
|
||||||
|
|
||||||
mRenderBuffer.endDraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterRender::beginRender(const Scene& geometry, const Vec2<tp::ualni>& size) {
|
|
||||||
resize(size);
|
|
||||||
|
|
||||||
for (auto object : geometry.mObjects) {
|
|
||||||
if (!object->mGUPBuffers) {
|
|
||||||
object->mGUPBuffers = new ObjectBuffers(&object.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterRender::endRender() {
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderBuffer* RasterRender::getRenderBuffer() { return &mRenderBuffer; }
|
RenderBuffer* RasterRender::getRenderBuffer() { return &mRenderBuffer; }
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
namespace tp {
|
namespace tp {
|
||||||
class RenderBuffer {
|
class RenderBuffer {
|
||||||
public:
|
public:
|
||||||
explicit RenderBuffer(const Vec2F& size = { 10, 10 });
|
explicit RenderBuffer(const Vec2F& size);
|
||||||
RenderBuffer(const Vec2F& size, tp::uint1 samples);
|
RenderBuffer(const Vec2F& size, tp::uint1 samples);
|
||||||
~RenderBuffer();
|
~RenderBuffer();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,27 +12,13 @@ namespace tp {
|
||||||
RasterRender();
|
RasterRender();
|
||||||
~RasterRender();
|
~RasterRender();
|
||||||
|
|
||||||
void beginRender(const Scene& geometry, const Vec2<ualni>& size);
|
void render(const Scene& geometry, const Vec2<ualni>& size);
|
||||||
void endRender();
|
|
||||||
|
|
||||||
void renderDefault(const Scene& geometry);
|
|
||||||
void renderOutline(const Camera& camera, const Object& object);
|
|
||||||
|
|
||||||
void resize(const Vec2<ualni>& size);
|
|
||||||
|
|
||||||
uint4 getRenderBufferID();
|
uint4 getRenderBufferID();
|
||||||
RenderBuffer* getRenderBuffer();
|
RenderBuffer* getRenderBuffer();
|
||||||
Vec2F getBufferSize();
|
Vec2F getBufferSize();
|
||||||
|
|
||||||
private:
|
|
||||||
void bindObjectShaderAttributes(const Object& object);
|
|
||||||
void bindCameraShaderAttributes(const Mat4F& cameraMat);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RenderBuffer mRenderBuffer;
|
RenderBuffer mRenderBuffer;
|
||||||
RenderBuffer mTempBuffer;
|
|
||||||
|
|
||||||
RenderShader mDefaultShader;
|
RenderShader mDefaultShader;
|
||||||
RenderShader mSolidShader;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
#version 330 core
|
|
||||||
|
|
||||||
layout(location = 0) in vec3 Point;
|
|
||||||
|
|
||||||
uniform vec4 Origin;
|
|
||||||
uniform mat4 Basis;
|
|
||||||
uniform mat4 Camera;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
// vec4 transformed = vec4(Point.xyz, 1.0);
|
|
||||||
vec4 transformed = (Basis * vec4(Point.xyz, 1.0)) + Origin;
|
|
||||||
gl_Position = Camera * transformed;
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#version 330 core
|
|
||||||
|
|
||||||
out vec4 FragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
FragColor = vec4(1, 0, 0, 1.f);
|
|
||||||
}
|
|
||||||
|
|
@ -43,8 +43,6 @@ normal = n1 * barycentric.x + n2 * barycentric.y + n3 * barycentric.z;
|
||||||
|
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
|
|
||||||
|
|
||||||
// TODO : de-duplicate in Scene?
|
|
||||||
void RayTracer::castRay(const Ray& ray, RayCastData& out, alnf farVal) {
|
void RayTracer::castRay(const Ray& ray, RayCastData& out, alnf farVal) {
|
||||||
out.hit = false;
|
out.hit = false;
|
||||||
out.obj = nullptr;
|
out.obj = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,14 @@ namespace tp {
|
||||||
void render(const Scene& scene, OutputBuffers& out, const RenderSettings& settings);
|
void render(const Scene& scene, OutputBuffers& out, const RenderSettings& settings);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct RayCastData {
|
||||||
|
const Object* obj = nullptr;
|
||||||
|
TrigCache* trig = nullptr;
|
||||||
|
Vec3F hitPos = { 0, 0, 0 };
|
||||||
|
bool hit = false;
|
||||||
|
bool inv = false;
|
||||||
|
};
|
||||||
|
|
||||||
struct LightData {
|
struct LightData {
|
||||||
halnf intensity = 0;
|
halnf intensity = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,4 @@ add_executable(Sketch3DApp ./applications/Entry.cpp)
|
||||||
target_link_libraries(Sketch3DApp ${PROJECT_NAME})
|
target_link_libraries(Sketch3DApp ${PROJECT_NAME})
|
||||||
|
|
||||||
file(COPY "rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
file(COPY "rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
||||||
file(COPY "../Graphics/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
file(COPY "applications/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ public:
|
||||||
Sketch3DApplication() {
|
Sketch3DApplication() {
|
||||||
setRoot(&mGui);
|
setRoot(&mGui);
|
||||||
|
|
||||||
mGui.createRenderWidget(mGraphics->getCanvas(), { 2560, 1440 });
|
mGui.createRenderWidget(mGraphics->getCanvas(), { 1920, 1080 });
|
||||||
mGui.setProject(&mSketch);
|
mGui.setProject(&mSketch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,4 +25,4 @@ void runApp() {
|
||||||
app.run();
|
app.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() { runApp(); }
|
int main() { runApp(); }
|
||||||
BIN
Sketch3D/applications/Font.ttf
Normal file
BIN
Sketch3D/applications/Font.ttf
Normal file
Binary file not shown.
|
|
@ -280,7 +280,7 @@ void PencilBrush::draw(Renderer* render, const Camera* camera) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PencilBrush::~PencilBrush() {
|
PencilBrush::~PencilBrush() {
|
||||||
delete mStroke;
|
if (mStroke) delete mStroke;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PencilBrush::finish(Project* proj) {
|
void PencilBrush::finish(Project* proj) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ using namespace tp;
|
||||||
class Example : public WidgetApplication {
|
class Example : public WidgetApplication {
|
||||||
public:
|
public:
|
||||||
Example() {
|
Example() {
|
||||||
exampleNestedMenus();
|
exampleColorPicker();
|
||||||
}
|
}
|
||||||
|
|
||||||
void exampleAll() {
|
void exampleAll() {
|
||||||
|
|
@ -64,7 +64,6 @@ public:
|
||||||
static ButtonWidget buttons[10];
|
static ButtonWidget buttons[10];
|
||||||
|
|
||||||
widget.setDirection(false);
|
widget.setDirection(false);
|
||||||
// widget.setDirection(false);
|
|
||||||
|
|
||||||
setRoot(&widget);
|
setRoot(&widget);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,7 @@ void RootWidget::processFrame(EventHandler* events, const RectF& screenArea) {
|
||||||
updateAreaCache(&mRoot, false);
|
updateAreaCache(&mRoot, false);
|
||||||
|
|
||||||
// trigger some widgets by moise pointer
|
// trigger some widgets by moise pointer
|
||||||
auto prevFocus = mUpdateManager.getFocusWidget();
|
mUpdateManager.handleFocusChanges(&mRoot, *events);
|
||||||
auto newFocus = mUpdateManager.findFocusWidget(&mRoot, *events);
|
|
||||||
mUpdateManager.handleFocusChanges(newFocus, prevFocus);
|
|
||||||
|
|
||||||
// check triggered widgets for removal
|
// check triggered widgets for removal
|
||||||
mUpdateManager.clean();
|
mUpdateManager.clean();
|
||||||
|
|
@ -150,11 +148,9 @@ void RootWidget::openPopup(Widget* widget) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWidget::closePopup(Widget* widget) {
|
void RootWidget::closePopup(Widget* widget) {
|
||||||
if (mUpdateManager.canRemoveWidget(widget)) {
|
mPopups.removeChild(widget);
|
||||||
mPopups.removeChild(widget);
|
mUpdateManager.freeFocus(widget);
|
||||||
mUpdateManager.removeWidget(widget);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWidget::lockFocus(Widget* widget) { mUpdateManager.lockFocus(widget); }
|
void RootWidget::lockFocus(Widget* widget) { mUpdateManager.lockFocus(widget); }
|
||||||
void RootWidget::freeFocus(Widget* widget) { mUpdateManager.freeFocus(widget); }
|
void RootWidget::freeFocus(Widget* widget) { mUpdateManager.freeFocus(widget); }
|
||||||
|
|
|
||||||
|
|
@ -113,17 +113,14 @@ void DebugManager::recursiveDraw(Canvas& canvas, Widget* active, const Vec2F& po
|
||||||
canvas.text((active->mDebug.id + ":" + std::to_string(depthOrder)).c_str(), area, 22, Canvas::Align::LC, 2, color);
|
canvas.text((active->mDebug.id + ":" + std::to_string(depthOrder)).c_str(), area, 22, Canvas::Align::LC, 2, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mRootWidget->mUpdateManager.mFocusLockStack.find(active)) {
|
|
||||||
canvas.frame(area, { 0, 1, 0, 0.5f });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (active->mFlags.get(Widget::IN_FOCUS)) {
|
if (active->mFlags.get(Widget::IN_FOCUS)) {
|
||||||
if (active->isUpdate()) {
|
if (active->isUpdate()) {
|
||||||
canvas.circle(pos + active->mDebug.pLocal, 5, active->mDebug.col);
|
canvas.circle(pos + active->mDebug.pLocal, 5, active->mDebug.col);
|
||||||
canvas.circle(active->mDebug.pGlobal, 15, active->mDebug.col);
|
canvas.circle(active->mDebug.pGlobal, 15, active->mDebug.col);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.debugCross(area, { 0, 1, 0, 1 });
|
RGBA color = { 1, 0, 0, 0.3f };
|
||||||
|
canvas.debugCross(area, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
int orderIdx = 0;
|
int orderIdx = 0;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ void LayoutManager::findDependencies(Widget* root) {
|
||||||
if (!widget->isUpdate()) continue;
|
if (!widget->isUpdate()) continue;
|
||||||
|
|
||||||
for (auto child : widget->mChildren) {
|
for (auto child : widget->mChildren) {
|
||||||
if (!child->isUpdate()) continue;
|
// if (!child->isUpdate()) continue;
|
||||||
|
|
||||||
mDepGraph.insert({ child, {} });
|
mDepGraph.insert({ child, {} });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,36 +69,35 @@ void UpdateManager::getWidgetPath(Widget* widget, std::vector<Widget*>& out) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget* UpdateManager::findFocusWidget(Widget* root, EventHandler& events) {
|
void UpdateManager::handleFocusChanges(Widget* root, EventHandler& events) {
|
||||||
|
auto prevFocus = mInFocusWidget;
|
||||||
|
|
||||||
events.setCursorOrigin({ 0, 0 });
|
events.setCursorOrigin({ 0, 0 });
|
||||||
|
|
||||||
mInFocusWidget = nullptr;
|
mInFocusWidget = nullptr;
|
||||||
findMouseFocusWidget(root, &mInFocusWidget, events.getPointer());
|
|
||||||
|
|
||||||
if (mFocusLockStack.size()) {
|
findFocusWidget(root, &mInFocusWidget, events.getPointer());
|
||||||
|
|
||||||
|
if (mFocusLockWidget) {
|
||||||
bool hasLockedWidget = false;
|
bool hasLockedWidget = false;
|
||||||
for (auto iter = mInFocusWidget; iter; iter = iter->mParent) {
|
for (auto iter = mInFocusWidget; iter; iter = iter->mParent) {
|
||||||
if (iter == mFocusLockStack.last()) {
|
if (iter == mFocusLockWidget) {
|
||||||
hasLockedWidget = true;
|
hasLockedWidget = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hasLockedWidget) {
|
if (!hasLockedWidget) {
|
||||||
mInFocusWidget = mFocusLockStack.last();
|
mInFocusWidget = mFocusLockWidget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mInFocusWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateManager::handleFocusChanges(Widget* active, Widget* prevActive) {
|
|
||||||
// if (mInFocusWidget == prevFocus) return;
|
// if (mInFocusWidget == prevFocus) return;
|
||||||
if (active) scheduleUpdate(active, "focus entered");
|
if (mInFocusWidget) scheduleUpdate(mInFocusWidget, "focus entered");
|
||||||
|
|
||||||
if (!active && !prevActive) return;
|
if (!mInFocusWidget && !prevFocus) return;
|
||||||
|
|
||||||
std::vector<Widget*> path2;
|
std::vector<Widget*> path2;
|
||||||
getWidgetPath(active, path2);
|
getWidgetPath(mInFocusWidget, path2);
|
||||||
size_t propLen2 = path2.size();
|
size_t propLen2 = path2.size();
|
||||||
for (auto i = 0; i < path2.size(); i++) {
|
for (auto i = 0; i < path2.size(); i++) {
|
||||||
if (!path2[i]->propagateEventsToChildren()) {
|
if (!path2[i]->propagateEventsToChildren()) {
|
||||||
|
|
@ -108,7 +107,7 @@ void UpdateManager::handleFocusChanges(Widget* active, Widget* prevActive) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Widget*> path1;
|
std::vector<Widget*> path1;
|
||||||
getWidgetPath(prevActive, path1);
|
getWidgetPath(prevFocus, path1);
|
||||||
size_t propLen1 = path1.size();
|
size_t propLen1 = path1.size();
|
||||||
for (auto i = 0; i < path1.size(); i++) {
|
for (auto i = 0; i < path1.size(); i++) {
|
||||||
if (!path1[i]->propagateEventsToChildren()) {
|
if (!path1[i]->propagateEventsToChildren()) {
|
||||||
|
|
@ -136,7 +135,7 @@ void UpdateManager::handleFocusChanges(Widget* active, Widget* prevActive) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateManager::findMouseFocusWidget(Widget* iter, Widget** focus, const Vec2F& pointer) {
|
void UpdateManager::findFocusWidget(Widget* iter, Widget** focus, const Vec2F& pointer) {
|
||||||
if (!iter->mArea.getTargetRect().isInside(pointer) || !iter->mFlags.get(Widget::ENABLED)) return;
|
if (!iter->mArea.getTargetRect().isInside(pointer) || !iter->mFlags.get(Widget::ENABLED)) return;
|
||||||
|
|
||||||
if (iter->processesEvents()) {
|
if (iter->processesEvents()) {
|
||||||
|
|
@ -144,7 +143,7 @@ void UpdateManager::findMouseFocusWidget(Widget* iter, Widget** focus, const Vec
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto child = iter->mDepthOrder.lastNode(); child; child = child->prev) {
|
for (auto child = iter->mDepthOrder.lastNode(); child; child = child->prev) {
|
||||||
findMouseFocusWidget(child->data, focus, pointer - iter->mArea.getTargetRect().pos);
|
findFocusWidget(child->data, focus, pointer - iter->mArea.getTargetRect().pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,10 +159,8 @@ void UpdateManager::processActiveTree(Widget* iter, EventHandler& events, Vec2F
|
||||||
procWidget(iter, events, false);
|
procWidget(iter, events, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto child = iter->mDepthOrder.firstNode(); child;) {
|
for (auto child : iter->mDepthOrder) {
|
||||||
auto next = child->next; // any child may be removed at runtime
|
processActiveTree(child.data(), events, current);
|
||||||
processActiveTree(child->data, events, current);
|
|
||||||
child = next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,24 +211,10 @@ void UpdateManager::procWidget(Widget* widget, EventHandler& events, bool withEv
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateManager::lockFocus(tp::Widget* widget) {
|
void UpdateManager::lockFocus(tp::Widget* widget) {
|
||||||
DEBUG_ASSERT(mFocusLockStack.find(widget) == nullptr)
|
mFocusLockWidget = widget;
|
||||||
// TODO : check that widget is a child of top of the stack
|
|
||||||
mFocusLockStack.pushBack(widget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateManager::freeFocus(tp::Widget* widget) {
|
void UpdateManager::freeFocus(tp::Widget* widget) {
|
||||||
DEBUG_ASSERT(mFocusLockStack.last() == widget)
|
// DEBUG_ASSERT(mFocusLockWidget == widget)
|
||||||
mFocusLockStack.popBack();
|
mFocusLockWidget = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UpdateManager::canRemoveWidget(Widget* widget) const {
|
|
||||||
if (auto node = mFocusLockStack.find(widget)) {
|
|
||||||
if (node->next) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateManager::removeWidget(Widget* widget) {
|
|
||||||
freeFocus(widget);
|
|
||||||
}
|
|
||||||
|
|
@ -86,7 +86,7 @@ void DockWidget::process(const EventHandler& events) {
|
||||||
}
|
}
|
||||||
} else if (events.isReleased(InputID::MOUSE1)) {
|
} else if (events.isReleased(InputID::MOUSE1)) {
|
||||||
layout()->endResize();
|
layout()->endResize();
|
||||||
if (layout()->isResizing()) freeFocus();
|
freeFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layout()->isResizing()) {
|
if (layout()->isResizing()) {
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,9 @@ using namespace tp;
|
||||||
void ScrollableBarWidget::process(const EventHandler& events) {
|
void ScrollableBarWidget::process(const EventHandler& events) {
|
||||||
// all content is visible no need to process anything
|
// all content is visible no need to process anything
|
||||||
if (mSizeFactor >= 1) {
|
if (mSizeFactor >= 1) {
|
||||||
if (mScrolling) freeFocus();
|
|
||||||
|
|
||||||
mScrolling = false;
|
mScrolling = false;
|
||||||
mPosFactor = mSizeFactor / 2.f;
|
mPosFactor = mSizeFactor / 2.f;
|
||||||
|
freeFocus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,6 @@ namespace tp {
|
||||||
|
|
||||||
using DFSAction = std::function<void(Widget*)>;
|
using DFSAction = std::function<void(Widget*)>;
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
enum Flags : int1 {
|
enum Flags : int1 {
|
||||||
ENABLED = 0,
|
ENABLED = 0,
|
||||||
NEEDS_UPDATE,
|
NEEDS_UPDATE,
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ namespace tp {
|
||||||
bool mDebug = false;
|
bool mDebug = false;
|
||||||
bool mDebugStopProcessing = false;
|
bool mDebugStopProcessing = false;
|
||||||
bool mDebugRedrawAlways = false;
|
bool mDebugRedrawAlways = false;
|
||||||
bool mDetailed = true;
|
bool mDetailed = false;
|
||||||
|
|
||||||
std::set<Widget*> mProcBreakpoints;
|
std::set<Widget*> mProcBreakpoints;
|
||||||
std::set<Widget*> mLayBreakpoints;
|
std::set<Widget*> mLayBreakpoints;
|
||||||
|
|
|
||||||
|
|
@ -25,26 +25,20 @@ namespace tp {
|
||||||
void clean();
|
void clean();
|
||||||
|
|
||||||
void updateTreeToProcess(Widget* root);
|
void updateTreeToProcess(Widget* root);
|
||||||
void handleFocusChanges(Widget* active, Widget* prevActive);
|
void handleFocusChanges(Widget* root, EventHandler& events);
|
||||||
Widget* findFocusWidget(Widget* root, EventHandler& events);
|
|
||||||
|
|
||||||
void findMouseFocusWidget(Widget* iter, Widget** focus, const Vec2F& pointer);
|
void findFocusWidget(Widget* iter, Widget** focus, const Vec2F& pointer);
|
||||||
static void getWidgetPath(Widget* widget, std::vector<Widget*>& out);
|
static void getWidgetPath(Widget* widget, std::vector<Widget*>& out);
|
||||||
void processActiveTree(Widget* iter, EventHandler& events, Vec2F pos);
|
void processActiveTree(Widget* iter, EventHandler& events, Vec2F pos);
|
||||||
void processFocusItems(EventHandler& events);
|
void processFocusItems(EventHandler& events);
|
||||||
|
|
||||||
Widget* getFocusWidget() { return mInFocusWidget; }
|
|
||||||
|
|
||||||
bool canRemoveWidget(Widget* widget) const;
|
|
||||||
void removeWidget(Widget* widget);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void procWidget(Widget* widget, EventHandler& events, bool withEvents = false);
|
static void procWidget(Widget* widget, EventHandler& events, bool withEvents = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<Widget*, bool> mTriggeredWidgets;
|
std::map<Widget*, bool> mTriggeredWidgets;
|
||||||
Widget* mInFocusWidget = nullptr;
|
Widget* mInFocusWidget = nullptr;
|
||||||
List<Widget*> mFocusLockStack;
|
Widget* mFocusLockWidget = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int mDebugWidgetsToProcess = 0;
|
int mDebugWidgetsToProcess = 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue