# 3D Sceneries plugin

## Description

A 3D walkaround environment with applications from finding the best spot in your garden for unobstructed observing of some celestial event to archaeo-/ethnoastronomical alignment and light-and-shadow interaction studies.

## Introduction

Have you ever wished to be able to walk through Stonehenge or other ancient building structures described as being constructed with astronomical orientation in mind, and experience such orientation in a 3D virtual environment that also provides a good sky simulation?

The Stellarium Scenery3d plugin allows you to see architectural 3D models embedded in a landscape combined with the excellent representation of the sky provided by Stellarium. You can walk around, check for (or demonstrate) possible astronomical alignments of ancient architecture, see sundials and other shadow casters in action, etc.

## Usage

You activate the plugin with the circular enclosure button at screen bottom or by pressing [Ctrl+3]. The other button with circular enclosure and tool icon (or [Ctrl+Shift+3]) opens the settings dialog. Once loaded and displaying, you can walk around pressing [Ctrl] plus cursor keys. Change eye height with [Ctrl]+[PgUp]/[PgDn] keys. Adding [Shift] key increases speed by 10, [Alt] by 5 (pressing both keys multiplies by 50!). If you release [Ctrl] before the cursor key, animation will continue. (Press [Ctrl]+any cursor key to stop moving.)

Further key bindings exist which can be configured using the Stellarium default key-binding interface. Some options are also available in the Scenery3d dialog. For example, coordinate display can be enabled. If your models are georeferenced in a true geographical coordinate grid, e.g. UTM or Gauss-Krueger, you will especially like this, and this makes the plugin usable for scientific purposes. Display shows grid name, Easting, Northing, Altitude of ground, and eye height above ground.

Other features include a virtual torchlight, which can be enabled to give additional local illumination around the viewer to help to see in the dark. Interesting points of view can be saved and restored later by the user, including a description of the view. Scene authors can also distribute predefined viewpoints in their scene.

The plugin also simulates the shadows of the scene's objects cast by the Sun, Moon and even Venus (only 1 shadow caster used at a time, you will never see shadows cast by Venus in moonlight), so you could use it for examining sundials, or analyze and simulate light-and-shadow interactions in archeological structures.

## Hardware Requirements & Performance

In order to work with the non-linear projection models in Stellarium, this plugin uses a trick to create the foreground renderings: it renders the scene into the six planes of a cubemap, which is then correctly reprojected onto the sides of a cube, depending on the current projection settings. Your graphics card must be able to do this, i.e. it must support the OpenGL extension called EXT_framebuffer_object. Typical modern 3D cards support this extension. In case your graphics hardware does not suppport it, the plugin will still work, but you are limited to perspective projection.

You can influence rendering quality, but also speed, using the plugin's GUI, which provides some options such as enabling the use of shadows, bumpmapping (provides more realistic surface lighting) or configuring the sizes of the textures used for the cubemap or shadowmaps. Larger values there improve the quality, but require faster hardware and more video memory for smooth results.

Because the cubemap trick requires quite a large amount of performance (in essence, the scene has to be rendered 6 times), there are some options available that try to reduce this burden. The first option is to change the type of the cubemap. The most compatible setting is 6 textures, which seems to work best on older integrated Intel GPUs. The recommended default is the second setting, Cubemap, which uses a more modern OpenGL feature and generally works a bit faster than 6 textures on more modern graphics cards. Finally, the Geometry shader option tries to render all 6 cube faces at once. This requires a more recent GPU + drivers (at least OpenGL 3.2 must be supported), the setting is disabled otherwise. Depending on your hardware and the scene's complexity, this method may give a speedup or may be slower, you must find this out yourself.

