Skip to content
This repository has been archived by the owner on Apr 10, 2018. It is now read-only.

3d extrusion (buildings etc) spec #456

Closed
lbud opened this issue May 26, 2016 · 53 comments
Closed

3d extrusion (buildings etc) spec #456

lbud opened this issue May 26, 2016 · 53 comments

Comments

@lbud
Copy link
Contributor

lbud commented May 26, 2016

Spinning off of mapbox/mapbox-gl-js#684 (comment): I've reimplemented @ansis's 3d building demo (js branch; spec branch; shader branch). That code is ported pretty faithfully from the demo, except that I've renamed building to extrusion everywhere: it

  • adds a new extrusion type (in which one would specify a polygon source layer)
  • hardcodes a light direction
  • extrudes a height based on a feature's properties.levels (the demo is done based on a source from @ajashton with this property), or falls back to a hardcoded levels integer
  • I also added a extrusion-shadow-color, which colors the shadow tint (but is pretty subtle; doesn't change the amount of possible shadowing)

I propose the following additions to the spec (:warning: not all of which are yet implemented):

  • We add a new extrusion type. At present it only extrudes polygons. We may add support for extruding lines and points in the future, given compelling use cases/need.
  • Extrusion properties:
    • layout:
      • visibility
      • Presumably there will be additional layout properties concerning label placement etc once more cases are tested
    • paint:
      • extrusion-color
      • extrusion-shadow-color (open to other naming suggestions -- @tmcw might have one)
      • extrusion-opacity (I'm on the fence about this as it can create weird ghostly buildings, but can support if people find ghostly buildings compelling)
      • extrusion-pattern: implementation has been punted so far but I fear this should probably exist
      • extrusion-antialias
      • extrusion-outline-color (and if so, what should an extrusion outline be? Just the base? Other edges? (Hint: I haven't done other edges))
      • extrusion-translate
      • extrusion-translate-anchor
      • extrusion-height: Though undoubtably there are cases to extrude not based on data (@1ec5 would here point out that the buildings in DC are more or less all the same height by law), I think it's important this new type be DDS-first.
      • extrusion-lighting-anchor (whether a lighting direction should be oriented to map or viewport)
  • APIs:
    • map.setLightDirection to change lighting

@mapbox/gl @mapbox/cartography-cats

@1ec5
Copy link
Contributor

1ec5 commented May 26, 2016

extrusion-opacity (I'm on the fence about this as it can create weird ghostly buildings, but can support if people find ghostly buildings compelling)

Some values of extrusion-opacity might lead to weird effects like the one you found, but Google Maps makes its buildings subtly transcluent to prevent tall buildings from completely obscuring surrounding streets.

extrusion-pattern: implementation has been punted so far but I fear this should probably exist

Would the use case would be for, say, a realistic texture for stone façades or a window pattern on office buildings?

map.setLightDirection to change lighting

I think this would be useful for terrain lighting, too.

In addition to the lighting source’s azimuth, what about its altitude? The sun (or moon) would need to be much lower to accommodate a sunrise or sunset effect.

extrudes a height based on a feature's properties.levels (the demo is done based on a source from @ajashton with this property), or falls back to a hardcoded levels integer

Aside: Cantilevered building structures or pedestrian bridges that have a significant horizontal footprint would need a min-levels or min-height property. I think it would be useful to consider these cases even in a simple extrusion model that doesn’t account for unusual building shapes.

@ajashton
Copy link

Awesome. We'll also need something like extrusion-height-factor (or #47) since height data will be in a variety of units (levels, meters, feet, some other non-height data to visualize such as population density).

@ajashton
Copy link

Cantilevered building structures or pedestrian bridges

There are loads of other of odd building shapes that are not suitable for simple extrusion. Since many of these are important landmarks that can't be ignored, we'll probably need some kind of separate true 3d modelling - maybe cantilevers and sky bridges would best be preprocessed into whatever this format ends up being rather than having special extrusion handling for them?

@peterqliu
Copy link
Contributor

would need a min-levels or min-height property

Would such a 3D shape levitate in midair? or would it rest on a second, smaller shape?

@lbud
Copy link
Contributor Author

lbud commented May 26, 2016

@peterqliu these
image
are actually tons of little polygons extruded separately to form complex buildings (see e.g.). I would assume in the case of pedestrian bridges or cantilevered buildings they would be relations similarly modeled with multiple polygons, some powerless to gravity. But I agree with @ajashton: let's handle simple extrusion cases first…

@1ec5
Copy link
Contributor

1ec5 commented May 26, 2016

Would such a 3D shape levitate in midair? or would it rest on a second, smaller shape?

In the source being used in @lbud’s demo, each building part is extruded individually, so imagine Fallingwater being represented by a number of building parts, some of which have a min-height. (In OpenStreetMap, the min_height and building:min_level tags are used even in areas that aren’t more meticulously mapped according to the “simple 3D buildings” scheme.)

maybe cantilevers and sky bridges would best be preprocessed into whatever this format ends up being rather than having special extrusion handling for them?

I don’t think it’s strictly necessary to support arbitrary building shapes in order to support raised features as part of extrusion. Or perhaps the concept should be generalized so that, for instance, a point feature can levitate above a tilted map. Such a property would be useful for the “user location dot” or “course puck” that is typically drawn with a drop shadow, as if levitating, in mobile map SDKs. But for buildings, I think the concept of a “knocked-out” floor is not merely decorative and also not necessarily tied to true 3D modeling.

@andreasviglakis
Copy link

andreasviglakis commented May 26, 2016

this is great.

but Google Maps makes its buildings subtly transcluent to prevent tall buildings from completely obscuring surrounding streets.

👍

Would such a 3D shape levitate in midair?

yes? but no, not really.

image

how would this spec deal (now or in the future) with complex but critical edge cases like the eiffel tower? would this be covered by "support for extruding lines and points?"

@lucaswoj
Copy link

At present it only extrudes polygons. We may add support for extruding lines and points in the future, given compelling use cases/need.

Would it be possible to add the extrude-* properties to the existing fill (and eventually lineand point) types rather than adding a new layer type?

@lbud
Copy link
Contributor Author

lbud commented May 26, 2016

Hmm. @lucaswoj — I considered this, but ultimately I think it makes more sense to create a new layer type (also, I should note I'm very skeptical about use cases for extruding lines and points*):

  • The intention behind filling in a flat area of land (or water) vs that behind creating three-dimensional shapes feel inherently very different
  • Lighting affects the flat surface of an extrusion in addition to its walls, meaning without writing separate cases for this, a light source would change the color of even an unextruded fill
  • Everything else about the bucket/shader code would have to be very if/else anyway, and it would be much cleaner to keep these separate

* I'd also add that I do see the case for raising, say, a point (circle/symbol type) on a map, but I wouldn't consider those "extrusions" — "extrusion" here isn't so much "raise this thing on the map" as it is "turn this into a vertical prism/give it walls."

@1ec5
Copy link
Contributor

1ec5 commented May 26, 2016

There are use cases for extruding lines and points, as opposed to having them levitate. For example, you might want to place an elevation profile on the map, or mark cities with extruded points whose heights correspond to population or some other attribute.

@lbud
Copy link
Contributor Author

lbud commented May 26, 2016

Alright; maybe we'll do those later.

@peterqliu
Copy link
Contributor

peterqliu commented May 26, 2016

If it's not a significant scope creep, negative extrusions would be useful for things like strip mines/sinkholes.

edit: can just be a rectilinear cavity, not a complex shape or mesh

@lbud
Copy link
Contributor Author

lbud commented May 26, 2016

@peterqliu unfortunately that is a significant scope creep for now.

edit: re edit: still significant scope creep

@lucaswoj
Copy link

  • APIs:
    • map.setLightDirection to change lighting

Could this be a root property on the style? We would still need a Map#setLightDirection method.


Otherwise, :shipit: on this spec 😄

@lucaswoj
Copy link

Lighting affects the flat surface of an extrusion in addition to its walls, meaning without writing separate cases for this, a light source would change the color of even an unextruded fill

Will the map look funny in any situations if the lighting doesn't affect unextruded fills?

@scothis
Copy link
Contributor

scothis commented Aug 10, 2016

👍 for adding lightDirection to the root of the style. It will fit nicely alongside the defaults for center, zoom, bearing and pitch. Only concern is that we should feel comfortable that this is the only lighting setting we want to have because it will be annoying to update/deprecate it later.

@nickidlugash
Copy link
Contributor

@scothis we're actually thinking now of adding a light object to the root of the style, which will have direction, anchor, and color properties. We'll update this ticket later today with a revision of the full proposal /cc @lbud

@nickidlugash
Copy link
Contributor

Here's an update to @lbud's and my proposed style spec changes:

  • Root properties:
    • light | Optional object
      • light-anchor | Optional enum. Default: viewport
      • light-direction | Optional array. Default: [-0.5, -0.3, 1.0]
      • light-color | Optional color. Default: rgba(1, 1, 1, 0.75) *
  • Extrusion properties:
    • Layout:
      • visibility | Optional enum. Default: visible
    • Paint:
      • extrusion-height | Optional number. Default: 1 (meter)
      • extrusion-min-height | Optional number. Default: 0 (meter) *
      • extrusion-color | Optional color. Default: #929292
      • extrusion-layer-opacity | Optional number. Default: 1 *
      • extrusion-pattern | Optional string
      • extrusion-antialias | Optional boolean. Default false
      • extrusion-outline-color | Optional color. Matches extrusion-color if unspecified
      • extrusion-translate | Optional array. Default [0, 0]
      • extrusion-translate-anchor | Optional enum. Default: map
  • APIs:
    • map.setLightProperty
      • e.g. map.setLightProperty({light-anchor: "map", light-color: "#f00"})

Notes

  • the alpha value in light-color is the light intensity.
  • extrusion-min-height is the height to start extruding from. This corresponds to the concept of min-height in OSM.
  • extrusion-layer-opacityis per-layer opacity, unlike the -opacity properties of other layer types which are per-feature, because per-feature opacity for extrusions results in unexpected behavior. We may be able to add an extrusion-opacity property for per-feature opacity in the future.
  • Shading color is currently affected by a combination of the extrusion-color and light-color properties. There is no specific shading-color property, although we could potential add that in the future if needed.

@1ec5
Copy link
Contributor

1ec5 commented Aug 12, 2016

What unit is light-direction expressed in? Is it a real-world unit?

@dpieri
Copy link

dpieri commented Aug 15, 2016

Is this spec being designed with future support for 3D terrain meshes in mind?

@gatelli
Copy link

gatelli commented Aug 19, 2016

Amazing ! Do you have an idea of the release date ?

@lucaswoj
Copy link

  • Root properties:
    • light | Optional object
      • light-anchor | Optional enum. Default: viewport
      • light-direction | Optional array. Default: [-0.5, -0.3, 1.0]
      • light-color | Optional color. Default: rgba(1, 1, 1, 0.75) *

Why a light object rather than putting the light-* properties directly in the root of the stylesheet? These properties are double-namespaced.


  • APIs:
    • map.setLightProperty
      • e.g. map.setLightProperty({light-anchor: "map", light-color: "#f00"})

The other Map#set*Property methods have a signature like map.setLightProperty('light-anchor', 'map'). I like this new signature too! If we're going to support it, we should support it everywhere.


  • extrusion-min-height is the height to start extruding from. This corresponds to the concept of min-height in OSM.

I appreciate that this is the naming convention established by OSM.
I also think it could be confusing to users who expect it to behave like CSS's min-* properties in the context of a stylesheet.
Perhaps a name like extrusion-bottom-height would be less surprising.

@jfirebaugh
Copy link
Contributor

What is the function of extrusion-outline-color? Does this stroke the edges of the extrusion? Is there potential for regretting this property, as we do with fill-outline-color?

per-feature opacity for extrusions results in unexpected behavior

Can you say more about this? E.g. is it a technical limitation or a bug in the current code that we haven't tracked down yet? What happens if you use something like "extrusion-color": rgba(255, 0, 0, 0.5) in lieu of "extrusion-color": rgb(255, 0, 0), "extrusion-opacity": 0.5?

Perhaps a name like extrusion-bottom-height would be less surprising.

Or even simply extrusion-bottom + extrusion-top, a la CSS?

@nickidlugash
Copy link
Contributor

Perhaps a name like extrusion-bottom-height would be less surprising.

Or even simply extrusion-bottom + extrusion-top, a la CSS?

These are probably better options than extrusion-min-height. I think specifying that these are -height properties is important (I could be wrong, but I think the only CSS properties that are not specific in this way are the shorthand properties that combine multiple properties). So maybe either:

  1. extrusion-height + extrusion-bottom-height
  2. extrusion-top-height + extrusion-bottom-height ?

It's a bit long-winded, but maybe the second option is better, for clarity and just to be more parallel?

@1ec5
Copy link
Contributor

1ec5 commented Aug 22, 2016

The only information that “height” provides in this context is that “top” and “bottom” are measured along the vertical (altitudinal) axis. But “top” and “bottom” already provide this context. In CSS, when an element is absolutely positioned, top and bottom also represent absolute values along the vertical axis; no -height or -depth suffix is needed.

@peterqliu
Copy link
Contributor

peterqliu commented Aug 22, 2016

Are there situations (even in the future) when an extrusion-bottom or extrusion-min-height can actually be above the "top" of the extrusion? This might happen if we support negative extrusions in the future, and would be confusing.

extrusion-min-height is the height to start extruding from. This corresponds to the concept of min-height in OSM.

how about some form of extrusion-start?

@lbud
Copy link
Contributor Author

lbud commented Aug 22, 2016

What unit is light-direction expressed in? Is it a real-world unit?

@1ec5 No, it's a three-dimensional x, y, z vector, where [0,0,0] would represent light coming from inside an individual extrusion. The higher the number, the more intense the light, both in the positive and negative direction. I'm not entirely sure what's the best way to communicate this yet…

@scothis
Copy link
Contributor

scothis commented Aug 30, 2016

Also agree that extrusion-min-height is a strange name. I interpret it as setting a value a the height cannot be less than Math.max(minHeight, height). Something like extrusion-base-height is more clear to me, as the value is where the extrusion starts from.

@nickidlugash
Copy link
Contributor

extrusion-height + extrusion-base-height sounds good to me.

@lucaswoj
Copy link

lucaswoj commented Sep 1, 2016

I would like to revisit this proposal

Would it be possible to add the extrude-* properties to the existing fill (and eventually lineand point) types rather than adding a new layer type?

There has been continued interest in extruding lines, points, and circles. The implementation of this functionality may be done later but the specification design must be considered now. The cleanest way to implement this functionality is to allow extrude-* properties on other layer types.


The intention behind filling in a flat area of land (or water) vs that behind creating three-dimensional shapes feel inherently very different

The only reason fill layers are flat is because we haven't implemented extrusions yet.

Lighting affects the flat surface of an extrusion in addition to its walls, meaning without writing separate cases for this, a light source would change the color of even an unextruded fill

I find it surprising that the top of an extrusion is colored differently than a fill layer. This implies that lighting is applied inconsistently to different layer types. That'd be surprising whether fill and extrusion are separate layer types or not.

Everything else about the bucket/shader code would have to be very if/else anyway, and it would be much cleaner to keep these separate

We can keep the implementations separate and hide that implementation detail from the spec.

* I'd also add that I do see the case for raising, say, a point (circle/symbol type) on a map, but I wouldn't consider those "extrusions" — "extrusion" here isn't so much "raise this thing on the map" as it is "turn this into a vertical prism/give it walls."

A quick search indicates that 3d modeling software (Blender, Sketchup) supports "extruding" lines and points.

@1ec5
Copy link
Contributor

1ec5 commented Sep 1, 2016

* I'd also add that I do see the case for raising, say, a point (circle/symbol type) on a map, but I wouldn't consider those "extrusions" — "extrusion" here isn't so much "raise this thing on the map" as it is "turn this into a vertical prism/give it walls."

A quick search indicates that 3d modeling software (Blender, Sketchup) supports "extruding" lines and points.

Indeed, but as I pointed out in #456 (comment), I think there’s a distinction to be made between “levitating” a layer (raising it above the ground) and extruding it (giving it a support structure). Is it extrusion if you take a 2D layer and levitate it without giving it any depth?

Consider a map that has extruded buildings, so you want the Maki POI markers to levitate with leader lines extending from the POIs down to the ground, to avoid any ambiguity around depth. The symbol layer for the POI markers would be levitated, while the leader lines would be implemented as extruded point layers. Google Maps does something like this on the Web (in 3D Earth view), although it would be awesome to be able to vary the vertical offset by the POI’s importance. Maybe it’s already possible using icon-offset, though.

Implementation-wise, should we treat levitation as a special case of extrusion regardless (extrusion-base-height equaling extrusion-height)?

@lbud
Copy link
Contributor Author

lbud commented Sep 1, 2016

Alright team, you've got me convinced.

@mapbox/gl @peterqliu

Increasing use cases for 3d maps (navigation, gaming) definitely present use cases for

  • extruding geometries
    • extruding fills (buildings ++)
      image
    • extruding lines
      image
    • extruding circles (data viz)
  • levitating geometries
    • levitating lines
      image
    • levitating points (symbols)
    • and, likely, levitating fills

Levitation use cases will be addressed in mapbox/DEPRECATED-mapbox-gl#6. But we will design the spec in a way that makes it more extensible for extruding multiple geometry types.

As such we are modifying this spec proposal: presently,

  • the extrusion type is no more
  • fill types will have an additional
    • fill-extrude-height (default: 0)
    • fill-extrude-base (default: 0)

In the future we'll add the same properties to line types, and eventually also likely circle types.

At present this means we'll handle fill-opacity without extrudes and fill-opacity with extrudes differently, the former on a per-feature basis (as it currently is) and the latter on a per-layer basis. All other fill properties can still apply directly to extruded fills (extrusion-color -> fill-color, extrusion-pattern -> fill-pattern, -translate, -translate-anchor, etc).

The biggest catch in this is that as soon as a feature is extruded it will also be affected by the map's lighting. The current in-progress implementation of extrusions treats extrusion-color as the surface color of an object and lights all sides (including the top) accordingly, so lighting will make the tops of extruded fills look different from flat fills.

@lbud
Copy link
Contributor Author

lbud commented Sep 1, 2016

(I'm flexible on exact wording of [type]-extrude-height and [type]-extrude-base)

@nickidlugash
Copy link
Contributor

Just noting here that our roadmap doesn't currently include the ability to create 3D leader lines (I suppose you could hack something together with a symbol layer + circle layer, but they wouldn't be related to each other, so collisions would be inconsistent). I think this is fine for now, as you also can't currently create 2D leader lines either. Leader lines in general may need special implementation in the symbol layer.

@lbud
Copy link
Contributor Author

lbud commented Oct 20, 2016

Closing as implemented — will open tickets for other 3d properties as needed.

@bensleveritt
Copy link

bensleveritt commented Dec 9, 2016

@lbud Is there a plan to create tickets for levitated line and circles? After playing with the extrusion layer (and loving it), it'd be great to get lines that correlated vertically with their extrusion. Also circles.

@lbud
Copy link
Contributor Author

lbud commented Dec 9, 2016

@bensleveritt there's discussion happening at mapbox/DEPRECATED-mapbox-gl#6 about how we may approach "levitated" features.

@bensleveritt
Copy link

@lbud Thanks, I did see that, but I wasn't sure it was the most up to date tracking of the feature.

@phprad
Copy link

phprad commented Oct 30, 2017

How do you style individual building.
How can one loop through the building to gets the bounding coordinates of a building.
Thanks

@lbud
Copy link
Contributor Author

lbud commented Oct 30, 2017

Hi @phprad, thanks for using Mapbox. For "how do I" questions like this, please refer to our help documentation, and if you can't find the answer there, contact support. This issue tracker is for reporting bugs and feature requests. Thank you!

@strech345
Copy link

Does i understand right, properties like extrusion-antialias was removed? Is there a way to enable it anyway?

@lbud
Copy link
Contributor Author

lbud commented Jan 29, 2018

That's right @strech345, there is no antialias or outline property for fill-extrusions.

@strech345
Copy link

Hello @lbud ,
thanks, coud you explain why this was removes and if this will come again?

@lbud
Copy link
Contributor Author

lbud commented Feb 8, 2018

Sure, fill-extrusion-antialias was a bit of a misnomer as it essentially implemented 1px outlines (like fill-antialias does) without actually using the same antialiasing technique fill-antialias does, so it did not effectively provide antialiasing, and we deemed outlines unnecessary. We experimented with another antialiasing technique that didn't provide great results either and therefore removed this property.

@strech345
Copy link

Hello @lbud ,
thanks.
Do you know if someone is working on it and if it will include in future?

@lbud
Copy link
Contributor Author

lbud commented Feb 20, 2018

It is not under active development or prioritized at this time.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests