Made the vegetation impostors face the camera
This commit is contained in:
parent
9d7a7a0ff7
commit
d2efb599d9
17 changed files with 192 additions and 79 deletions
5
Makefile
5
Makefile
|
@ -62,6 +62,11 @@ profile_cli:build
|
||||||
LD_LIBRARY_PATH=${LIBRARY_PATH} perf record -g ${BUILDPATH}/interface/commandline/paysages-cli $(ARGS)
|
LD_LIBRARY_PATH=${LIBRARY_PATH} perf record -g ${BUILDPATH}/interface/commandline/paysages-cli $(ARGS)
|
||||||
perf report -g
|
perf report -g
|
||||||
|
|
||||||
|
gltrace:build
|
||||||
|
rm -f *.trace
|
||||||
|
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/apitrace/wrappers/glxtrace.so LD_LIBRARY_PATH=$(LIBRARY_PATH) ${BUILDPATH}/interface/modeler/quickapp/paysages-modeler $(ARGS)
|
||||||
|
qapitrace paysages-modeler.trace
|
||||||
|
|
||||||
package:build
|
package:build
|
||||||
rm -rf paysages3d-linux
|
rm -rf paysages3d-linux
|
||||||
rm -f paysages3d-linux.tar.bz2
|
rm -f paysages3d-linux.tar.bz2
|
||||||
|
|
|
@ -44,8 +44,7 @@ bool VegetationPresenceDefinition::collectInstances(std::vector<VegetationInstan
|
||||||
double angle = 3.0 * generator->get2DTotal(-x * 20.0, z * 20.0); // TODO balanced distribution
|
double angle = 3.0 * generator->get2DTotal(-x * 20.0, z * 20.0); // TODO balanced distribution
|
||||||
double xo = x + fabs(generator->get2DTotal(x * 12.0, -z * 12.0));
|
double xo = x + fabs(generator->get2DTotal(x * 12.0, -z * 12.0));
|
||||||
double zo = z + fabs(generator->get2DTotal(-x * 27.0, -z * 27.0));
|
double zo = z + fabs(generator->get2DTotal(-x * 27.0, -z * 27.0));
|
||||||
if (xo >= xmin and xo < xmax and zo >= zmin and zo < zmax)
|
if (xo >= xmin and xo < xmax and zo >= zmin and zo < zmax) {
|
||||||
{
|
|
||||||
double y = getScenery()->getTerrain()->getInterpolatedHeight(xo, zo, true, true);
|
double y = getScenery()->getTerrain()->getInterpolatedHeight(xo, zo, true, true);
|
||||||
result->push_back(VegetationInstance(model, Vector3(xo, y, zo), size, angle));
|
result->push_back(VegetationInstance(model, Vector3(xo, y, zo), size, angle));
|
||||||
added++;
|
added++;
|
||||||
|
|
|
@ -296,16 +296,21 @@ static void testVegetationModels() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void testOpenGLVegetationImpostor() {
|
static void testOpenGLVegetationImpostor() {
|
||||||
std::string filename = getFileName("opengl_vegetation_impostor");
|
for (int i = 0; i < 4; i++) {
|
||||||
std::cout << "Rendering " << filename << "..." << std::endl;
|
std::string filename = getFileName("opengl_vegetation_impostor", i);
|
||||||
|
std::cout << "Rendering " << filename << "..." << std::endl;
|
||||||
|
|
||||||
Scenery scenery;
|
Scenery scenery;
|
||||||
scenery.autoPreset(1);
|
scenery.autoPreset(i);
|
||||||
OpenGLVegetationImpostor impostor(200);
|
|
||||||
VegetationModelDefinition model(NULL);
|
OpenGLVegetationImpostor impostor(128);
|
||||||
bool interrupted = false;
|
VegetationModelDefinition model(NULL);
|
||||||
impostor.prepareTexture(model, scenery, &interrupted);
|
|
||||||
impostor.getTexture()->saveToFile(filename);
|
bool interrupted = false;
|
||||||
|
impostor.prepareTexture(model, scenery, &interrupted);
|
||||||
|
|
||||||
|
impostor.getTexture()->saveToFile(filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void runTestSuite() {
|
void runTestSuite() {
|
||||||
|
|
|
@ -41,12 +41,10 @@ void OpenGLPart::updateScenery(bool onlyCommon) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scenery *OpenGLPart::getScenery() const
|
Scenery *OpenGLPart::getScenery() const {
|
||||||
{
|
|
||||||
return renderer->getScenery();
|
return renderer->getScenery();
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLFunctions *OpenGLPart::getOpenGlFunctions() const
|
OpenGLFunctions *OpenGLPart::getOpenGlFunctions() const {
|
||||||
{
|
|
||||||
return renderer->getOpenGlFunctions();
|
return renderer->getOpenGlFunctions();
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,13 +75,13 @@ void OpenGLShaderProgram::release() {
|
||||||
void OpenGLShaderProgram::drawTriangles(float *vertices, int triangle_count) {
|
void OpenGLShaderProgram::drawTriangles(float *vertices, int triangle_count) {
|
||||||
bind();
|
bind();
|
||||||
|
|
||||||
GLuint vertex = program->attributeLocation("vertex");
|
GLuint array_vertex = program->attributeLocation("vertex");
|
||||||
program->setAttributeArray(vertex, GL_FLOAT, vertices, 3);
|
program->setAttributeArray(array_vertex, GL_FLOAT, vertices, 3);
|
||||||
program->enableAttributeArray(vertex);
|
program->enableAttributeArray(array_vertex);
|
||||||
|
|
||||||
functions->glDrawArrays(GL_TRIANGLES, 0, triangle_count * 3);
|
functions->glDrawArrays(GL_TRIANGLES, 0, triangle_count * 3);
|
||||||
|
|
||||||
program->disableAttributeArray(vertex);
|
program->disableAttributeArray(array_vertex);
|
||||||
|
|
||||||
release();
|
release();
|
||||||
}
|
}
|
||||||
|
@ -89,13 +89,51 @@ void OpenGLShaderProgram::drawTriangles(float *vertices, int triangle_count) {
|
||||||
void OpenGLShaderProgram::drawTriangleStrip(float *vertices, int vertex_count) {
|
void OpenGLShaderProgram::drawTriangleStrip(float *vertices, int vertex_count) {
|
||||||
bind();
|
bind();
|
||||||
|
|
||||||
GLuint vertex = program->attributeLocation("vertex");
|
GLuint array_vertex = program->attributeLocation("vertex");
|
||||||
program->setAttributeArray(vertex, GL_FLOAT, vertices, 3);
|
program->setAttributeArray(array_vertex, GL_FLOAT, vertices, 3);
|
||||||
program->enableAttributeArray(vertex);
|
program->enableAttributeArray(array_vertex);
|
||||||
|
|
||||||
functions->glDrawArrays(GL_TRIANGLE_STRIP, 0, vertex_count);
|
functions->glDrawArrays(GL_TRIANGLE_STRIP, 0, vertex_count);
|
||||||
|
|
||||||
program->disableAttributeArray(vertex);
|
program->disableAttributeArray(array_vertex);
|
||||||
|
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderProgram::drawTrianglesUV(float *vertices, float *uv, int triangle_count) {
|
||||||
|
bind();
|
||||||
|
|
||||||
|
GLuint array_vertex = program->attributeLocation("vertex");
|
||||||
|
program->setAttributeArray(array_vertex, GL_FLOAT, vertices, 3);
|
||||||
|
program->enableAttributeArray(array_vertex);
|
||||||
|
|
||||||
|
GLuint array_uv = program->attributeLocation("uv");
|
||||||
|
program->setAttributeArray(array_uv, GL_FLOAT, uv, 2);
|
||||||
|
program->enableAttributeArray(array_uv);
|
||||||
|
|
||||||
|
functions->glDrawArrays(GL_TRIANGLES, 0, triangle_count * 3);
|
||||||
|
|
||||||
|
program->disableAttributeArray(array_vertex);
|
||||||
|
program->disableAttributeArray(array_uv);
|
||||||
|
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderProgram::drawTriangleStripUV(float *vertices, float *uv, int vertex_count) {
|
||||||
|
bind();
|
||||||
|
|
||||||
|
GLuint array_vertex = program->attributeLocation("vertex");
|
||||||
|
program->setAttributeArray(array_vertex, GL_FLOAT, vertices, 3);
|
||||||
|
program->enableAttributeArray(array_vertex);
|
||||||
|
|
||||||
|
GLuint array_uv = program->attributeLocation("uv");
|
||||||
|
program->setAttributeArray(array_uv, GL_FLOAT, uv, 2);
|
||||||
|
program->enableAttributeArray(array_uv);
|
||||||
|
|
||||||
|
functions->glDrawArrays(GL_TRIANGLE_STRIP, 0, vertex_count);
|
||||||
|
|
||||||
|
program->disableAttributeArray(array_vertex);
|
||||||
|
program->disableAttributeArray(array_uv);
|
||||||
|
|
||||||
release();
|
release();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,9 @@ class OPENGLSHARED_EXPORT OpenGLShaderProgram {
|
||||||
void drawTriangles(float *vertices, int triangle_count);
|
void drawTriangles(float *vertices, int triangle_count);
|
||||||
void drawTriangleStrip(float *vertices, int vertex_count);
|
void drawTriangleStrip(float *vertices, int vertex_count);
|
||||||
|
|
||||||
|
void drawTrianglesUV(float *vertices, float *uv, int triangle_count);
|
||||||
|
void drawTriangleStripUV(float *vertices, float *uv, int vertex_count);
|
||||||
|
|
||||||
void bind();
|
void bind();
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
OpenGLSharedState::OpenGLSharedState() {
|
OpenGLSharedState::OpenGLSharedState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLSharedState::~OpenGLSharedState()
|
OpenGLSharedState::~OpenGLSharedState() {
|
||||||
{
|
|
||||||
for (const auto &pair : variables) {
|
for (const auto &pair : variables) {
|
||||||
delete pair.second;
|
delete pair.second;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace opengl {
|
||||||
class OPENGLSHARED_EXPORT OpenGLSharedState {
|
class OPENGLSHARED_EXPORT OpenGLSharedState {
|
||||||
public:
|
public:
|
||||||
OpenGLSharedState();
|
OpenGLSharedState();
|
||||||
~OpenGLSharedState();
|
~OpenGLSharedState();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Apply the stored variables to the bound program.
|
* \brief Apply the stored variables to the bound program.
|
||||||
|
|
|
@ -91,8 +91,7 @@ void OpenGLVariable::set(const Texture4D *texture, bool repeat, bool color) {
|
||||||
texture_color = color;
|
texture_color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLVariable::set(int value)
|
void OpenGLVariable::set(int value) {
|
||||||
{
|
|
||||||
assert(type == TYPE_NONE or type == TYPE_INTEGER);
|
assert(type == TYPE_NONE or type == TYPE_INTEGER);
|
||||||
|
|
||||||
type = TYPE_INTEGER;
|
type = TYPE_INTEGER;
|
||||||
|
|
|
@ -27,7 +27,7 @@ class paysages::opengl::VegetationUpdater : public Thread {
|
||||||
while (not interrupted) {
|
while (not interrupted) {
|
||||||
std::vector<OpenGLVegetationLayer *> layers;
|
std::vector<OpenGLVegetationLayer *> layers;
|
||||||
vegetation->acquireLayers(layers);
|
vegetation->acquireLayers(layers);
|
||||||
for (auto layer: layers) {
|
for (auto layer : layers) {
|
||||||
layer->threadedUpdate();
|
layer->threadedUpdate();
|
||||||
}
|
}
|
||||||
vegetation->releaseLayers(layers);
|
vegetation->releaseLayers(layers);
|
||||||
|
@ -50,7 +50,7 @@ OpenGLVegetation::OpenGLVegetation(OpenGLRenderer *renderer) : OpenGLPart(render
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLVegetation::~OpenGLVegetation() {
|
OpenGLVegetation::~OpenGLVegetation() {
|
||||||
for (auto layer: layers) {
|
for (auto layer : layers) {
|
||||||
delete layer;
|
delete layer;
|
||||||
}
|
}
|
||||||
layers.clear();
|
layers.clear();
|
||||||
|
@ -81,7 +81,7 @@ void OpenGLVegetation::render() {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
std::vector<OpenGLVegetationLayer *> layers;
|
std::vector<OpenGLVegetationLayer *> layers;
|
||||||
acquireLayers(layers);
|
acquireLayers(layers);
|
||||||
for (auto layer: layers) {
|
for (auto layer : layers) {
|
||||||
layer->render();
|
layer->render();
|
||||||
}
|
}
|
||||||
releaseLayers(layers);
|
releaseLayers(layers);
|
||||||
|
@ -94,16 +94,14 @@ void OpenGLVegetation::nodeChanged(const DefinitionNode *node, const DefinitionD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scenery *OpenGLVegetation::getScenery() const
|
Scenery *OpenGLVegetation::getScenery() const {
|
||||||
{
|
|
||||||
return renderer->getScenery();
|
return renderer->getScenery();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLVegetation::cameraChanged(const CameraDefinition *camera)
|
void OpenGLVegetation::cameraChanged(const CameraDefinition *camera) {
|
||||||
{
|
|
||||||
std::vector<OpenGLVegetationLayer *> layers;
|
std::vector<OpenGLVegetationLayer *> layers;
|
||||||
acquireLayers(layers);
|
acquireLayers(layers);
|
||||||
for (auto layer: layers) {
|
for (auto layer : layers) {
|
||||||
layer->setCamera(camera);
|
layer->setCamera(camera);
|
||||||
}
|
}
|
||||||
releaseLayers(layers);
|
releaseLayers(layers);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "OpenGLVegetationImpostor.h"
|
#include "OpenGLVegetationImpostor.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include "OpenGLShaderProgram.h"
|
#include "OpenGLShaderProgram.h"
|
||||||
#include "OpenGLSharedState.h"
|
#include "OpenGLSharedState.h"
|
||||||
#include "OpenGLVegetationInstance.h"
|
#include "OpenGLVegetationInstance.h"
|
||||||
|
@ -16,16 +17,30 @@
|
||||||
#include "LightingManager.h"
|
#include "LightingManager.h"
|
||||||
#include "CameraDefinition.h"
|
#include "CameraDefinition.h"
|
||||||
|
|
||||||
OpenGLVegetationImpostor::OpenGLVegetationImpostor(int partsize) {
|
// Get the rotation matrix for an impostor grid index
|
||||||
vertices = new float[4 * 3];
|
static inline Matrix4 matrixForIndex(int index) {
|
||||||
texture_size = partsize * 4;
|
if (index == 0) {
|
||||||
texture = new Texture2D(texture_size, texture_size);
|
return Matrix4::newRotateZ(M_PI_2);
|
||||||
texture_changed = true;
|
} else if (index < 6) {
|
||||||
|
return Matrix4::newRotateY(M_2PI * (double)(index - 1) * 0.2).mult(Matrix4::newRotateZ(M_PI_4));
|
||||||
|
} else {
|
||||||
|
return Matrix4::newRotateY(M_2PI * (double)(index - 6) * 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setVertex(0, 0.0f, 0.0f, 0.0f);
|
OpenGLVegetationImpostor::OpenGLVegetationImpostor(int partsize) {
|
||||||
setVertex(1, 0.0f, 0.0f, 1.0f);
|
int parts = 4;
|
||||||
setVertex(2, 0.0f, 1.0f, 0.0f);
|
|
||||||
setVertex(3, 0.0f, 1.0f, 1.0f);
|
vertices = new float[4 * parts * parts * 3];
|
||||||
|
uv = new float[4 * 2];
|
||||||
|
texture_size = partsize * parts;
|
||||||
|
texture = new Texture2D(texture_size, texture_size);
|
||||||
|
texture_changed = false;
|
||||||
|
|
||||||
|
setVertex(0, 0.0f, 0.0f);
|
||||||
|
setVertex(1, 0.0f, 1.0f);
|
||||||
|
setVertex(2, 1.0f, 0.0f);
|
||||||
|
setVertex(3, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLVegetationImpostor::~OpenGLVegetationImpostor() {
|
OpenGLVegetationImpostor::~OpenGLVegetationImpostor() {
|
||||||
|
@ -34,15 +49,17 @@ OpenGLVegetationImpostor::~OpenGLVegetationImpostor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLVegetationImpostor::render(OpenGLShaderProgram *program, const OpenGLVegetationInstance *instance,
|
void OpenGLVegetationImpostor::render(OpenGLShaderProgram *program, const OpenGLVegetationInstance *instance,
|
||||||
int index) {
|
int instance_index, const Vector3 &camera_location) {
|
||||||
if (index == 0 or texture_changed) {
|
if (instance_index == 0 or texture_changed) {
|
||||||
texture_changed = false;
|
texture_changed = false;
|
||||||
program->getState()->set("impostorTexture", texture);
|
program->getState()->set("impostorTexture", texture);
|
||||||
}
|
}
|
||||||
program->getState()->setInt("index", 15); // TODO
|
|
||||||
|
int index = getIndex(camera_location, instance->getBase());
|
||||||
|
program->getState()->setInt("index", index);
|
||||||
program->getState()->set("offset", instance->getBase());
|
program->getState()->set("offset", instance->getBase());
|
||||||
program->getState()->set("size", instance->getSize());
|
program->getState()->set("size", 2.0 * instance->getSize());
|
||||||
program->drawTriangleStrip(vertices, 4);
|
program->drawTriangleStripUV(vertices + index * 4 * 3, uv, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLVegetationImpostor::prepareTexture(const VegetationModelDefinition &model, const Scenery &environment,
|
void OpenGLVegetationImpostor::prepareTexture(const VegetationModelDefinition &model, const Scenery &environment,
|
||||||
|
@ -58,19 +75,12 @@ void OpenGLVegetationImpostor::prepareTexture(const VegetationModelDefinition &m
|
||||||
|
|
||||||
int parts = 4;
|
int parts = 4;
|
||||||
int partsize = texture_size / parts;
|
int partsize = texture_size / parts;
|
||||||
Matrix4 rotation;
|
|
||||||
for (int py = 0; py < parts; py++) {
|
for (int py = 0; py < parts; py++) {
|
||||||
for (int px = 0; px < parts; px++) {
|
for (int px = 0; px < parts; px++) {
|
||||||
int index = py * parts + px;
|
int index = py * parts + px;
|
||||||
if (index == 0) {
|
Matrix4 rotation = matrixForIndex(index);
|
||||||
rotation = Matrix4::newRotateX(-M_PI_2);
|
|
||||||
} else if (index < 6) {
|
|
||||||
rotation = Matrix4::newRotateY(M_2PI * (double)(index - 1) * 0.2).mult(Matrix4::newRotateX(-M_PI_4));
|
|
||||||
} else {
|
|
||||||
rotation = Matrix4::newRotateY(M_2PI * (double)(index - 6) * 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 cam(0.0, 0.0, 5.0);
|
Vector3 cam(5.0, 0.0, 0.0);
|
||||||
scenery.getCamera()->setLocation(rotation.multPoint(cam));
|
scenery.getCamera()->setLocation(rotation.multPoint(cam));
|
||||||
scenery.getCamera()->setTarget(VECTOR_ZERO);
|
scenery.getCamera()->setTarget(VECTOR_ZERO);
|
||||||
renderer.prepare();
|
renderer.prepare();
|
||||||
|
@ -83,10 +93,10 @@ void OpenGLVegetationImpostor::prepareTexture(const VegetationModelDefinition &m
|
||||||
for (int y = 0; y < partsize; y++) {
|
for (int y = 0; y < partsize; y++) {
|
||||||
double dy = (double)y / (double)partsize;
|
double dy = (double)y / (double)partsize;
|
||||||
|
|
||||||
Vector3 near(dx - 0.5, dy - 0.5, 5.0);
|
Vector3 near(5.0, dy - 0.5, -(dx - 0.5));
|
||||||
Vector3 far(dx - 0.5, dy - 0.5, -5.0);
|
Vector3 far(-5.0, dy - 0.5, -(dx - 0.5));
|
||||||
SpaceSegment segment(rotation.multPoint(near.scale(1.3)).add(VECTOR_UP.scale(0.5)),
|
SpaceSegment segment(rotation.multPoint(near.scale(2.0)).add(VECTOR_UP.scale(0.5)),
|
||||||
rotation.multPoint(far.scale(1.3)).add(VECTOR_UP.scale(0.5)));
|
rotation.multPoint(far.scale(2.0)).add(VECTOR_UP.scale(0.5)));
|
||||||
|
|
||||||
RayCastingResult result = vegetation->renderInstance(segment, instance, false, true);
|
RayCastingResult result = vegetation->renderInstance(segment, instance, false, true);
|
||||||
texture->setPixel(startx + x, starty + y,
|
texture->setPixel(startx + x, starty + y,
|
||||||
|
@ -99,8 +109,40 @@ void OpenGLVegetationImpostor::prepareTexture(const VegetationModelDefinition &m
|
||||||
texture_changed = true;
|
texture_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLVegetationImpostor::setVertex(int i, float x, float y, float z) {
|
int OpenGLVegetationImpostor::getIndex(const Vector3 &camera, const Vector3 &instance) const {
|
||||||
vertices[i * 3] = x;
|
int result;
|
||||||
vertices[i * 3 + 1] = y;
|
|
||||||
vertices[i * 3 + 2] = z;
|
VectorSpherical diff = camera.sub(instance).toSpherical();
|
||||||
|
if (diff.theta > 1.0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
double angle = diff.phi / M_2PI;
|
||||||
|
if (diff.theta > 0.4) {
|
||||||
|
angle = (angle >= 0.9) ? 0.0 : (angle + 0.1);
|
||||||
|
return 1 + (int)(5.0 * angle);
|
||||||
|
} else {
|
||||||
|
angle = (angle >= 0.95) ? 0.0 : (angle + 0.05);
|
||||||
|
return 6 + (int)(10.0 * angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(result >= 0 and result <= 16);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLVegetationImpostor::setVertex(int i, float u, float v) {
|
||||||
|
int parts = 4;
|
||||||
|
for (int py = 0; py < parts; py++) {
|
||||||
|
for (int px = 0; px < parts; px++) {
|
||||||
|
int index = py * parts + px;
|
||||||
|
Matrix4 rotation = matrixForIndex(index);
|
||||||
|
|
||||||
|
Vector3 vertex = rotation.multPoint(Vector3(1.0, u, -(v - 0.5)));
|
||||||
|
vertices[index * 4 * 3 + i * 3] = vertex.x;
|
||||||
|
vertices[index * 4 * 3 + i * 3 + 1] = vertex.y;
|
||||||
|
vertices[index * 4 * 3 + i * 3 + 2] = vertex.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uv[i * 2] = u;
|
||||||
|
uv[i * 2 + 1] = v;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,18 +21,25 @@ class OPENGLSHARED_EXPORT OpenGLVegetationImpostor {
|
||||||
/**
|
/**
|
||||||
* Render a single instance using this impostor.
|
* Render a single instance using this impostor.
|
||||||
*/
|
*/
|
||||||
void render(OpenGLShaderProgram *program, const OpenGLVegetationInstance *instance, int index);
|
void render(OpenGLShaderProgram *program, const OpenGLVegetationInstance *instance, int instance_index,
|
||||||
|
const Vector3 &camera_location);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the texture grid for a given model.
|
* Prepare the texture grid for a given model.
|
||||||
*/
|
*/
|
||||||
void prepareTexture(const VegetationModelDefinition &model, const Scenery &environment, bool *interrupt);
|
void prepareTexture(const VegetationModelDefinition &model, const Scenery &environment, bool *interrupt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the impostor grid index for an instance, to face the camera.
|
||||||
|
*/
|
||||||
|
int getIndex(const Vector3 &camera, const Vector3 &instance) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setVertex(int i, float x, float y, float z);
|
void setVertex(int i, float u, float v);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float *vertices;
|
float *vertices;
|
||||||
|
float *uv;
|
||||||
int texture_size;
|
int texture_size;
|
||||||
bool texture_changed;
|
bool texture_changed;
|
||||||
Texture2D *texture;
|
Texture2D *texture;
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
OpenGLVegetationInstance::OpenGLVegetationInstance(const VegetationInstance &wrapped) : wrapped(wrapped) {
|
OpenGLVegetationInstance::OpenGLVegetationInstance(const VegetationInstance &wrapped) : wrapped(wrapped) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLVegetationInstance::setDistance(double distance)
|
void OpenGLVegetationInstance::setDistance(double distance) {
|
||||||
{
|
|
||||||
this->distance = distance;
|
this->distance = distance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ class OPENGLSHARED_EXPORT OpenGLVegetationInstance {
|
||||||
*/
|
*/
|
||||||
void setDistance(double distance);
|
void setDistance(double distance);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VegetationInstance wrapped;
|
VegetationInstance wrapped;
|
||||||
double distance;
|
double distance;
|
||||||
};
|
};
|
||||||
|
|
|
@ -93,7 +93,7 @@ void OpenGLVegetationLayer::threadedUpdate() {
|
||||||
zmax = newzmax;
|
zmax = newzmax;
|
||||||
removeInstancesOutsideArea(xmin, xmax, zmin, zmax, &instances);
|
removeInstancesOutsideArea(xmin, xmax, zmin, zmax, &instances);
|
||||||
instances.insert(instances.end(), new_instances.begin(), new_instances.end());
|
instances.insert(instances.end(), new_instances.begin(), new_instances.end());
|
||||||
for (auto instance: instances) {
|
for (auto instance : instances) {
|
||||||
instance->setDistance(instance->getBase().sub(*camera_location).getNorm());
|
instance->setDistance(instance->getBase().sub(*camera_location).getNorm());
|
||||||
}
|
}
|
||||||
std::sort(instances.begin(), instances.end(), compareInstances);
|
std::sort(instances.begin(), instances.end(), compareInstances);
|
||||||
|
@ -111,7 +111,7 @@ void OpenGLVegetationLayer::render() {
|
||||||
// TODO Instanced rendering
|
// TODO Instanced rendering
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (auto instance : instances) {
|
for (auto instance : instances) {
|
||||||
impostor->render(parent->getProgram(), instance, index++);
|
impostor->render(parent->getProgram(), instance, index++, *camera_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_instances->release();
|
lock_instances->release();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
attribute highp vec4 vertex;
|
attribute highp vec3 vertex;
|
||||||
|
attribute highp vec2 uv;
|
||||||
uniform highp mat4 viewMatrix;
|
uniform highp mat4 viewMatrix;
|
||||||
uniform highp vec3 offset;
|
uniform highp vec3 offset;
|
||||||
uniform float size;
|
uniform float size;
|
||||||
|
@ -9,8 +10,7 @@ uniform float waterOffset;
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
vec3 final = offset + size * (vertex.xyz - vec3(0.0, 0.0, 0.5)); // + vec3(0, waterOffset, 0)
|
unprojected = offset + size * vertex; // + vec3(0, waterOffset, 0)
|
||||||
unprojected = final.xyz;
|
texcoord = vec2(0.25 * (uv.s + float(mod(index, 4))), 0.25 * (uv.t + float(index / 4)));
|
||||||
texcoord = vec2(0.25 * (vertex.z + float(mod(index, 4))), 0.25 * (vertex.y + float(index / 4)));
|
gl_Position = viewMatrix * vec4(unprojected, 1.0);
|
||||||
gl_Position = viewMatrix * vec4(final.xyz, 1.0);
|
|
||||||
}
|
}
|
||||||
|
|
21
src/tests/OpenGLVegetationImpostor_Test.cpp
Normal file
21
src/tests/OpenGLVegetationImpostor_Test.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include "BaseTestCase.h"
|
||||||
|
#include "OpenGLVegetationImpostor.h"
|
||||||
|
|
||||||
|
#include "Vector3.h"
|
||||||
|
|
||||||
|
TEST(OpenGLVegetationImpostor, getIndex) {
|
||||||
|
OpenGLVegetationImpostor impostor;
|
||||||
|
|
||||||
|
EXPECT_EQ(0, impostor.getIndex(Vector3(0.0, 1.0, 0.0), VECTOR_ZERO));
|
||||||
|
|
||||||
|
EXPECT_EQ(1, impostor.getIndex(Vector3(1.0, 1.0, 0.0), VECTOR_ZERO));
|
||||||
|
EXPECT_EQ(1, impostor.getIndex(Vector3(1.0, 1.0, 0.1), VECTOR_ZERO));
|
||||||
|
EXPECT_EQ(1, impostor.getIndex(Vector3(1.0, 1.0, -0.1), VECTOR_ZERO));
|
||||||
|
|
||||||
|
EXPECT_EQ(2, impostor.getIndex(Vector3(1.0, 1.0, -1.0), VECTOR_ZERO));
|
||||||
|
EXPECT_EQ(5, impostor.getIndex(Vector3(1.0, 1.0, 1.0), VECTOR_ZERO));
|
||||||
|
|
||||||
|
EXPECT_EQ(6, impostor.getIndex(Vector3(1.0, 0.0, 0.0), VECTOR_ZERO));
|
||||||
|
EXPECT_EQ(6, impostor.getIndex(Vector3(1.0, 0.0, 0.1), VECTOR_ZERO));
|
||||||
|
EXPECT_EQ(6, impostor.getIndex(Vector3(1.0, 0.0, -0.1), VECTOR_ZERO));
|
||||||
|
}
|
Loading…
Reference in a new issue