Added automatic tessellation near camera frustum culling
This allows the camera nearer the ground and fixes holes in lower quality renders
This commit is contained in:
parent
652c66a2fa
commit
3fc8b1c98f
10 changed files with 185 additions and 32 deletions
1
TODO
1
TODO
|
@ -5,7 +5,6 @@ Technlology Preview 2 :
|
||||||
- Add clouds to OpenGL with 3d textures.
|
- Add clouds to OpenGL with 3d textures.
|
||||||
- Refactor medium traversal to unify clouds, atmosphere and god rays.
|
- Refactor medium traversal to unify clouds, atmosphere and god rays.
|
||||||
- Fix potential holes in land rendering (OpenGL and software).
|
- Fix potential holes in land rendering (OpenGL and software).
|
||||||
- Fix polygon culling near the camera in low-res renders (automatic tessellation ?).
|
|
||||||
- Fix sun size not being consistent between opengl and software
|
- Fix sun size not being consistent between opengl and software
|
||||||
|
|
||||||
Technology Preview 3 :
|
Technology Preview 3 :
|
||||||
|
|
|
@ -76,3 +76,8 @@ VectorSpherical Vector3::toSpherical() const
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3 Vector3::midPointTo(const Vector3 &other) const
|
||||||
|
{
|
||||||
|
return Vector3((other.x + x) * 0.5, (other.y + y) * 0.5, (other.z + z) * 0.5);
|
||||||
|
}
|
||||||
|
|
|
@ -61,6 +61,11 @@ public:
|
||||||
double dotProduct(const Vector3 &other) const;
|
double dotProduct(const Vector3 &other) const;
|
||||||
Vector3 crossProduct(const Vector3 &other) const;
|
Vector3 crossProduct(const Vector3 &other) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mid-point of the segment between *this* point and *other*.
|
||||||
|
*/
|
||||||
|
Vector3 midPointTo(const Vector3 &other) const;
|
||||||
|
|
||||||
VectorSpherical toSpherical() const;
|
VectorSpherical toSpherical() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -191,8 +191,8 @@ void Scenery::getWater(WaterDefinition* water)
|
||||||
void Scenery::keepCameraAboveGround(CameraDefinition* camera)
|
void Scenery::keepCameraAboveGround(CameraDefinition* camera)
|
||||||
{
|
{
|
||||||
Vector3 camera_location = camera->getLocation();
|
Vector3 camera_location = camera->getLocation();
|
||||||
double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, true, true) + 2.0;
|
double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, true, true) + 1.0;
|
||||||
double water_height = 1.5;
|
double water_height = 0.5;
|
||||||
if (camera_location.y < water_height || camera_location.y < terrain_height)
|
if (camera_location.y < water_height || camera_location.y < terrain_height)
|
||||||
{
|
{
|
||||||
double diff = ((water_height > terrain_height) ? water_height : terrain_height) - camera_location.y;
|
double diff = ((water_height > terrain_height) ? water_height : terrain_height) - camera_location.y;
|
||||||
|
|
|
@ -21,14 +21,18 @@
|
||||||
|
|
||||||
void startRender(SoftwareCanvasRenderer *renderer, const char *outputpath);
|
void startRender(SoftwareCanvasRenderer *renderer, const char *outputpath);
|
||||||
|
|
||||||
static void startTestRender(SoftwareCanvasRenderer *renderer, const std::string &name, int iteration)
|
static void startTestRender(SoftwareCanvasRenderer *renderer, const std::string &name, int iteration=-1)
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
|
|
||||||
stream << "pic_test_" << name << "_";
|
stream << "pic_test_" << name;
|
||||||
stream.width(4);
|
if (iteration >= 0)
|
||||||
stream.fill('0');
|
{
|
||||||
stream << iteration;
|
stream << "_";
|
||||||
|
stream.width(4);
|
||||||
|
stream.fill('0');
|
||||||
|
stream << iteration;
|
||||||
|
}
|
||||||
stream << ".png";
|
stream << ".png";
|
||||||
|
|
||||||
startRender(renderer, stream.str().data());
|
startRender(renderer, stream.str().data());
|
||||||
|
@ -192,11 +196,25 @@ static void testGodRays()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void testNearFrustum()
|
||||||
|
{
|
||||||
|
Scenery scenery;
|
||||||
|
scenery.autoPreset(3);
|
||||||
|
scenery.getCamera()->setLocation(Vector3(0.0, 0.0, 0.0));
|
||||||
|
scenery.getCamera()->setTarget(Vector3(1.0, 0.0, 1.0));
|
||||||
|
scenery.keepCameraAboveGround(scenery.getCamera());
|
||||||
|
|
||||||
|
SoftwareCanvasRenderer renderer(&scenery);
|
||||||
|
renderer.setSize(400, 300);
|
||||||
|
renderer.setQuality(0.1);
|
||||||
|
startTestRender(&renderer, "near_frustum");
|
||||||
|
}
|
||||||
|
|
||||||
void runTestSuite()
|
void runTestSuite()
|
||||||
{
|
{
|
||||||
testGroundShadowQuality();
|
testGroundShadowQuality();
|
||||||
testRasterizationQuality();
|
testRasterizationQuality();
|
||||||
testCloudQuality();
|
testCloudQuality();
|
||||||
testGodRays();
|
testGodRays();
|
||||||
|
testNearFrustum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ Rasterizer::Rasterizer(SoftwareRenderer* renderer, RenderProgress *progress, int
|
||||||
this->color = new Color(color);
|
this->color = new Color(color);
|
||||||
|
|
||||||
interrupted = false;
|
interrupted = false;
|
||||||
|
triangle_count = 0;
|
||||||
|
auto_cut_limit = 0.01;
|
||||||
|
|
||||||
setQuality(0.5);
|
setQuality(0.5);
|
||||||
}
|
}
|
||||||
|
@ -56,7 +58,17 @@ void Rasterizer::setQuality(double)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rasterizer::pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pixel1, const Vector3 &pixel2, const Vector3 &pixel3, const Vector3 &location1, const Vector3 &location2, const Vector3 &location3)
|
void Rasterizer::setAutoCutLimit(double limit)
|
||||||
|
{
|
||||||
|
this->auto_cut_limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rasterizer::resetTriangleCount()
|
||||||
|
{
|
||||||
|
triangle_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rasterizer::pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pixel1, const Vector3 &pixel2, const Vector3 &pixel3, const Vector3 &location1, const Vector3 &location2, const Vector3 &location3)
|
||||||
{
|
{
|
||||||
ScanPoint point1, point2, point3;
|
ScanPoint point1, point2, point3;
|
||||||
double limit_width = (double)(canvas->getWidth() - 1);
|
double limit_width = (double)(canvas->getWidth() - 1);
|
||||||
|
@ -67,13 +79,20 @@ void Rasterizer::pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pix
|
||||||
Vector3 dpixel2 = pixel2.sub(canvas_offset);
|
Vector3 dpixel2 = pixel2.sub(canvas_offset);
|
||||||
Vector3 dpixel3 = pixel3.sub(canvas_offset);
|
Vector3 dpixel3 = pixel3.sub(canvas_offset);
|
||||||
|
|
||||||
/* Filter if outside screen */
|
double limit_near = renderer->render_camera->getPerspective().znear;
|
||||||
if (dpixel1.z < 1.0 || dpixel2.z < 1.0 || dpixel3.z < 1.0 || (dpixel1.x < 0.0 && dpixel2.x < 0.0 && dpixel3.x < 0.0) || (dpixel1.y < 0.0 && dpixel2.y < 0.0 && dpixel3.y < 0.0) || (dpixel1.x > limit_width && dpixel2.x > limit_width && dpixel3.x > limit_width) || (dpixel1.y > limit_height && dpixel2.y > limit_height && dpixel3.y > limit_height))
|
if ((dpixel1.z < limit_near && dpixel2.z < limit_near && dpixel3.z < limit_near) || (dpixel1.x < 0.0 && dpixel2.x < 0.0 && dpixel3.x < 0.0) || (dpixel1.y < 0.0 && dpixel2.y < 0.0 && dpixel3.y < 0.0) || (dpixel1.x > limit_width && dpixel2.x > limit_width && dpixel3.x > limit_width) || (dpixel1.y > limit_height && dpixel2.y > limit_height && dpixel3.y > limit_height))
|
||||||
{
|
{
|
||||||
return;
|
// Fully outside screen
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (dpixel1.z < limit_near || dpixel2.z < limit_near || dpixel3.z < limit_near)
|
||||||
|
{
|
||||||
|
// Intersects the near frustum plane, needs cutting
|
||||||
|
// ... except if the triangle is already small
|
||||||
|
return location1.sub(location2).getNorm() > auto_cut_limit && location2.sub(location3).getNorm() > auto_cut_limit && location3.sub(location1).getNorm() > auto_cut_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare vertices */
|
// Prepare vertices
|
||||||
point1.pixel.x = dpixel1.x;
|
point1.pixel.x = dpixel1.x;
|
||||||
point1.pixel.y = dpixel1.y;
|
point1.pixel.y = dpixel1.y;
|
||||||
point1.pixel.z = dpixel1.z;
|
point1.pixel.z = dpixel1.z;
|
||||||
|
@ -98,7 +117,7 @@ void Rasterizer::pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pix
|
||||||
point3.location.z = location3.z;
|
point3.location.z = location3.z;
|
||||||
point3.client = client_id;
|
point3.client = client_id;
|
||||||
|
|
||||||
/* Prepare scanlines */
|
// Prepare scanlines
|
||||||
// TODO Don't create scanlines for each triangles (one by thread is more appropriate)
|
// TODO Don't create scanlines for each triangles (one by thread is more appropriate)
|
||||||
RenderScanlines scanlines;
|
RenderScanlines scanlines;
|
||||||
int width = canvas->getWidth();
|
int width = canvas->getWidth();
|
||||||
|
@ -107,17 +126,20 @@ void Rasterizer::pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pix
|
||||||
scanlines.up = new ScanPoint[width];
|
scanlines.up = new ScanPoint[width];
|
||||||
scanlines.down = new ScanPoint[width];
|
scanlines.down = new ScanPoint[width];
|
||||||
|
|
||||||
/* Render edges in scanlines */
|
// Render edges in scanlines
|
||||||
pushScanLineEdge(canvas, &scanlines, &point1, &point2);
|
pushScanLineEdge(canvas, &scanlines, &point1, &point2);
|
||||||
pushScanLineEdge(canvas, &scanlines, &point2, &point3);
|
pushScanLineEdge(canvas, &scanlines, &point2, &point3);
|
||||||
pushScanLineEdge(canvas, &scanlines, &point3, &point1);
|
pushScanLineEdge(canvas, &scanlines, &point3, &point1);
|
||||||
|
|
||||||
/* Commit scanlines to area */
|
// Commit scanlines to area
|
||||||
renderScanLines(canvas, &scanlines);
|
renderScanLines(canvas, &scanlines);
|
||||||
|
|
||||||
/* Free scalines */
|
// Free scalines
|
||||||
delete[] scanlines.up;
|
delete[] scanlines.up;
|
||||||
delete[] scanlines.down;
|
delete[] scanlines.down;
|
||||||
|
|
||||||
|
triangle_count++;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rasterizer::pushTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3)
|
void Rasterizer::pushTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3)
|
||||||
|
@ -128,13 +150,17 @@ void Rasterizer::pushTriangle(CanvasPortion *canvas, const Vector3 &v1, const Ve
|
||||||
p2 = getRenderer()->projectPoint(v2);
|
p2 = getRenderer()->projectPoint(v2);
|
||||||
p3 = getRenderer()->projectPoint(v3);
|
p3 = getRenderer()->projectPoint(v3);
|
||||||
|
|
||||||
pushProjectedTriangle(canvas, p1, p2, p3, v1, v2, v3);
|
if (pushProjectedTriangle(canvas, p1, p2, p3, v1, v2, v3))
|
||||||
}
|
{
|
||||||
|
// Cutting needed
|
||||||
void Rasterizer::pushQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4)
|
Vector3 vm1 = v1.midPointTo(v2);
|
||||||
{
|
Vector3 vm2 = v2.midPointTo(v3);
|
||||||
pushTriangle(canvas, v2, v3, v1);
|
Vector3 vm3 = v3.midPointTo(v1);
|
||||||
pushTriangle(canvas, v4, v1, v3);
|
pushTriangle(canvas, v1, vm1, vm3);
|
||||||
|
pushTriangle(canvas, v2, vm1, vm2);
|
||||||
|
pushTriangle(canvas, v3, vm3, vm2);
|
||||||
|
pushTriangle(canvas, vm1, vm2, vm3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rasterizer::pushDisplacedTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3)
|
void Rasterizer::pushDisplacedTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3)
|
||||||
|
@ -145,7 +171,26 @@ void Rasterizer::pushDisplacedTriangle(CanvasPortion *canvas, const Vector3 &v1,
|
||||||
p2 = getRenderer()->projectPoint(v2);
|
p2 = getRenderer()->projectPoint(v2);
|
||||||
p3 = getRenderer()->projectPoint(v3);
|
p3 = getRenderer()->projectPoint(v3);
|
||||||
|
|
||||||
pushProjectedTriangle(canvas, p1, p2, p3, ov1, ov2, ov3);
|
if (pushProjectedTriangle(canvas, p1, p2, p3, ov1, ov2, ov3))
|
||||||
|
{
|
||||||
|
// Cutting needed
|
||||||
|
Vector3 vm1 = v1.midPointTo(v2);
|
||||||
|
Vector3 vm2 = v2.midPointTo(v3);
|
||||||
|
Vector3 vm3 = v3.midPointTo(v1);
|
||||||
|
Vector3 ovm1 = ov1.midPointTo(ov2);
|
||||||
|
Vector3 ovm2 = ov2.midPointTo(ov3);
|
||||||
|
Vector3 ovm3 = ov3.midPointTo(ov1);
|
||||||
|
pushDisplacedTriangle(canvas, v1, vm1, vm3, ov1, ovm1, ovm3);
|
||||||
|
pushDisplacedTriangle(canvas, v2, vm1, vm2, ov2, ovm1, ovm2);
|
||||||
|
pushDisplacedTriangle(canvas, v3, vm3, vm2, ov3, ovm3, ovm2);
|
||||||
|
pushDisplacedTriangle(canvas, vm1, vm2, vm3, ovm1, ovm2, ovm3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rasterizer::pushQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4)
|
||||||
|
{
|
||||||
|
pushTriangle(canvas, v2, v3, v1);
|
||||||
|
pushTriangle(canvas, v4, v1, v3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rasterizer::pushDisplacedQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3, const Vector3 &ov4)
|
void Rasterizer::pushDisplacedQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3, const Vector3 &ov4)
|
||||||
|
|
|
@ -19,6 +19,7 @@ public:
|
||||||
virtual ~Rasterizer();
|
virtual ~Rasterizer();
|
||||||
|
|
||||||
inline SoftwareRenderer *getRenderer() const {return renderer;}
|
inline SoftwareRenderer *getRenderer() const {return renderer;}
|
||||||
|
inline int getTriangleCount() const {return triangle_count;}
|
||||||
|
|
||||||
virtual Color shadeFragment(const CanvasFragment &fragment) const = 0;
|
virtual Color shadeFragment(const CanvasFragment &fragment) const = 0;
|
||||||
virtual void interrupt();
|
virtual void interrupt();
|
||||||
|
@ -28,6 +29,16 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void setQuality(double factor);
|
virtual void setQuality(double factor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the edge length under which to stop auto-cutting triangles near the camera.
|
||||||
|
*/
|
||||||
|
void setAutoCutLimit(double limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the internal triangle counter to 0.
|
||||||
|
*/
|
||||||
|
void resetTriangleCount();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract method to prepare for the rasterization process, and return the estimated progress count.
|
* Abstract method to prepare for the rasterization process, and return the estimated progress count.
|
||||||
*/
|
*/
|
||||||
|
@ -35,16 +46,17 @@ public:
|
||||||
/**
|
/**
|
||||||
* Abstract method to effectively do the rasterization on a canvas.
|
* Abstract method to effectively do the rasterization on a canvas.
|
||||||
*/
|
*/
|
||||||
virtual void rasterizeToCanvas(CanvasPortion* canvas) = 0;
|
virtual void rasterizeToCanvas(CanvasPortion *canvas) = 0;
|
||||||
|
|
||||||
protected:
|
|
||||||
void pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pixel1, const Vector3 &pixel2, const Vector3 &pixel3, const Vector3 &location1, const Vector3 &location2, const Vector3 &location3);
|
|
||||||
|
|
||||||
void pushTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3);
|
void pushTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3);
|
||||||
void pushQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4);
|
|
||||||
void pushDisplacedTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3);
|
void pushDisplacedTriangle(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3);
|
||||||
|
|
||||||
|
void pushQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4);
|
||||||
void pushDisplacedQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3, const Vector3 &ov4);
|
void pushDisplacedQuad(CanvasPortion *canvas, const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3, const Vector3 &ov4);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pixel1, const Vector3 &pixel2, const Vector3 &pixel3, const Vector3 &location1, const Vector3 &location2, const Vector3 &location3);
|
||||||
|
|
||||||
Color* color;
|
Color* color;
|
||||||
SoftwareRenderer *renderer;
|
SoftwareRenderer *renderer;
|
||||||
RenderProgress *progress;
|
RenderProgress *progress;
|
||||||
|
@ -57,6 +69,9 @@ private:
|
||||||
void pushScanPoint(CanvasPortion *canvas, RenderScanlines *scanlines, ScanPoint *point);
|
void pushScanPoint(CanvasPortion *canvas, RenderScanlines *scanlines, ScanPoint *point);
|
||||||
void pushScanLineEdge(CanvasPortion *canvas, RenderScanlines *scanlines, ScanPoint *point1, ScanPoint *point2);
|
void pushScanLineEdge(CanvasPortion *canvas, RenderScanlines *scanlines, ScanPoint *point1, ScanPoint *point2);
|
||||||
void renderScanLines(CanvasPortion *canvas, RenderScanlines *scanlines);
|
void renderScanLines(CanvasPortion *canvas, RenderScanlines *scanlines);
|
||||||
|
|
||||||
|
int triangle_count;
|
||||||
|
double auto_cut_limit;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
54
src/tests/Rasterizer_Test.cpp
Normal file
54
src/tests/Rasterizer_Test.cpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#include "BaseTestCase.h"
|
||||||
|
#include "Rasterizer.h"
|
||||||
|
|
||||||
|
#include "SoftwareRenderer.h"
|
||||||
|
#include "Scenery.h"
|
||||||
|
#include "Vector3.h"
|
||||||
|
#include "CameraDefinition.h"
|
||||||
|
#include "Color.h"
|
||||||
|
#include "CanvasPortion.h"
|
||||||
|
|
||||||
|
class FakeRasterizer: public Rasterizer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FakeRasterizer(SoftwareRenderer *renderer): Rasterizer(renderer, NULL, 0, COLOR_WHITE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual Color shadeFragment(const CanvasFragment &) const override
|
||||||
|
{
|
||||||
|
return COLOR_RED;
|
||||||
|
}
|
||||||
|
virtual int prepareRasterization() override
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
virtual void rasterizeToCanvas(CanvasPortion *) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(Rasterizer, autoSplitNearFrustum)
|
||||||
|
{
|
||||||
|
Scenery scenery;
|
||||||
|
scenery.getCamera()->setLocation(Vector3(0.0, 5.0, 0.0));
|
||||||
|
scenery.getCamera()->setTarget(Vector3(0.0, 5.0, 1.0));
|
||||||
|
SoftwareRenderer renderer(&scenery);
|
||||||
|
|
||||||
|
FakeRasterizer rast(&renderer);
|
||||||
|
CanvasPortion portion;
|
||||||
|
portion.setSize(300, 300);
|
||||||
|
portion.preparePixels();
|
||||||
|
|
||||||
|
rast.pushTriangle(&portion, Vector3(0.0, 0.0, 8.0), Vector3(0.0, 0.0, 10.0), Vector3(2.0, 0.0, 8.0));
|
||||||
|
EXPECT_EQ(1, rast.getTriangleCount());
|
||||||
|
|
||||||
|
rast.resetTriangleCount();
|
||||||
|
rast.setAutoCutLimit(15.0);
|
||||||
|
rast.pushTriangle(&portion, Vector3(0.0, 0.0, 0.0), Vector3(-10.0, 0.0, 10.0), Vector3(10.0, 0.0, 10.0));
|
||||||
|
EXPECT_EQ(0, rast.getTriangleCount());
|
||||||
|
|
||||||
|
rast.resetTriangleCount();
|
||||||
|
rast.setAutoCutLimit(9.0);
|
||||||
|
rast.pushTriangle(&portion, Vector3(0.0, 0.0, 0.0), Vector3(-10.0, 0.0, 10.0), Vector3(10.0, 0.0, 10.0));
|
||||||
|
EXPECT_EQ(3, rast.getTriangleCount());
|
||||||
|
}
|
10
src/tests/Vector3_Test.cpp
Normal file
10
src/tests/Vector3_Test.cpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include "BaseTestCase.h"
|
||||||
|
#include "Vector3.h"
|
||||||
|
|
||||||
|
TEST(Vector3, midPointTo)
|
||||||
|
{
|
||||||
|
Vector3 v1(1.0, 2.0, 8.0);
|
||||||
|
Vector3 v2(4.0, 2.5, -1.0);
|
||||||
|
Vector3 vm = v1.midPointTo(v2);
|
||||||
|
EXPECT_VECTOR3_COORDS(vm, 2.5, 2.25, 3.5);
|
||||||
|
}
|
|
@ -31,7 +31,9 @@ SOURCES += main.cpp \
|
||||||
IntNode_Test.cpp \
|
IntNode_Test.cpp \
|
||||||
LightingManager_Test.cpp \
|
LightingManager_Test.cpp \
|
||||||
GodRaysSampler_Test.cpp \
|
GodRaysSampler_Test.cpp \
|
||||||
Interpolation_Test.cpp
|
Interpolation_Test.cpp \
|
||||||
|
Rasterizer_Test.cpp \
|
||||||
|
Vector3_Test.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
BaseTestCase.h
|
BaseTestCase.h
|
||||||
|
|
Loading…
Reference in a new issue