diff --git a/src/rendering/camera.c b/src/rendering/camera.c index f00b475..2d085a8 100644 --- a/src/rendering/camera.c +++ b/src/rendering/camera.c @@ -5,6 +5,7 @@ #include "render.h" #include "scenery.h" #include "tools.h" +#include "tools/boundingbox.h" struct CameraDefinition { @@ -361,58 +362,49 @@ Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point) renderPushQuad(&v1, &v2, &v3, &v4); }*/ -static inline void _updateBox(Vector3* point, double* xmin, double* xmax, double* ymin, double* ymax, double* zmax) -{ - *xmin = (*xmin < point->x) ? *xmin : point->x; - *ymin = (*ymin < point->y) ? *ymin : point->y; - - *xmax = (*xmax > point->x) ? *xmax : point->x; - *ymax = (*ymax > point->y) ? *ymax : point->y; - *zmax = (*zmax > point->z) ? *zmax : point->z; -} - int cameraIsBoxInView(CameraDefinition* camera, Vector3 center, double xsize, double ysize, double zsize) { - Vector3 projected; - double xmin, xmax, ymin, ymax, zmax; + BoundingBox box; - center.x -= xsize / 2.0; - center.y -= ysize / 2.0; - center.z -= zsize / 2.0; - projected = cameraProject(camera, center); - xmin = xmax = projected.x; - ymin = ymax = projected.y; - zmax = projected.z; + boundingBoxReset(&box); - center.x += xsize; - projected = cameraProject(camera, center); - _updateBox(&projected, &xmin, &xmax, &ymin, &ymax, &zmax); + boundingBoxPushPoint(&box, v3Add(center, v3(-xsize, -ysize, -zsize))); + boundingBoxPushPoint(&box, v3Add(center, v3(xsize, ysize, zsize))); - center.z += zsize; - projected = cameraProject(camera, center); - _updateBox(&projected, &xmin, &xmax, &ymin, &ymax, &zmax); + return cameraIsUnprojectedBoxInView(camera, &box); +} - center.x -= xsize; - projected = cameraProject(camera, center); - _updateBox(&projected, &xmin, &xmax, &ymin, &ymax, &zmax); +int cameraIsUnprojectedBoxInView(CameraDefinition* camera, BoundingBox* box) +{ + BoundingBox projected; - center.y += ysize; - projected = cameraProject(camera, center); - _updateBox(&projected, &xmin, &xmax, &ymin, &ymax, &zmax); + boundingBoxReset(&projected); - center.x += xsize; - projected = cameraProject(camera, center); - _updateBox(&projected, &xmin, &xmax, &ymin, &ymax, &zmax); + boundingBoxPushPoint(&projected, cameraProject(camera, v3(box->xmin, box->ymin, box->zmin))); + boundingBoxPushPoint(&projected, cameraProject(camera, v3(box->xmax, box->ymin, box->zmin))); + boundingBoxPushPoint(&projected, cameraProject(camera, v3(box->xmin, box->ymax, box->zmin))); + boundingBoxPushPoint(&projected, cameraProject(camera, v3(box->xmax, box->ymax, box->zmin))); + boundingBoxPushPoint(&projected, cameraProject(camera, v3(box->xmin, box->ymin, box->zmax))); + boundingBoxPushPoint(&projected, cameraProject(camera, v3(box->xmax, box->ymin, box->zmax))); + boundingBoxPushPoint(&projected, cameraProject(camera, v3(box->xmin, box->ymax, box->zmax))); + boundingBoxPushPoint(&projected, cameraProject(camera, v3(box->xmax, box->ymax, box->zmax))); - center.z -= zsize; - projected = cameraProject(camera, center); - _updateBox(&projected, &xmin, &xmax, &ymin, &ymax, &zmax); + return cameraIsProjectedBoxInView(camera, &projected); +} - center.x -= xsize; - projected = cameraProject(camera, center); - _updateBox(&projected, &xmin, &xmax, &ymin, &ymax, &zmax); +int cameraIsProjectedBoxInView(CameraDefinition* camera, BoundingBox* box) +{ + if (box->xmin <= camera->width && box->xmax >= 0.0 && box->ymin <= camera->height && box->ymax >= 0.0 && box->zmax >= camera->perspective.znear) + { + double dx = box->xmax - box->xmin; + double dy = box->ymax - box->ymin; - return xmin <= camera->width && xmax >= 0.0 && ymin <= camera->height && ymax >= 0.0 && zmax >= camera->perspective.znear; + return (int)ceil(dx) * (int)ceil(dy); + } + else + { + return 0; + } } int cameraTransitionToAnother(CameraDefinition* current, CameraDefinition* wanted, double factor) diff --git a/src/rendering/camera.h b/src/rendering/camera.h index e5b5efc..3f77683 100644 --- a/src/rendering/camera.h +++ b/src/rendering/camera.h @@ -3,6 +3,7 @@ #include "tools/pack.h" #include "tools/euclid.h" +#include "tools/boundingbox.h" #ifdef __cplusplus extern "C" @@ -57,6 +58,8 @@ Vector3 cameraProject(CameraDefinition* camera, Vector3 point); Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point); /*void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback);*/ int cameraIsBoxInView(CameraDefinition* camera, Vector3 center, double xsize, double ysize, double zsize); +int cameraIsUnprojectedBoxInView(CameraDefinition* camera, BoundingBox* box); +int cameraIsProjectedBoxInView(CameraDefinition* camera, BoundingBox* box); int cameraTransitionToAnother(CameraDefinition* current, CameraDefinition* wanted, double factor); diff --git a/src/rendering/tools/boundingbox.c b/src/rendering/tools/boundingbox.c new file mode 100644 index 0000000..01e1d9a --- /dev/null +++ b/src/rendering/tools/boundingbox.c @@ -0,0 +1,41 @@ +#include "boundingbox.h" + +void boundingBoxReset(BoundingBox* box) +{ + box->empty = 1; + box->xmin = 10000000000.0; + box->xmax = -10000000000.0; + box->ymin = 10000000000.0; + box->ymax = -10000000000.0; + box->zmin = 10000000000.0; + box->zmax = -10000000000.0; +} + +void boundingBoxPushPoint(BoundingBox* box, Vector3 point) +{ + box->empty = 0; + if (point.x < box->xmin) + { + box->xmin = point.x; + } + if (point.x > box->xmax) + { + box->xmax = point.x; + } + if (point.y < box->ymin) + { + box->ymin = point.y; + } + if (point.y > box->ymax) + { + box->ymax = point.y; + } + if (point.z < box->zmin) + { + box->zmin = point.z; + } + if (point.z > box->zmax) + { + box->zmax = point.z; + } +} diff --git a/src/rendering/tools/boundingbox.h b/src/rendering/tools/boundingbox.h new file mode 100644 index 0000000..1aeb29a --- /dev/null +++ b/src/rendering/tools/boundingbox.h @@ -0,0 +1,28 @@ +#ifndef _RENDERING_TOOLS_BOUNDINGBOX_H_ +#define _RENDERING_TOOLS_BOUNDINGBOX_H_ + +#include "euclid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + int empty; + double xmin; + double xmax; + double ymin; + double ymax; + double zmin; + double zmax; +} BoundingBox; + +void boundingBoxReset(BoundingBox* box); +void boundingBoxPushPoint(BoundingBox* box, Vector3 point); + +#ifdef __cplusplus +} +#endif + +#endif