Another option prevents re-rendering of the cubemap if nothing relevant has changed. You can define the interval (in Stellarium's simulation time) in which nothing is updated in the GUI. You can still rotate the camera without causing a re-draw, giving a subjective performance that is close to Stellarium's performance without Scenery3d. When moving, the cubemap will be updated. You can enable another option that only causes 1 or 2 sides of the cubemap to be updated while you move, giving a speedup but causing some parts of the image to be outdated and discontinuous. The cubemap will be completed again when you stop moving.

The configuration GUI shows tooltips for most of its settings, which can explain what a setting does. All settings are saved automatically, and restored when you reopen Stellarium.

### Performance notes

On reasonably good hardware (tested on a notebook PC with NVidia M580 GTS), models with about 500.000 triangles are fluent with shadows and bumpmaps. On very small hardware like single-board computers with native OpenGL ES2, models may be limited to 64k vertices (points). If display is too slow, switch to perspective projection: all other projections require almost sixfold effort! You should also prefer the lazy cubemap mode, where the scene is only rendered in specific timesteps or when movement happens.

## Installation of 3rd-party Models

(THIS SECTION IS WORK IN PROGRESS, 2016-01-02 --GZ--)

While there is a built-in process to install new Landscapes, installing new model files is currently done manually. If you want to add a model which somebody else has already prepared for use with Stellarium, please do the following.

Usually a model will come as ZIP file.

1. Browse to your User Data Directory, which varies according to your operating system. (eg. in Windows Vista/7 enter  %appdata%\stellarium in Explorer's location bar )
2. Create a sub-directory called scenery3d in your user directory (if it doesn't exist).
3. Unzip the model .zip file in the scenery3d directory. A sub-directory should be created for each model.
4. Go into the subdirectory and see that there is a file scenery3d.ini and at least one file of type .obj. If you want to get deeper involved, read on.

## Model Configuration

The model format supported in Scenery3d is Wavefront .OBJ, which is pretty common for 3D models. You can use several modeling programs to build your models. Software such as Blender, Maya, 3D Studio Max etc. can export OBJ.

A simple to use and cost-free modeling program is Google Sketchup, commonly used to create the 3D buildings seen in Google Earth. It can be used to create georeferenced models. OBJ is not a native export format for the standard version of Google Sketchup. If you are not willing to afford Sketchup Pro, you have to find another way to export a textured OBJ model.

One good exporter is available in the Kerkythea renderer project [1]. You need SU2KT~3.17 or better, and KT2OBJ~1.1.0 or better. Deselect any selection, then export your model to the Kerkythea XML format with the following settings:

Geometry:     Yes
Lights:       Yes
Clay:          No
Photomatched: Yes
DefaultUVs:    No
Instanced:     No


(Or, with selection enabled, make sure settings are No-Yes-Yes-No-Yes-No-No.) You do not have to launch Kerkythea unless you want to create nice renderings of your model.

Then, use the KT2OBJ converter to create an OBJ. You can delete the XML after the conversion. Note that some texture coordinates may not be exported correctly. The setting Photomatched:Yes seems now to have corrected this issue, esp. with distorted/manually shifted textures.

Another free OBJ exporter has been made available by TIG: OBJexporter.rb, available from [2]. This is the only OBJ exporter capable of handling large TIN landscapes (>450.000 triangles). As of version 2.6 it seems to be the best OBJ exporter available for Sketchup.

This exporter swaps Y/Z coordinates, but you can add a key to the config file to correct swapped axes, see below. Other exporters may also provide coordinates in any order of X, Y, Z -- all those can be properly configured.

### Notes on OBJ file format limitations

The OBJ format supported is only a subset of the full OBJ format: Only (optionally textured) triangle meshes are supported, i.e., only lines containing statements: mtllib, usemtl, v, vn, vt, f (with three elements only!), g, o. Negative vertex numbers (i.e., a specification of relative positions) are not supported.

A further recommendation for correct illumination is that all vertices should have vertex normals. Sketchup models exported with the Kerkythea or TIG plugins should have correct normals. If your model does not provide them, default normals can be reconstructed from the triangle edges, resulting in a faceted look.

If possible, the model should be triangulated, but the current loader may also work with non-triangle geometry. The correct use of objects (o) and groups (g) will improve performance: it is best if you pre-combine all objects that use the same material into a single one. The loader will try to optimize it anyways if this is not the case, but can do this only partly (to combine 2 objects with the same material into 1, it requires them to follow directly after each other in the OBJ). A simple guide to use Blender for this task follows:

• Import from Wavefront (.obj) - you may need to change the forward/up axes for correct orientation, try -Y for forward and Z for up
• Select an object which has a shared material
• Press Shift+L and select By Material
• Select Join in the left (main) tool window
• Repeat for other objects that have shared materials
• Export the .obj, making sure to select the same forward/up axes as in the import, also make sure Write Normals, Write Materials and Include UVs are checked

For transparent objects (with a d or Tr value, alpha testing does NOT need this), this recommendation does NOT hold: for optimal results, each separate transparent object should be exported as a separate OBJ object. This is because they need to be sorted during rendering to achieve correct transparency. If the objects are combined already, you can separate them using Blender:

• Import .obj (see above)
• Select the combined transparent object
• Enter Edit mode with TAB and make sure everything is selected (press A if not)
• Press P and select By loose parts, this should separate the object into its unconnected regions
• Export .obj (see above), also check Objects as OBJ Objects

The MTL file specified by mtllib contains the material parameters. The minimum that should be specified is either map_Kd or a Kd line specifying color values used for the respective faces. But there are other options in MTL files, and the supported parameters and defaults are listed in the following Table.

Parameter      Default           Range          Meaning
Ka            set to Kd values  0...1 each  R/G/B Ambient color
Kd            0.8 0.8 0.8       0...1 each  R/G/B Diffuse color
Ke            0.0 0.0 0.0       0...1 each  R/G/B Emissive color
Ks            0.0 0.0 0.0       0...1 each  R/G/B Specular color
Ns            8.0               0...\infty  shinyness
d or Tr       1.0               0...1       opacity
bAlphatest    0                 0 or 1      perform alpha test
bBackface     0                 0 or 1      render backface
map_Kd         (none)           filename    texture map to be mixed with Ka, Kd
map_Ke         (none)           filename    texture map to be mixed with Ke
map_bump       (none)           filename    normal map for surface roughness


If no ambient color is specified, the diffuse color values are taken for the ambient color. An optional emissive term Ke can be added, which is modulated to only be visible during nighttime. This also requires the landscape's self-illumination layer to be enabled. It allows to model self-illuminating objects such as street lights, billboards, windows etc. It can optionally also be modulated by the emissive texture map_Ke.

If a value for Ks is specified, specularity is evaluated using the Phong reflection model [3] with Ns as the exponential shininess constant. Larger shininess means smaller specular highlights (more metal-like appearance). Specularity is not modulated by the texture maps.

If a value for d or Tr exists, alpha blending is enabled for this material. This simulates transparency effects. Transparency can be further controlled using the alpha channel of the map_Kd texture.

A simpler and usually more performant way to achieve simple cutout transparency effects is alpha-testing, by setting bAlphatest to 1. This simply discards all pixels of the model where the alpha value of the map_Kd is below the transparency_threshold value from scenery3d.ini, making holes in the model. This also produces better shadows for such objects. If required, alpha testing can be combined with real blending-based transparency.

Sometimes, exported objects only have a single side (paper wall), and may appear only visible from one side when looked at in Scenery3d. This is caused by an optimization called back-face culling [4], which skips drawing the back sides of objects because they are usually not visible anyway. If possible, avoid such thin geometry, this will also produce better shadows on the object. As a workaround, you can also set bBackface to 1 to disable back-face culling for this material.

The optional map_bump enables the use of tangent-space normal maps [5], which provides a dramatic improvement in surface detail under illumination.

### Configuring OBJ for Scenery3d

The walkaround in your scene can use a ground level (piece of terrain) on which the observer can walk. The observer eye will always stay eye height above ground. Currently, there is no collision detection with walls implemented, so you can easily walk through walls, or jump on high towers, if their platform or roof is exported in the ground layer. If your model has no explicit ground layer, walk will be on the highest surface of the scenery layer. If you use the special name NULL as ground layer, walk will be above zero_ground_height level.

Technically, if your model has cavities or doors, you should export your model twice. Once, just the ground plane, i.e. where you will walk. Of course, for a temple or other building, this includes its socket above soil, and any steps, but pillars should not be included. This plane is required to compute eye position above ground. Note that it is not possible to walk in several floors of a building, or in a multi-plane staircase. You may have to export several ground planes and configure several scenery directories for those rare cases. For optimal performance, the ground model should consist of as few triangles as you can tolerate.

The second export includes all visible model parts, and will be used for rendering. Of course, this requires the ground plane again, but also all building elements, walls, roofs, etc.

If you have not done so by yourself, it is recommended to separate ground and buildings into Sketchup layers (or similar concepts in whichever editor you are using) in order to easily switch the model to the right state prior to exporting.

Filename recommendations:

<Temple>.skp        Name of a Sketchup Model file.
(The "<>" brackets signal "use your own name here!")
The SKP file is not used by Scenery3d, but you may want
to leave it in the folder for later improvements.
<Temple>.obj        Model in OBJ format.
<Temple>_ground.obj Ground layer, if different from Model file.


OBJ export may also create folders TX_<Temple> and TX_<Temple>_ground. You can delete the TX_<Temple>_ground folder, <Temple>_ground.obj is just used to compute vertical height.

Stellarium uses a directory to store additional data per-user. On Windows, this defaults to C:\Documents and Settings\<username>\Application Data\Stellarium, but you can use another directory by using the command-line argument --user-dir <USERDATA>. We will refer to this directory. Put the OBJ, MTL and TX directories into a directory, <USERDATA>/Stellarium/scenery3d/<Temple>, and add a text file scenery3d.ini (This name is mandatory!) with content described as follows.

[model]
name=<Temple>                Unique ID within all models in scenery3d directory.
Recommendation: use directory name.
landscape=<landscapename>    Name of an available Stellarium landscape.


This is required if the landscape file includes geographical coordinates and your model does not: First, the location coordinates of the landscape.ini file are used, then location coordinates given here. The landscape also provides the background image of your scenery. - If you want a zero-height (mathematical) horizon, use the provided landscape called Zero Horizon.

scenery=<Temple>.obj         The complete model, including visible ground.
ground=<Temple>_ground.obj   Optional: separate ground plane. (NULL for zero altitude.)
description=<Description>    A basic scene description (including HTML tags)


The scenery3d.ini may contain a simple scene description, but it is recommended to use the localizable description format: in the scene's directory (which contains scenery3d.ini) create files in the format description.<lang_code>.utf8 which can contain arbitrary UTF-8-encoded HTML content. <lang_code> is the ISO 639 language code.

author=<Your Name yourname@yourplace.com>

obj_order=XYZ      | Use this if you have used an exporter which swaps Y/Z coordinates.
| Defaults to XYZ, other options: XZY, YZX, YXZ, ZXY, ZYX
camNearZ=0.3       This defines the distance of the camera near plane, default 0.3.
Everything closer than this value to the camera can not be
displayed. Must be larger than zero. It may seem tempting
to set this very small, but this will lead to accuracy issues.
Recommendation is not to go under 0.1
camFarZ=10000      Defines the maximal viewing distance, default 10000.
value from camFarZ is used here. If this is set to a smaller
value, this may increase the quality of the shadows that are
still visible.
better shadows up close, try setting this to higher values.
The default is calculated using a heuristic that incorporates
scene size.


The general section defines some further import/rendering options.

[general]
transparency_threshold=0.5   Defines the alpha threshold for alpha-testing,
as described in section 4.1. Default: 0.5
scenery_generate_normals=0   Boolean, if true normals are recalculated by the
plugin, instead of imported. Default: false
ground_generate_normals=0    Boolean, same as above, for ground model. Default: false.


Optional location section to specify geographic longitude λ, latitude φ, and altitude. Required if coord/convergence_angle=from_grid, else location is inherited from landscape.

[location]
planet = Earth
latitude = +48d31'30.4"      ; Required if coord/convergence_angle=from_grid
longitude = +16d12'25.5"     ; "--"
altitude =from_model|<int>   ;


altitude (for astronomical computations) can be computed from the model: if from_model, it is computed as (z_min+z_max)/2+orig_H, i.e. from the model bounding box centre height.

display_fog = 0
atmospheric_extinction_coefficient = 0.2
atmospheric_temperature = 10.0
atmospheric_pressure = -1
light_pollution = 1


Entries in the coord section are again optional, default to zero when not specified, but are required if you want to display meaningful eye coordinates in your survey (world) coordinate system, like UTM or Gauss-Krüger.

[coord]
grid_name=<string>


Name of grid coordinates, e.g. UTM 33 U (WGS 84), Gauss-Krüger M34 or Relative to Center. This name is only displayed, there is no evaluation of its contents.

orig_E=<double> | (Easting)  East-West-distance to zone central meridian
orig_N=<double> | (Northing) North distance from Equator
orig_H=<double> | (Height)   Altitude above Mean Sea Level of model origin


These entries describe the offset, in metres, of the model coordinates relative to coordinates in a geographic grid, like Gauss-Krüger. If you have your model vertices specified in grid coordinates, do not specify orig_... data, but please definitely add start_... data, below.

Note that using grid coordinates without offset for the vertices is usually a bad idea for real-world applications like surveyed sites in UTM coordinates. Coordinate values are often very large numbers (ranging into millions of meters from equator and many thousands from the zone meridian). If you want to assign millimetre values to model vertices, you will hit numerical problems with the usual single-precision floating point arithmetic. Therefore we can specify this offset which is only necessary for coordinate display.

convergence_angle=from_grid|<double>
grid_meridian=<double>|+<int>d<int>'<float>"


Typically, digital elevation models and building structures built on those are survey-grid aligned, so true geographical north will not coincide with grid north, the difference is known as meridian convergence: γ(λ, &varphi;)=arctan(tan(λ-λo) sinφ)

This amount can be given in convergence_angle (degrees), so that your model will be rotated clockwise by this amount around the vertical axis to be aligned with True North [6] Note that Sketchup's georeferencing dictionary provides a NorthAngle entry, which is 360-convergence_angle.

grid_meridian Central meridian λo of grid zone, e.g. for UTM or Gauss-Krüger, is only required to compute convergence angle if convergence_angle="from_grid"

zero_ground_height=<double>


height of terrain outside <Temple>_ground.OBJ, or if ground=NULL. Allows smooth approach from outside. This value is relative to the model origin, or typically close to zero, i.e., use a Z value in model coordinates, not world coordinates! (If you want the terrain height surrounding your model to be orig_H, use 0, not the correct mean height above sea level!) Defaults to minimum of height of ground level (or model, resp.) bounding box.

start_E=<double>
start_N=<double>
start_H=<double>     /* only meaningful if ground==NULL, else H is derived from ground */
start_Eye=<double>   /* default: 1.65m */
start_az_alt_fov=<az_deg>,<alt_deg>,<fov_deg> /* initial view direction and field of view.*/


start_... defines the view position to be set after loading the scenery. Defaults to center of model boundingbox.

It is advisable to use the grid coordinates of the location of the panoramic photo ("landscape") as start_... coordinates, or the correct coordinates and some carefully selected start_az_alt_fov in case of certain view corridors (temple axes, ...).

## Predefined views

You can also distribute some predefined views with your model in a viewpoints.ini file. See the provided Sterngarten scene for an example. These entries are not editable by the user through the interface. The user can always save his own views, they will be saved into the file userviews.ini in the user's Stellarium user directory, and are editable.

[StoredViews]
size=<int>              Defines how many entries are in this file.
Prefix each entry with its index!
1/label=<string>        The name of this entry
1/description=<string>  A description of this entry (can include HTML)
1/position=<x,y,z,h>    The x,y,z grid coordinates (like orig_* or start_*
in scenery3d.ini) + the current eye height
1/view_fov=<az_deg,alt_deg,fov_deg>  The view direction + FOV
(like start_az_alt_fov in scenery3d.ini)
; an example for the second entry (note the 2 at the beginning of each line!)
2/label       = Signs
2/description = Two signs that describe the Sterngarten
2/position    = 593155.2421280354,5333348.6304404084,325.7295809038,0.8805893660
2/view_fov    = 84.315399,-8.187078,83.000000


## Authors and Acknowledgements

Scenery3d was conceived by Georg Zotti for the ASTROSIM project. A first prototype was implemented originally in 2010/2011 by Simon Parzer and Peter Neubauer as student work supervised by Michael Wimmer (TU Wien). Models for accuracy tests (Sterngarten, Testscene), and later improvements in integration, user interaction, .ini option handling, OBJ/MTL loader bugfixes and georeference testing by Georg Zotti.

Andrei Borza in 2011/12 further improved rendering quality (shadow mapping, normal mapping) and speed.

In 2014/15, Florian Schaukowitsch adapted the code to work with Qt5 and the Stellarium 0.13 codebase, replaced the renderer with a more efficient, fully shader-based system, implemented various performance, quality and usability enhancements, and did some code cleanup. Both Andrei and Florian were again supervised by Michael Wimmer.

This work has been originally created during the ASTROSIM project [7] supported 2008-2012 by the Austrian Science Fund (FWF) under grant number P~21208-G19.

## How you can help

We are welcome bug reports, feature requests and feedback through the usual channels (trackers, forums and so on).