1 # This file is a part of the HiRISE DTM Importer for Blender
3 # Copyright (C) 2017 Arizona Board of Regents on behalf of the Planetary Image
4 # Research Laboratory, Lunar and Planetary Laboratory at the University of
7 # This program is free software: you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by the Free
9 # Software Foundation, either version 3 of the License, or (at your option)
12 # This program is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 # You should have received a copy of the GNU General Public License along
18 # with this program. If not, see <http://www.gnu.org/licenses/>.
20 """Blender menu importer for loading a DTM"""
23 from bpy
.props
import (
28 from bpy_extras
.io_utils
import ImportHelper
30 from ..mesh
.terrain
import BTerrain
31 from ..mesh
.dtm
import DTM
34 class ImportHiRISETerrain(bpy
.types
.Operator
, ImportHelper
):
35 """DTM Import Helper"""
36 bl_idname
= "import_mesh.pds_dtm"
37 bl_label
= "Import HiRISE Terrain Model"
41 filter_glob
= StringProperty(
46 # Allow the user to specify a resolution factor for loading the
47 # terrain data at. This is useful because it allows the user to stage
48 # a scene with a low resolution terrain map, apply textures, modifiers,
49 # etc. and then increase the resolution to prepare for final rendering.
51 # Displaying this value as a percentage (0, 100] is an intuitive way
52 # for users to grasp what this value does. The DTM importer, however,
53 # wants to receive a value between (0, 1]. This is obviously a
54 # straightforward conversion:
58 # But this conversion should happen here, in the terrain panel, rather
59 # than in the DTM importing utility itself. We can't pass get/set
60 # functions to the property itself because they result in a recursion
61 # error. Instead, we use another, hidden, property to store the scaled
63 dtm_resolution
= FloatProperty(
66 "Percentage scale for terrain model resolution. 100\% loads the "
67 "model at full resolution (i.e. one vertex for each post in the "
68 "original terrain model) and is *MEMORY INTENSIVE*. Downsampling "
69 "uses Nearest Neighbors. You will be able to increase the "
70 "resolution of your mesh later, and still maintain all textures, "
71 "transformations, modifiers, etc., so best practice is to start "
72 "small. The downsampling algorithm may need to alter the "
73 "resolution you specify here to ensure it results in a whole "
74 "number of vertices. If it needs to alter the value you specify, "
75 "you are guaranteed that it will shrink it (i.e. decrease the "
78 name
="Terrain Model Resolution",
79 min=1.0, max=100.0, default
=10.0
81 scaled_dtm_resolution
= FloatProperty(
83 name
="Scaled Terrain Model Resolution",
84 get
=(lambda self
: self
.dtm_resolution
/ 100)
87 # HiRISE DTMs are huge, but it can be nice to load them in at scale. Here,
88 # we present the user with the option of setting up the Blender viewport
89 # to avoid a couple of common pitfalls encountered when working with such
92 # 1. The Blender viewport has a default clipping distance of 1km. HiRISE
93 # DTMs are often many kilometers in each direction. If this setting is
94 # not changed, an unsuspecting user may only see part (or even nothing
95 # at all) of the terrain. This option (true, by default) instructs
96 # Blender to change the clipping distance to something appropriate for
97 # the DTM, and scales the grid floor to have gridlines 1km apart,
98 # instead of 1m apart.
99 should_setup_viewport
= BoolProperty(
101 "Set up the Blender screen to try and avoid clipping the DTM "
102 "and to make the grid floor larger. *WARNING* This will change "
103 "clipping distances and the Blender grid floor, and will fit the "
104 "DTM in the viewport"
106 name
="Setup Blender Scene", default
=True
108 # 2. Blender's default units are dimensionless. This option instructs
109 # Blender to change its unit's dimension to meters.
110 should_setup_units
= BoolProperty(
112 "Set the Blender scene to use meters as its unit"
114 name
="Set Blender Units to Meters", default
=True
117 def execute(self
, context
):
118 """Runs when the "Import HiRISE Terrain Model" button is pressed"""
119 filepath
= bpy
.path
.ensure_ext(self
.filepath
, self
.filename_ext
)
120 # Create a BTerrain from the DTM
121 dtm
= DTM(filepath
, self
.scaled_dtm_resolution
)
124 # Set up the Blender UI
125 if self
.should_setup_units
:
126 self
._setup
_units
(context
)
127 if self
.should_setup_viewport
:
128 self
._setup
_viewport
(context
)
132 def _setup_units(self
, context
):
133 """Sets up the Blender scene for viewing the DTM"""
134 scene
= bpy
.context
.scene
137 scene
.unit_settings
.system
= 'METRIC'
138 scene
.unit_settings
.scale_length
= 1.0
142 def _setup_viewport(self
, context
):
143 """Sets up the Blender screen to make viewing the DTM easier"""
144 screen
= bpy
.context
.screen
146 # Fetch the 3D_VIEW Area
147 for area
in screen
.areas
:
148 if area
.type == 'VIEW_3D':
149 space
= area
.spaces
[0]
150 # Adjust 3D View Properties
151 # TODO: Can these be populated more intelligently?
152 space
.clip_end
= 100000
153 space
.grid_scale
= 1000
154 space
.grid_lines
= 50
156 # Fly to a nice view of the DTM
157 self
._view
_dtm
(context
)
161 def _view_dtm(self
, context
):
162 """Sets up the Blender screen to make viewing the DTM easier"""
163 screen
= bpy
.context
.screen
165 # Fetch the 3D_VIEW Area
166 for area
in screen
.areas
:
167 if area
.type == 'VIEW_3D':
168 # Move the camera around in the viewport. This requires
169 # a context override.
170 for region
in area
.regions
:
171 if region
.type == 'WINDOW':
175 'edit_object': bpy
.context
.edit_object
177 # Center View on DTM (SHORTCUT: '.')
178 bpy
.ops
.view3d
.view_selected(override
)
179 # Move to 'TOP' viewport (SHORTCUT: NUMPAD7)
180 bpy
.ops
.view3d
.viewnumpad(override
, type='TOP')