WS30: Improved streetlights
- Use a single LightBin per tile, rather than per road - Support lights offset on either side of the road.
This commit is contained in:
@@ -277,6 +277,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
|
|||||||
light_edge_intensity_cd = props->getDoubleValue("light-edge-intensity-cd", 50.0);
|
light_edge_intensity_cd = props->getDoubleValue("light-edge-intensity-cd", 50.0);
|
||||||
light_edge_angle_horizontal_deg = props->getDoubleValue("light-edge-angle-horizontal-deg", 360.0);
|
light_edge_angle_horizontal_deg = props->getDoubleValue("light-edge-angle-horizontal-deg", 360.0);
|
||||||
light_edge_angle_vertical_deg = props->getDoubleValue("light-edge-angle-vertical-deg", 360.0);
|
light_edge_angle_vertical_deg = props->getDoubleValue("light-edge-angle-vertical-deg", 360.0);
|
||||||
|
light_edge_offset = props->getBoolValue("light-edge-offset", true);
|
||||||
|
|
||||||
light_edge_colour[0] = props->getDoubleValue("light-edge-color/r", 1.0);
|
light_edge_colour[0] = props->getDoubleValue("light-edge-color/r", 1.0);
|
||||||
light_edge_colour[1] = props->getDoubleValue("light-edge-color/g", 1.0);
|
light_edge_colour[1] = props->getDoubleValue("light-edge-color/g", 1.0);
|
||||||
@@ -457,6 +458,7 @@ SGMaterial::init ()
|
|||||||
light_edge_angle_horizontal_deg = 360.0;
|
light_edge_angle_horizontal_deg = 360.0;
|
||||||
light_edge_angle_vertical_deg = 360.0;
|
light_edge_angle_vertical_deg = 360.0;
|
||||||
light_edge_colour = SGVec4f(1.0,1.0,1.0,1.0);
|
light_edge_colour = SGVec4f(1.0,1.0,1.0,1.0);
|
||||||
|
light_edge_offset = true;
|
||||||
|
|
||||||
building_coverage = 0.0;
|
building_coverage = 0.0;
|
||||||
|
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ public:
|
|||||||
inline double get_light_edge_angle_horizontal_deg() const { return light_edge_angle_horizontal_deg; };
|
inline double get_light_edge_angle_horizontal_deg() const { return light_edge_angle_horizontal_deg; };
|
||||||
inline double get_light_edge_angle_vertical_deg() const { return light_edge_angle_vertical_deg; };
|
inline double get_light_edge_angle_vertical_deg() const { return light_edge_angle_vertical_deg; };
|
||||||
inline SGVec4f get_light_edge_colour() const { return light_edge_colour; };
|
inline SGVec4f get_light_edge_colour() const { return light_edge_colour; };
|
||||||
|
inline bool get_light_edge_offset() const { return light_edge_offset; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the building coverage.
|
* Get the building coverage.
|
||||||
@@ -452,6 +453,7 @@ private:
|
|||||||
double light_edge_angle_horizontal_deg;
|
double light_edge_angle_horizontal_deg;
|
||||||
double light_edge_angle_vertical_deg;
|
double light_edge_angle_vertical_deg;
|
||||||
SGVec4f light_edge_colour;
|
SGVec4f light_edge_colour;
|
||||||
|
bool light_edge_offset;
|
||||||
|
|
||||||
// coverage of buildings
|
// coverage of buildings
|
||||||
double building_coverage;
|
double building_coverage;
|
||||||
|
|||||||
@@ -1647,6 +1647,7 @@ void VPBTechnique::applyLineFeatures(BufferData& buffer, Locator* masterLocator)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get all appropriate roads. We assume that the VPB terrain tile is smaller than a Bucket size.
|
// Get all appropriate roads. We assume that the VPB terrain tile is smaller than a Bucket size.
|
||||||
|
LightBin lightbin;
|
||||||
const osg::Vec3d world = buffer._transform->getMatrix().getTrans();
|
const osg::Vec3d world = buffer._transform->getMatrix().getTrans();
|
||||||
const SGGeod loc = SGGeod::fromCart(toSG(world));
|
const SGGeod loc = SGGeod::fromCart(toSG(world));
|
||||||
const SGBucket bucket = SGBucket(loc);
|
const SGBucket bucket = SGBucket(loc);
|
||||||
@@ -1673,10 +1674,11 @@ void VPBTechnique::applyLineFeatures(BufferData& buffer, Locator* masterLocator)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int xsize = mat->get_xsize();
|
const unsigned int xsize = mat->get_xsize();
|
||||||
unsigned int ysize = mat->get_ysize();
|
const unsigned int ysize = mat->get_ysize();
|
||||||
double light_edge_spacing = mat->get_light_edge_spacing_m();
|
const bool light_edge_offset = mat->get_light_edge_offset();
|
||||||
double light_edge_height = mat->get_light_edge_height_m();
|
const double light_edge_spacing = mat->get_light_edge_spacing_m();
|
||||||
|
const double light_edge_height = mat->get_light_edge_height_m();
|
||||||
|
|
||||||
// Generate a geometry for this set of roads.
|
// Generate a geometry for this set of roads.
|
||||||
osg::Vec3Array* v = new osg::Vec3Array;
|
osg::Vec3Array* v = new osg::Vec3Array;
|
||||||
@@ -1688,7 +1690,7 @@ void VPBTechnique::applyLineFeatures(BufferData& buffer, Locator* masterLocator)
|
|||||||
auto lineFeatures = rb->getLineFeatures();
|
auto lineFeatures = rb->getLineFeatures();
|
||||||
|
|
||||||
for (auto r = lineFeatures.begin(); r != lineFeatures.end(); ++r) {
|
for (auto r = lineFeatures.begin(); r != lineFeatures.end(); ++r) {
|
||||||
if (r->_width > minWidth) generateLineFeature(buffer, masterLocator, *r, world, v, t, n, lights, xsize, ysize, light_edge_spacing, light_edge_height);
|
if (r->_width > minWidth) generateLineFeature(buffer, masterLocator, *r, world, v, t, n, lights, xsize, ysize, light_edge_spacing, light_edge_height, light_edge_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v->size() == 0) continue;
|
if (v->size() == 0) continue;
|
||||||
@@ -1715,7 +1717,6 @@ void VPBTechnique::applyLineFeatures(BufferData& buffer, Locator* masterLocator)
|
|||||||
addVegetationConstraint(geode);
|
addVegetationConstraint(geode);
|
||||||
|
|
||||||
if (lights->size() > 0) {
|
if (lights->size() > 0) {
|
||||||
LightBin lightbin;
|
|
||||||
const double size = mat->get_light_edge_size_cm();
|
const double size = mat->get_light_edge_size_cm();
|
||||||
const double intensity = mat->get_light_edge_intensity_cd();
|
const double intensity = mat->get_light_edge_intensity_cd();
|
||||||
const SGVec4f color = mat->get_light_edge_colour();
|
const SGVec4f color = mat->get_light_edge_colour();
|
||||||
@@ -1728,14 +1729,14 @@ void VPBTechnique::applyLineFeatures(BufferData& buffer, Locator* masterLocator)
|
|||||||
|
|
||||||
std::for_each(lights->begin(), lights->end(),
|
std::for_each(lights->begin(), lights->end(),
|
||||||
[&, size, intensity, color, direction, horiz, vertical] (osg::Vec3f p) { lightbin.insert(toSG(p), size, intensity, 1, color, direction, horiz, vertical); } );
|
[&, size, intensity, color, direction, horiz, vertical] (osg::Vec3f p) { lightbin.insert(toSG(p), size, intensity, 1, color, direction, horiz, vertical); } );
|
||||||
|
|
||||||
buffer._transform->addChild(createLights(lightbin, osg::Matrix::identity(), _options));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lightbin.getNumLights() > 0) buffer._transform->addChild(createLights(lightbin, osg::Matrix::identity(), _options));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VPBTechnique::generateLineFeature(BufferData& buffer, Locator* masterLocator, LineFeatureBin::LineFeature road, osg::Vec3d modelCenter, osg::Vec3Array* v, osg::Vec2Array* t, osg::Vec3Array* n, osg::Vec3Array* lights, unsigned int xsize, unsigned int ysize, double light_edge_spacing, double light_edge_height)
|
void VPBTechnique::generateLineFeature(BufferData& buffer, Locator* masterLocator, LineFeatureBin::LineFeature road, osg::Vec3d modelCenter, osg::Vec3Array* v, osg::Vec2Array* t, osg::Vec3Array* n, osg::Vec3Array* lights, unsigned int xsize, unsigned int ysize, double light_edge_spacing, double light_edge_height, bool light_edge_offset)
|
||||||
{
|
{
|
||||||
// We're in Earth-centered coordinates, so "up" is simply directly away from (0,0,0)
|
// We're in Earth-centered coordinates, so "up" is simply directly away from (0,0,0)
|
||||||
osg::Vec3d up = modelCenter;
|
osg::Vec3d up = modelCenter;
|
||||||
@@ -1829,34 +1830,34 @@ void VPBTechnique::generateLineFeature(BufferData& buffer, Locator* masterLocato
|
|||||||
yTexBaseA = yTexA;
|
yTexBaseA = yTexA;
|
||||||
yTexBaseB = yTexB;
|
yTexBaseB = yTexB;
|
||||||
last_spanwise = spanwise;
|
last_spanwise = spanwise;
|
||||||
float edge_length = (c-a).length() + last_light_distance;
|
float edge_length = (c-a).length();
|
||||||
|
float start_a = last_light_distance;
|
||||||
|
float start_b = start_a;
|
||||||
|
|
||||||
if ((road._attributes == 1) && (light_edge_spacing > 0.0)) {
|
if ((road._attributes == 1) && (light_edge_spacing > 0.0)) {
|
||||||
// We have some edge lighting. Traverse edges a-c and b-d adding lights as appropriate.
|
// We have some edge lighting. Traverse edges a-c and b-d adding lights as appropriate.
|
||||||
if (edge_length > light_edge_spacing) {
|
|
||||||
int num_lights = (int) floor(edge_length / light_edge_spacing);
|
// Handle the case where lights are on alternate sides of the road rather than in pairs
|
||||||
|
if (light_edge_offset) start_b = fmodf(start_b + light_edge_spacing * 0.5, light_edge_spacing);
|
||||||
|
|
||||||
// Get a pair of vector to travel along the edges
|
osg::Vec3f p1 = (c-a);
|
||||||
osg::Vec3f p1 = (c-a);
|
p1.normalize();
|
||||||
p1.normalize();
|
|
||||||
p1 = p1 * light_edge_spacing;
|
|
||||||
|
|
||||||
osg::Vec3f p2 = (d-b);
|
while (start_a < edge_length) {
|
||||||
p2.normalize();
|
lights->push_back(a + (osg::Vec3f) p1 * start_a + up * (light_edge_height + 1.0));
|
||||||
p2 = p2 * light_edge_spacing;
|
start_a += light_edge_spacing;
|
||||||
|
|
||||||
for (int i = 1; i <= num_lights; i++) {
|
|
||||||
// Place the lights, 5m above the road itself on either side.
|
|
||||||
lights->push_back((osg::Vec3f) a + p1 * (i - last_light_distance / light_edge_spacing) + up * (light_edge_height + 1.0));
|
|
||||||
lights->push_back((osg::Vec3f) b + p2 * (i - last_light_distance / light_edge_spacing) + up * (light_edge_height + 1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
last_light_distance = fmodf(edge_length, light_edge_spacing);
|
|
||||||
} else {
|
|
||||||
// For small road segments, keep track of the distance since the last light so we generate
|
|
||||||
// some lights on curves.
|
|
||||||
last_light_distance += edge_length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::Vec3f p2 = (d-b);
|
||||||
|
p2.normalize();
|
||||||
|
|
||||||
|
while (start_b < edge_length) {
|
||||||
|
lights->push_back(b + (osg::Vec3f) p2 * start_b + up * (light_edge_height + 1.0));
|
||||||
|
start_b += light_edge_spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the position for the first light on the next road segment.
|
||||||
|
last_light_distance = fmodf(start_a + edge_length, light_edge_spacing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,8 @@ class VPBTechnique : public TerrainTechnique
|
|||||||
unsigned int xsize,
|
unsigned int xsize,
|
||||||
unsigned int ysize,
|
unsigned int ysize,
|
||||||
double light_edge_spacing,
|
double light_edge_spacing,
|
||||||
double light_edge_height);
|
double light_edge_height,
|
||||||
|
bool light_edge_offset);
|
||||||
|
|
||||||
virtual void applyAreaFeatures(BufferData& buffer, Locator* masterLocator);
|
virtual void applyAreaFeatures(BufferData& buffer, Locator* masterLocator);
|
||||||
virtual void generateAreaFeature(BufferData& buffer,
|
virtual void generateAreaFeature(BufferData& buffer,
|
||||||
|
|||||||
Reference in New Issue
Block a user