vegetation: Fixed segfault in unit test

This commit is contained in:
Michaël Lemaire 2015-12-13 17:47:22 +01:00
parent 4a710c0977
commit 1d9d24b958
4 changed files with 68 additions and 48 deletions

View file

@ -29,9 +29,9 @@ void VegetationDefinition::applyPreset(VegetationPreset preset, RandomGenerator
clear(); clear();
if (preset == VEGETATION_PRESET_TEMPERATE) { /*if (preset == VEGETATION_PRESET_TEMPERATE) {
layer.applyPreset(VegetationLayerDefinition::VEGETATION_BASIC_TREES, random); layer.applyPreset(VegetationLayerDefinition::VEGETATION_BASIC_TREES, random);
layer.setName("Basic tree"); layer.setName("Basic tree");
addLayer(layer); addLayer(layer);
} }*/
} }

View file

@ -59,49 +59,55 @@ void OpenGLVegetationLayer::removeInstancesOutsideArea(double xmin, double xmax,
instances->erase(remove_if(instances->begin(), instances->end(), isNull), instances->end()); instances->erase(remove_if(instances->begin(), instances->end(), isNull), instances->end());
} }
void OpenGLVegetationLayer::updateInstances() {
// Compute new area around camera
double newxmin, newxmax, newzmin, newzmax;
newxmin = camera_location->x - range;
newxmax = camera_location->x + range;
newzmin = camera_location->z - range;
newzmax = camera_location->z + range;
// Prepare instances where area grew
vector<OpenGLVegetationInstance *> new_instances;
if (newxmin < xmin) {
produceInstancesInArea(newxmin, xmin, newzmin, newzmax, &new_instances);
}
if (newxmax > xmax) {
produceInstancesInArea(xmax, newxmax, newzmin, newzmax, &new_instances);
}
if (newzmin < zmin) {
produceInstancesInArea(xmin, xmax, newzmin, zmin, &new_instances);
}
if (newzmax > zmax) {
produceInstancesInArea(xmin, xmax, zmax, newzmax, &new_instances);
}
// Apply the changes
lock_instances->acquire();
xmin = newxmin;
xmax = newxmax;
zmin = newzmin;
zmax = newzmax;
removeInstancesOutsideArea(xmin, xmax, zmin, zmax, &instances);
instances.insert(instances.end(), new_instances.begin(), new_instances.end());
for (auto instance : instances) {
instance->setDistance(instance->getBase().sub(*camera_location).getNorm());
}
sort(instances.begin(), instances.end(), compareInstances);
lock_instances->release();
}
void OpenGLVegetationLayer::updateImpostor() {
bool interrupted = false;
impostor->prepareTexture(*definition->getModel(), *parent->getScenery(), &interrupted);
}
void OpenGLVegetationLayer::threadedUpdate() { void OpenGLVegetationLayer::threadedUpdate() {
if (camera_changed) { if (camera_changed) {
camera_changed = false; camera_changed = false;
// Compute new area around camera updateInstances();
double newxmin, newxmax, newzmin, newzmax; updateImpostor();
newxmin = camera_location->x - range;
newxmax = camera_location->x + range;
newzmin = camera_location->z - range;
newzmax = camera_location->z + range;
// Prepare instances where area grew
vector<OpenGLVegetationInstance *> new_instances;
if (newxmin < xmin) {
produceInstancesInArea(newxmin, xmin, newzmin, newzmax, &new_instances);
}
if (newxmax > xmax) {
produceInstancesInArea(xmax, newxmax, newzmin, newzmax, &new_instances);
}
if (newzmin < zmin) {
produceInstancesInArea(xmin, xmax, newzmin, zmin, &new_instances);
}
if (newzmax > zmax) {
produceInstancesInArea(xmin, xmax, zmax, newzmax, &new_instances);
}
// Apply the changes
lock_instances->acquire();
xmin = newxmin;
xmax = newxmax;
zmin = newzmin;
zmax = newzmax;
removeInstancesOutsideArea(xmin, xmax, zmin, zmax, &instances);
instances.insert(instances.end(), new_instances.begin(), new_instances.end());
for (auto instance : instances) {
instance->setDistance(instance->getBase().sub(*camera_location).getNorm());
}
sort(instances.begin(), instances.end(), compareInstances);
lock_instances->release();
// Update impostor texture
bool interrupted = false;
impostor->prepareTexture(*definition->getModel(), *parent->getScenery(), &interrupted);
} }
} }

