Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'io_convert_image_to_mesh_img/ui/importer.py')
-rw-r--r--io_convert_image_to_mesh_img/ui/importer.py177
1 files changed, 177 insertions, 0 deletions
diff --git a/io_convert_image_to_mesh_img/ui/importer.py b/io_convert_image_to_mesh_img/ui/importer.py
new file mode 100644
index 00000000..981e49c2
--- /dev/null
+++ b/io_convert_image_to_mesh_img/ui/importer.py
@@ -0,0 +1,177 @@
+# This file is a part of the HiRISE DTM Importer for Blender
+#
+# Copyright (C) 2017 Arizona Board of Regents on behalf of the Planetary Image
+# Research Laboratory, Lunar and Planetary Laboratory at the University of
+# Arizona.
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""Blender menu importer for loading a DTM"""
+
+import bpy
+import bpy.props
+from bpy_extras.io_utils import ImportHelper
+
+from ..mesh.terrain import BTerrain
+from ..mesh.dtm import DTM
+
+
+class ImportHiRISETerrain(bpy.types.Operator, ImportHelper):
+ """DTM Import Helper"""
+ bl_idname = "import.pds_dtm"
+ bl_label = "Import HiRISE Terrain Model"
+ bl_options = {'UNDO'}
+ filename_ext = ".img"
+ filter_glob = bpy.props.StringProperty(
+ options={'HIDDEN'},
+ default="*.img"
+ )
+
+ # Allow the user to specify a resolution factor for loading the
+ # terrain data at. This is useful because it allows the user to stage
+ # a scene with a low resolution terrain map, apply textures, modifiers,
+ # etc. and then increase the resolution to prepare for final rendering.
+ #
+ # Displaying this value as a percentage (0, 100] is an intuitive way
+ # for users to grasp what this value does. The DTM importer, however,
+ # wants to recieve a value between (0, 1]. This is obviously a
+ # straightforward conversion:
+ #
+ # f(x) = x / 100
+ #
+ # But this conversion should happen here, in the terrain panel, rather
+ # than in the DTM importing utility itself. We can't pass get/set
+ # functions to the property itself because they result in a recursion
+ # error. Instead, we use another, hidden, property to store the scaled
+ # resolution.
+ dtm_resolution = bpy.props.FloatProperty(
+ subtype="PERCENTAGE",
+ description=(
+ "Percentage scale for terrain model resolution. 100\% loads the "
+ "model at full resolution (i.e. one vertex for each post in the "
+ "original terrain model) and is *MEMORY INTENSIVE*. Downsampling "
+ "uses Nearest Neighbors. You will be able to increase the "
+ "resolution of your mesh later, and still maintain all textures, "
+ "transformations, modifiers, etc., so best practice is to start "
+ "small. The downsampling algorithm may need to alter the "
+ "resolution you specify here to ensure it results in a whole "
+ "number of vertices. If it needs to alter the value you specify, "
+ "you are guaranteed that it will shrink it (i.e. decrease the "
+ "DTM resolution."
+ ),
+ name="Terrain Model Resolution",
+ min=1.0, max=100.0, default=10.0
+ )
+ scaled_dtm_resolution = bpy.props.FloatProperty(
+ options={'HIDDEN'},
+ name="Scaled Terrain Model Resolution",
+ get=(lambda self: self.dtm_resolution / 100)
+ )
+
+ # HiRISE DTMs are huge, but it can be nice to load them in at scale. Here,
+ # we present the user with the option of setting up the Blender viewport
+ # to avoid a couple of common pitfalls encountered when working with such
+ # a large mesh.
+ #
+ # 1. The Blender viewport has a default clipping distance of 1km. HiRISE
+ # DTMs are often many kilometers in each direction. If this setting is
+ # not changed, an unsuspecting user may only see part (or even nothing
+ # at all) of the terrain. This option (true, by default) instructs
+ # Blender to change the clipping distance to something appropriate for
+ # the DTM, and scales the grid floor to have gridlines 1km apart,
+ # instead of 1m apart.
+ should_setup_viewport = bpy.props.BoolProperty(
+ description=(
+ "Set up the Blender screen to try and avoid clipping the DTM "
+ "and to make the grid floor larger. *WARNING* This will change "
+ "clipping distances and the Blender grid floor, and will fit the "
+ "DTM in the viewport."
+ ),
+ name="Setup Blender Scene", default=True
+ )
+ # 2. Blender's default units are dimensionless. This option instructs
+ # Blender to change its unit's dimension to meters.
+ should_setup_units = bpy.props.BoolProperty(
+ description=(
+ "Set the Blender scene to use meters as its unit."
+ ),
+ name="Set Blender Units to Meters", default=True
+ )
+
+ def execute(self, context):
+ """Runs when the "Import HiRISE Terrain Model" button is pressed"""
+ filepath = bpy.path.ensure_ext(self.filepath, self.filename_ext)
+ # Create a BTerrain from the DTM
+ dtm = DTM(filepath, self.scaled_dtm_resolution)
+ BTerrain.new(dtm)
+
+ # Set up the Blender UI
+ if self.should_setup_units:
+ self._setup_units(context)
+ if self.should_setup_viewport:
+ self._setup_viewport(context)
+
+ return {"FINISHED"}
+
+ def _setup_units(self, context):
+ """Sets up the Blender scene for viewing the DTM"""
+ scene = bpy.context.scene
+
+ # Set correct units
+ scene.unit_settings.system = 'METRIC'
+ scene.unit_settings.scale_length = 1.0
+
+ return {'FINISHED'}
+
+ def _setup_viewport(self, context):
+ """Sets up the Blender screen to make viewing the DTM easier"""
+ screen = bpy.context.screen
+
+ # Fetch the 3D_VIEW Area
+ for area in screen.areas:
+ if area.type == 'VIEW_3D':
+ space = area.spaces[0]
+ # Adjust 3D View Properties
+ # TODO: Can these be populated more intelligently?
+ space.clip_end = 100000
+ space.grid_scale = 1000
+ space.grid_lines = 50
+
+ # Fly to a nice view of the DTM
+ self._view_dtm(context)
+
+ return {'FINISHED'}
+
+ def _view_dtm(self, context):
+ """Sets up the Blender screen to make viewing the DTM easier"""
+ screen = bpy.context.screen
+
+ # Fetch the 3D_VIEW Area
+ for area in screen.areas:
+ if area.type == 'VIEW_3D':
+ # Move the camera around in the viewport. This requires
+ # a context override.
+ for region in area.regions:
+ if region.type == 'WINDOW':
+ override = {
+ 'area': area,
+ 'region': region,
+ 'edit_object': bpy.context.edit_object
+ }
+ # Center View on DTM (SHORTCUT: '.')
+ bpy.ops.view3d.view_selected(override)
+ # Move to 'TOP' viewport (SHORTCUT: NUMPAD7)
+ bpy.ops.view3d.viewnumpad(override, type='TOP')
+
+ return {'FINISHED'}