Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# 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 panel for managing a DTM *after* it's been imported"""
import bpy
from ..mesh.terrain import BTerrain
from ..mesh.dtm import DTM
class TerrainPanel(bpy.types.Panel):
"""Creates a Panel in the Object properites window for terrain objects"""
bl_label = "Terrain Model"
bl_idname = "OBJECT_PT_terrain"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
# Allow the user to specify a new resolution factor for reloading 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.
bpy.types.Object.dtm_resolution = bpy.props.FloatProperty(
subtype="PERCENTAGE",
name="New Resolution",
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. 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. "
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
),
min=1.0, max=100.0, default=10.0
)
bpy.types.Object.scaled_dtm_resolution = bpy.props.FloatProperty(
options={'HIDDEN'},
name="Scaled Terrain Model Resolution",
get=(lambda self: self.dtm_resolution / 100.0)
)
@classmethod
def poll(cls, context):
return context.object.get("IS_TERRAIN", False)
def draw(self, context):
obj = context.active_object
layout = self.layout
# User Controls
layout.prop(obj, 'dtm_resolution')
layout.operator("terrain.reload")
# Metadata
self.draw_metadata_panel(context)
def draw_metadata_panel(self, context):
"""Display some metadata about the DTM"""
obj = context.active_object
layout = self.layout
metadata_panel = layout.box()
dtm_resolution = metadata_panel.row()
dtm_resolution.label('Current Resolution: ')
dtm_resolution.label('{:9,.2%}'.format(
obj['DTM_RESOLUTION']
))
mesh_scale = metadata_panel.row()
mesh_scale.label('Current Scale: ')
mesh_scale.label('{:9,.2f} m/post'.format(
obj['MESH_SCALE']
))
dtm_scale = metadata_panel.row()
dtm_scale.label('Original Scale: ')
dtm_scale.label('{:9,.2f} m/post'.format(
obj['MAP_SCALE']
))
return {'FINISHED'}
class ReloadTerrain(bpy.types.Operator):
"""Button for reloading the terrain mesh at a new resolution"""
bl_idname = "terrain.reload"
bl_label = "Reload Terrain"
def execute(self, context):
# Reload the terrain
obj = context.object
path = obj['PATH']
scaled_dtm_resolution = obj.scaled_dtm_resolution
# Reload BTerrain with new DTM
dtm = DTM(path, scaled_dtm_resolution)
BTerrain.reload(obj, dtm)
return {"FINISHED"}