View file

@ -34,6 +34,20 @@ class OPENGLSHARED_EXPORT OpenGLVegetationLayer {
virtual void removeInstancesOutsideArea(double xmin, double xmax, double zmin, double zmax, virtual void removeInstancesOutsideArea(double xmin, double xmax, double zmin, double zmax,
vector<OpenGLVegetationInstance *> *instances) const; vector<OpenGLVegetationInstance *> *instances) const;
/**
* Update the instances list.
*
* This should be called when the camera has moved enough to make a change.
*/
void updateInstances();
/**
* Update the impostor textures.
*
* This should be called when the camera has moved enough to make a change.
*/
void updateImpostor();
/** /**
* Perform maintenance tasks that can be perform in a thread. * Perform maintenance tasks that can be perform in a thread.
* *

View file

@ -28,7 +28,7 @@ class FakeLayerRenderer : public OpenGLVegetationLayer {
vector<OpenGLVegetationInstance *> static_instances; vector<OpenGLVegetationInstance *> static_instances;
}; };
TEST(OpenGLVegetationLayer, threadedUpdate) { TEST(OpenGLVegetationLayer, updateInstances) {
CameraDefinition camera; CameraDefinition camera;
VegetationLayerDefinition definition(NULL, "test"); VegetationLayerDefinition definition(NULL, "test");
FakeLayerRenderer rendering(&definition); FakeLayerRenderer rendering(&definition);
@ -36,32 +36,32 @@ TEST(OpenGLVegetationLayer, threadedUpdate) {
EXPECT_EQ(0, rendering.getInstanceCount()); EXPECT_EQ(0, rendering.getInstanceCount());
rendering.threadedUpdate(); rendering.updateInstances();
EXPECT_EQ(0, rendering.getInstanceCount()); EXPECT_EQ(0, rendering.getInstanceCount());
rendering.static_instances.push_back( rendering.static_instances.push_back(
new OpenGLVegetationInstance(VegetationInstance(model, Vector3(0.0, 0.0, 0.0)))); new OpenGLVegetationInstance(VegetationInstance(model, Vector3(0.0, 0.0, 0.0))));
rendering.reset(); rendering.reset();
rendering.threadedUpdate(); rendering.updateInstances();
EXPECT_EQ(1, rendering.getInstanceCount()); EXPECT_EQ(1, rendering.getInstanceCount());
camera.setLocation(Vector3(-5.0, 0.0, 0.0)); camera.setLocation(Vector3(-5.0, 0.0, 0.0));
rendering.setCamera(&camera); rendering.setCamera(&camera);
rendering.threadedUpdate(); rendering.updateInstances();
EXPECT_EQ(1, rendering.getInstanceCount()); EXPECT_EQ(1, rendering.getInstanceCount());
camera.setLocation(Vector3(-11.0, 0.0, 0.0)); camera.setLocation(Vector3(-11.0, 0.0, 0.0));
rendering.setCamera(&camera); rendering.setCamera(&camera);
rendering.threadedUpdate(); rendering.updateInstances();
EXPECT_EQ(0, rendering.getInstanceCount()); EXPECT_EQ(0, rendering.getInstanceCount());
camera.setLocation(Vector3(0.0, 0.0, 5.0)); camera.setLocation(Vector3(0.0, 0.0, 5.0));
rendering.setCamera(&camera); rendering.setCamera(&camera);
rendering.threadedUpdate(); rendering.updateInstances();
EXPECT_EQ(1, rendering.getInstanceCount()); EXPECT_EQ(1, rendering.getInstanceCount());
camera.setLocation(Vector3(0.0, 0.0, 15.0)); camera.setLocation(Vector3(0.0, 0.0, 15.0));
rendering.setCamera(&camera); rendering.setCamera(&camera);
rendering.threadedUpdate(); rendering.updateInstances();
EXPECT_EQ(0, rendering.getInstanceCount()); EXPECT_EQ(0, rendering.getInstanceCount());
} }