Bsurfaces: Use context temp override to avoid deprecation #104486
@ -931,6 +931,26 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
|
||||
me.edges.foreach_get("vertices", t_ev)
|
||||
me.loops.foreach_get("edge_index", t_lei)
|
||||
|
||||
# Polygons might not be in the same order as loops. To export per-loop and per-polygon data in a matching order,
|
||||
# one must be set into the order of the other. Since there are fewer polygons than loops and there are usually
|
||||
# more geometry layers exported that are per-loop than per-polygon, it's more efficient to re-order polygons and
|
||||
# per-polygon data.
|
||||
perm_polygons_to_loop_order = None
|
||||
# t_ls indicates the ordering of polygons compared to loops. When t_ls is sorted, polygons and loops are in the same
|
||||
# order. Since each loop must be assigned to exactly one polygon for the mesh to be valid, every value in t_ls must
|
||||
# be unique, so t_ls will be monotonically increasing when sorted.
|
||||
# t_ls is expected to be in the same order as loops in most cases since exiting Edit mode will sort t_ls, so do an
|
||||
# initial check for any element being smaller than the previous element to determine if sorting is required.
|
||||
sort_polygon_data = np.any(t_ls[1:] < t_ls[:-1])
|
||||
if sort_polygon_data:
|
||||
# t_ls is not sorted, so get the indices that would sort t_ls using argsort, these will be re-used to sort
|
||||
# per-polygon data.
|
||||
# Using 'stable' for radix sort, which performs much better with partially ordered data and slightly worse with
|
||||
# completely random data, compared to the default of 'quicksort' for introsort.
|
||||
perm_polygons_to_loop_order = np.argsort(t_ls, kind='stable')
|
||||
# Sort t_ls into the same order as loops.
|
||||
t_ls = t_ls[perm_polygons_to_loop_order]
|
||||
|
||||
# Add "fake" faces for loose edges. Each "fake" face consists of two loops creating a new 2-sided polygon.
|
||||
if scene_data.settings.use_mesh_edges:
|
||||
bl_edge_is_loose_dtype = bool
|
||||
@ -1031,6 +1051,8 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
|
||||
if smooth_type == 'FACE':
|
||||
t_ps = np.empty(len(me.polygons), dtype=poly_use_smooth_dtype)
|
||||
me.polygons.foreach_get("use_smooth", t_ps)
|
||||
if sort_polygon_data:
|
||||
t_ps = t_ps[perm_polygons_to_loop_order]
|
||||
_map = b"ByPolygon"
|
||||
else: # EDGE
|
||||
_map = b"ByEdge"
|
||||
@ -1049,14 +1071,17 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
|
||||
# Get the 'use_smooth' attribute of all polygons.
|
||||
p_use_smooth_mask = np.empty(mesh_poly_nbr, dtype=poly_use_smooth_dtype)
|
||||
me.polygons.foreach_get('use_smooth', p_use_smooth_mask)
|
||||
if sort_polygon_data:
|
||||
p_use_smooth_mask = p_use_smooth_mask[perm_polygons_to_loop_order]
|
||||
# Invert to get all flat shaded polygons.
|
||||
p_flat_mask = np.invert(p_use_smooth_mask, out=p_use_smooth_mask)
|
||||
# Convert flat shaded polygons to flat shaded loops by repeating each element by the number of sides of
|
||||
# that polygon.
|
||||
# Polygon sides can be calculated from the element-wise difference of loop starts appended by the number
|
||||
# of loops. Alternatively, polygon sides can be retrieved directly from the 'loop_total' attribute of
|
||||
# polygons, but since we already have t_ls, it tends to be quicker to calculate from t_ls when above
|
||||
# around 10_000 polygons.
|
||||
# Polygon sides can be calculated from the element-wise difference of sorted loop starts appended by the
|
||||
# number of loops. Alternatively, polygon sides can be retrieved directly from the 'loop_total'
|
||||
# attribute of polygons, but that might need to be sorted, and we already have t_ls which is sorted loop
|
||||
# starts. It tends to be quicker to calculate from t_ls when above around 10_000 polygons even when the
|
||||
# 'loop_total' array wouldn't need sorting.
|
||||
polygon_sides = np.diff(mesh_t_ls_view, append=mesh_loop_nbr)
|
||||
p_flat_loop_mask = np.repeat(p_flat_mask, polygon_sides)
|
||||
# Convert flat shaded loops to flat shaded (sharp) edge indices.
|
||||
@ -1417,6 +1442,8 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
|
||||
fbx_pm_dtype = np.int32
|
||||
t_pm = np.empty(len(me.polygons), dtype=bl_pm_dtype)
|
||||
me.polygons.foreach_get("material_index", t_pm)
|
||||
if sort_polygon_data:
|
||||
t_pm = t_pm[perm_polygons_to_loop_order]
|
||||
|
||||
# We have to validate mat indices, and map them to FBX indices.
|
||||
# Note a mat might not be in me_fbxmaterials_idx (e.g. node mats are ignored).
|
||||
@ -1447,6 +1474,7 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
|
||||
elem_data_single_string(lay_ma, b"MappingInformationType", b"AllSame")
|
||||
elem_data_single_string(lay_ma, b"ReferenceInformationType", b"IndexToDirect")
|
||||
elem_data_single_int32_array(lay_ma, b"Materials", [0])
|
||||
del perm_polygons_to_loop_order
|
||||
|
||||
# And the "layer TOC"...
|
||||
|
||||
|
@ -1304,6 +1304,8 @@ class NWMergeNodes(Operator, NWBase):
|
||||
if tree_type == 'GEOMETRY':
|
||||
if nodes_list is selected_math or nodes_list is selected_vector or nodes_list is selected_mix:
|
||||
node_type = 'ShaderNode'
|
||||
if mode == 'MIX':
|
||||
mode = 'ADD'
|
||||
else:
|
||||
node_type = 'GeometryNode'
|
||||
if merge_position == 'CENTER':
|
||||
|
@ -15,8 +15,8 @@
|
||||
|
||||
bl_info = {
|
||||
"name": "Sun Position",
|
||||
"author": "Michael Martin",
|
||||
"version": (3, 2, 2),
|
||||
"author": "Michael Martin, Damien Picard",
|
||||
"version": (3, 3, 0),
|
||||
"blender": (3, 0, 0),
|
||||
"location": "World > Sun Position",
|
||||
"description": "Show sun position with objects and/or sky texture",
|
||||
@ -63,6 +63,7 @@ def register():
|
||||
bpy.app.handlers.load_post.append(sun_scene_handler)
|
||||
bpy.app.translations.register(__name__, translations.translations_dict)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.app.translations.unregister(__name__)
|
||||
bpy.app.handlers.frame_change_post.remove(sun_calc.sun_handler)
|
||||
|
@ -23,10 +23,6 @@ else:
|
||||
shader_info.vertex_out(shader_interface)
|
||||
|
||||
shader_info.vertex_source(
|
||||
# uniform mat4 u_ViewProjectionMatrix;
|
||||
# in vec3 position;
|
||||
# flat out vec2 v_StartPos;
|
||||
# out vec4 v_VertPos;
|
||||
'''
|
||||
void main()
|
||||
{
|
||||
@ -40,11 +36,6 @@ else:
|
||||
|
||||
shader_info.fragment_out(0, 'VEC4', "FragColor")
|
||||
shader_info.fragment_source(
|
||||
# uniform vec4 u_Color;
|
||||
# uniform vec2 u_Resolution;
|
||||
# flat in vec2 v_StartPos;
|
||||
# in vec4 v_VertPos;
|
||||
# out vec4 FragColor;
|
||||
'''
|
||||
void main()
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ class Parser:
|
||||
# do matching
|
||||
m = re.match(pattern, text)
|
||||
|
||||
if m == None:
|
||||
if m is None:
|
||||
return None
|
||||
|
||||
# build tree recursively by parsing subgroups
|
||||
@ -59,7 +59,7 @@ class Parser:
|
||||
|
||||
for i in range(len(subpattern_names)):
|
||||
text_part = m.group(i + 1)
|
||||
if not text_part == None:
|
||||
if text_part is not None:
|
||||
subpattern = subpattern_names[i]
|
||||
tree[subpattern] = self.parse(subpattern, text_part)
|
||||
|
||||
@ -158,7 +158,8 @@ def parse_position(s):
|
||||
Tries to be as tolerant as possible with input. Returns None if parsing doesn't succeed. """
|
||||
|
||||
parse_tree = position_parser.parse("position", s)
|
||||
if parse_tree == None: return None
|
||||
if parse_tree is None:
|
||||
return None
|
||||
|
||||
lat_sign = +1.
|
||||
if parse_tree.get(
|
||||
|
@ -64,8 +64,7 @@ def draw_callback_px(self, context):
|
||||
coords = ((-0.5, -0.5), (0.5, -0.5), (0.5, 0.5), (-0.5, 0.5))
|
||||
uv_coords = ((0, 0), (1, 0), (1, 1), (0, 1))
|
||||
batch = batch_for_shader(shader, 'TRI_FAN',
|
||||
{"pos" : coords,
|
||||
"texCoord" : uv_coords})
|
||||
{"pos": coords, "texCoord": uv_coords})
|
||||
|
||||
with gpu.matrix.push_pop():
|
||||
gpu.matrix.translate(position)
|
||||
@ -79,7 +78,7 @@ def draw_callback_px(self, context):
|
||||
# Crosshair
|
||||
# vertical
|
||||
coords = ((self.mouse_position[0], bottom), (self.mouse_position[0], top))
|
||||
colors = ((1,)*4,)*2
|
||||
colors = ((1,) * 4,) * 2
|
||||
shader = gpu.shader.from_builtin('2D_FLAT_COLOR')
|
||||
batch = batch_for_shader(shader, 'LINES',
|
||||
{"pos": coords, "color": colors})
|
||||
@ -134,7 +133,9 @@ class SUNPOS_OT_ShowHdr(bpy.types.Operator):
|
||||
self.mouse_position = Vector((mouse_position_abs.x - self.area.x,
|
||||
mouse_position_abs.y - self.area.y))
|
||||
|
||||
self.selected_point = (self.mouse_position - self.offset - Vector((self.right, self.top))/2) / self.scale
|
||||
self.selected_point = (self.mouse_position
|
||||
- self.offset
|
||||
- Vector((self.right, self.top)) / 2) / self.scale
|
||||
u = self.selected_point.x / self.area.width + 0.5
|
||||
v = (self.selected_point.y) / (self.area.width / 2) + 0.5
|
||||
|
||||
@ -275,10 +276,13 @@ class SUNPOS_OT_ShowHdr(bpy.types.Operator):
|
||||
self.initial_elevation = context.scene.sun_pos_properties.hdr_elevation
|
||||
self.initial_azimuth = context.scene.sun_pos_properties.hdr_azimuth
|
||||
|
||||
context.workspace.status_text_set("Enter/LMB: confirm, Esc/RMB: cancel, MMB: pan, mouse wheel: zoom, Ctrl + mouse wheel: set exposure")
|
||||
context.workspace.status_text_set(
|
||||
"Enter/LMB: confirm, Esc/RMB: cancel,"
|
||||
" MMB: pan, mouse wheel: zoom, Ctrl + mouse wheel: set exposure")
|
||||
|
||||
self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px,
|
||||
(self, context), 'WINDOW', 'POST_PIXEL')
|
||||
self._handle = bpy.types.SpaceView3D.draw_handler_add(
|
||||
draw_callback_px, (self, context), 'WINDOW', 'POST_PIXEL'
|
||||
)
|
||||
context.window_manager.modal_handler_add(self)
|
||||
|
||||
return {'RUNNING_MODAL'}
|
||||
|
@ -5,7 +5,7 @@ from bpy.types import AddonPreferences, PropertyGroup
|
||||
from bpy.props import (StringProperty, EnumProperty, IntProperty,
|
||||
FloatProperty, BoolProperty, PointerProperty)
|
||||
|
||||
from .sun_calc import sun_update, parse_coordinates, surface_update, analemmas_update
|
||||
from .sun_calc import sun_update, parse_coordinates, surface_update, analemmas_update, sun
|
||||
from .draw import north_update
|
||||
|
||||
from math import pi
|
||||
@ -19,7 +19,7 @@ TODAY = datetime.today()
|
||||
|
||||
class SunPosProperties(PropertyGroup):
|
||||
usage_mode: EnumProperty(
|
||||
name="Usage mode",
|
||||
name="Usage Mode",
|
||||
description="Operate in normal mode or environment texture mode",
|
||||
items=(
|
||||
('NORMAL', "Normal", ""),
|
||||
@ -29,14 +29,14 @@ class SunPosProperties(PropertyGroup):
|
||||
update=sun_update)
|
||||
|
||||
use_daylight_savings: BoolProperty(
|
||||
name="Daylight savings",
|
||||
name="Daylight Savings",
|
||||
description="Daylight savings time adds 1 hour to standard time",
|
||||
default=False,
|
||||
update=sun_update)
|
||||
|
||||
use_refraction: BoolProperty(
|
||||
name="Use refraction",
|
||||
description="Show apparent sun position due to refraction",
|
||||
name="Use Refraction",
|
||||
description="Show apparent Sun position due to refraction",
|
||||
default=True,
|
||||
update=sun_update)
|
||||
|
||||
@ -81,6 +81,34 @@ class SunPosProperties(PropertyGroup):
|
||||
default=0.0,
|
||||
update=sun_update)
|
||||
|
||||
sunrise_time: FloatProperty(
|
||||
name="Sunrise Time",
|
||||
description="Time at which the Sun rises",
|
||||
soft_min=0.0, soft_max=24.0,
|
||||
default=0.0,
|
||||
get=lambda _: sun.sunrise.time)
|
||||
|
||||
sunset_time: FloatProperty(
|
||||
name="Sunset Time",
|
||||
description="Time at which the Sun sets",
|
||||
soft_min=0.0, soft_max=24.0,
|
||||
default=0.0,
|
||||
get=lambda _: sun.sunset.time)
|
||||
|
||||
sun_azimuth: FloatProperty(
|
||||
name="Sun Azimuth",
|
||||
description="Rotation angle of the Sun from the north direction",
|
||||
soft_min=-pi, soft_max=pi,
|
||||
default=0.0,
|
||||
get=lambda _: sun.azimuth)
|
||||
|
||||
sun_elevation: FloatProperty(
|
||||
name="Sunset Time",
|
||||
description="Elevation angle of the Sun",
|
||||
soft_min=-pi/2, soft_max=pi/2,
|
||||
default=0.0,
|
||||
get=lambda _: sun.elevation)
|
||||
|
||||
co_parser: StringProperty(
|
||||
name="Enter coordinates",
|
||||
description="Enter coordinates from an online map",
|
||||
|
@ -4,9 +4,10 @@ import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
import gpu
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
|
||||
from mathutils import Euler, Vector
|
||||
import math
|
||||
from math import degrees, radians, pi
|
||||
|
||||
from math import degrees, radians, pi, sin, cos, asin, acos, tan, floor
|
||||
import datetime
|
||||
from .geo import parse_position
|
||||
|
||||
@ -47,6 +48,7 @@ class SunInfo:
|
||||
sun_distance = 0.0
|
||||
use_daylight_savings = False
|
||||
|
||||
|
||||
sun = SunInfo()
|
||||
|
||||
|
||||
@ -78,8 +80,8 @@ def parse_coordinates(self, context):
|
||||
|
||||
def move_sun(context):
|
||||
"""
|
||||
Cycle through all the selected objects and call set_sun_location and
|
||||
set_sun_rotations to place them in the sky
|
||||
Cycle through all the selected objects and set their position and rotation
|
||||
in the sky.
|
||||
"""
|
||||
addon_prefs = context.preferences.addons[__package__].preferences
|
||||
sun_props = context.scene.sun_pos_properties
|
||||
@ -100,11 +102,11 @@ def move_sun(context):
|
||||
env_tex.texture_mapping.rotation.z = az
|
||||
|
||||
if sun_props.sun_object:
|
||||
theta = math.pi / 2 - sun_props.hdr_elevation
|
||||
theta = pi / 2 - sun_props.hdr_elevation
|
||||
phi = -sun_props.hdr_azimuth
|
||||
|
||||
obj = sun_props.sun_object
|
||||
obj.location = get_sun_vector(theta, phi) * sun_props.sun_distance
|
||||
obj.location = get_sun_vector(azimuth, elevation, north_offset) * sun_props.sun_distance
|
||||
|
||||
rotation_euler = Euler((sun_props.hdr_elevation - pi/2,
|
||||
0, -sun_props.hdr_azimuth))
|
||||
@ -118,15 +120,15 @@ def move_sun(context):
|
||||
if sun.use_daylight_savings:
|
||||
zone -= 1
|
||||
|
||||
north_offset = degrees(sun_props.north_offset)
|
||||
north_offset = sun_props.north_offset
|
||||
|
||||
if addon_prefs.show_rise_set:
|
||||
calc_sunrise_sunset(rise=True)
|
||||
calc_sunrise_sunset(rise=False)
|
||||
|
||||
az_north, theta, phi, azimuth, elevation = get_sun_coordinates(
|
||||
azimuth, elevation = get_sun_coordinates(
|
||||
local_time, sun_props.latitude, sun_props.longitude,
|
||||
north_offset, zone, sun_props.month, sun_props.day, sun_props.year,
|
||||
zone, sun_props.month, sun_props.day, sun_props.year,
|
||||
sun_props.sun_distance)
|
||||
sun.azimuth = azimuth
|
||||
sun.elevation = elevation
|
||||
@ -135,17 +137,16 @@ def move_sun(context):
|
||||
sky_node = bpy.context.scene.world.node_tree.nodes.get(sun_props.sky_texture)
|
||||
if sky_node is not None and sky_node.type == "TEX_SKY":
|
||||
sky_node.texture_mapping.rotation.z = 0.0
|
||||
sky_node.sun_direction = get_sun_vector(theta, phi)
|
||||
sky_node.sun_elevation = math.radians(elevation)
|
||||
sky_node.sun_rotation = math.radians(az_north)
|
||||
sky_node.sun_direction = get_sun_vector(azimuth, elevation, north_offset)
|
||||
sky_node.sun_elevation = elevation
|
||||
sky_node.sun_rotation = azimuth
|
||||
|
||||
# Sun object
|
||||
if (sun_props.sun_object is not None
|
||||
and sun_props.sun_object.name in context.view_layer.objects):
|
||||
obj = sun_props.sun_object
|
||||
obj.location = get_sun_vector(theta, phi) * sun_props.sun_distance
|
||||
rotation_euler = Euler((math.radians(elevation - 90), 0,
|
||||
math.radians(-az_north)))
|
||||
obj.location = get_sun_vector(azimuth, elevation, north_offset) * sun_props.sun_distance
|
||||
rotation_euler = Euler((elevation - pi/2, 0, -azimuth))
|
||||
set_sun_rotations(obj, rotation_euler)
|
||||
|
||||
# Sun collection
|
||||
@ -161,16 +162,14 @@ def move_sun(context):
|
||||
time_increment = sun_props.time_spread
|
||||
|
||||
for obj in sun_objects:
|
||||
az_north, theta, phi, azimuth, elevation = get_sun_coordinates(
|
||||
azimuth, elevation = get_sun_coordinates(
|
||||
local_time, sun_props.latitude,
|
||||
sun_props.longitude, north_offset, zone,
|
||||
sun_props.longitude, zone,
|
||||
sun_props.month, sun_props.day,
|
||||
sun_props.year, sun_props.sun_distance)
|
||||
obj.location = get_sun_vector(theta, phi) * sun_props.sun_distance
|
||||
obj.location = get_sun_vector(azimuth, elevation, north_offset) * sun_props.sun_distance
|
||||
local_time -= time_increment
|
||||
obj.rotation_euler = (
|
||||
(math.radians(elevation - 90), 0,
|
||||
math.radians(-az_north)))
|
||||
obj.rotation_euler = ((elevation - pi/2, 0, -azimuth))
|
||||
else:
|
||||
# Analemma
|
||||
day_increment = 365 / object_count
|
||||
@ -178,22 +177,21 @@ def move_sun(context):
|
||||
for obj in sun_objects:
|
||||
dt = (datetime.date(sun_props.year, 1, 1) +
|
||||
datetime.timedelta(day - 1))
|
||||
az_north, theta, phi, azimuth, elevation = get_sun_coordinates(
|
||||
azimuth, elevation = get_sun_coordinates(
|
||||
local_time, sun_props.latitude,
|
||||
sun_props.longitude, north_offset, zone,
|
||||
sun_props.longitude, zone,
|
||||
dt.month, dt.day, sun_props.year,
|
||||
sun_props.sun_distance)
|
||||
obj.location = get_sun_vector(theta, phi) * sun_props.sun_distance
|
||||
obj.location = get_sun_vector(azimuth, elevation, north_offset) * sun_props.sun_distance
|
||||
day -= day_increment
|
||||
obj.rotation_euler = (
|
||||
(math.radians(elevation - 90), 0,
|
||||
math.radians(-az_north)))
|
||||
obj.rotation_euler = (elevation - pi/2, 0, -azimuth)
|
||||
|
||||
|
||||
def day_of_year_to_month_day(year, day_of_year):
|
||||
dt = (datetime.date(year, 1, 1) + datetime.timedelta(day_of_year - 1))
|
||||
return dt.day, dt.month
|
||||
|
||||
|
||||
def month_day_to_day_of_year(year, month, day):
|
||||
dt = datetime.date(year, month, day)
|
||||
return dt.timetuple().tm_yday
|
||||
@ -275,7 +273,7 @@ def format_lat_long(lat_long, is_latitude):
|
||||
return hh + "° " + mm + "' " + ss + '"' + coord_tag
|
||||
|
||||
|
||||
def get_sun_coordinates(local_time, latitude, longitude, north_offset,
|
||||
def get_sun_coordinates(local_time, latitude, longitude,
|
||||
utc_zone, month, day, year, distance):
|
||||
"""
|
||||
Calculate the actual position of the sun based on input parameters.
|
||||
@ -319,31 +317,31 @@ def get_sun_coordinates(local_time, latitude, longitude, north_offset,
|
||||
if hour_angle < -180.0:
|
||||
hour_angle += 360.0
|
||||
|
||||
csz = (math.sin(latitude) * math.sin(solar_dec) +
|
||||
math.cos(latitude) * math.cos(solar_dec) *
|
||||
math.cos(radians(hour_angle)))
|
||||
csz = (sin(latitude) * sin(solar_dec) +
|
||||
cos(latitude) * cos(solar_dec) *
|
||||
cos(radians(hour_angle)))
|
||||
if csz > 1.0:
|
||||
csz = 1.0
|
||||
elif csz < -1.0:
|
||||
csz = -1.0
|
||||
|
||||
zenith = math.acos(csz)
|
||||
zenith = acos(csz)
|
||||
|
||||
az_denom = math.cos(latitude) * math.sin(zenith)
|
||||
az_denom = cos(latitude) * sin(zenith)
|
||||
|
||||
if abs(az_denom) > 0.001:
|
||||
az_rad = ((math.sin(latitude) *
|
||||
math.cos(zenith)) - math.sin(solar_dec)) / az_denom
|
||||
az_rad = ((sin(latitude) *
|
||||
cos(zenith)) - sin(solar_dec)) / az_denom
|
||||
if abs(az_rad) > 1.0:
|
||||
az_rad = -1.0 if (az_rad < 0.0) else 1.0
|
||||
azimuth = 180.0 - degrees(math.acos(az_rad))
|
||||
azimuth = pi - acos(az_rad)
|
||||
if hour_angle > 0.0:
|
||||
azimuth = -azimuth
|
||||
else:
|
||||
azimuth = 180.0 if (latitude > 0.0) else 0.0
|
||||
azimuth = pi if (latitude > 0.0) else 0.0
|
||||
|
||||
if azimuth < 0.0:
|
||||
azimuth = azimuth + 360.0
|
||||
azimuth += 2*pi
|
||||
|
||||
exoatm_elevation = 90.0 - degrees(zenith)
|
||||
|
||||
@ -351,43 +349,37 @@ def get_sun_coordinates(local_time, latitude, longitude, north_offset,
|
||||
if exoatm_elevation > 85.0:
|
||||
refraction_correction = 0.0
|
||||
else:
|
||||
te = math.tan(radians(exoatm_elevation))
|
||||
te = tan(radians(exoatm_elevation))
|
||||
if exoatm_elevation > 5.0:
|
||||
refraction_correction = (
|
||||
58.1 / te - 0.07 / (te ** 3) + 0.000086 / (te ** 5))
|
||||
elif (exoatm_elevation > -0.575):
|
||||
s1 = (-12.79 + exoatm_elevation * 0.711)
|
||||
s2 = (103.4 + exoatm_elevation * (s1))
|
||||
s3 = (-518.2 + exoatm_elevation * (s2))
|
||||
elif exoatm_elevation > -0.575:
|
||||
s1 = -12.79 + exoatm_elevation * 0.711
|
||||
s2 = 103.4 + exoatm_elevation * s1
|
||||
s3 = -518.2 + exoatm_elevation * s2
|
||||
refraction_correction = 1735.0 + exoatm_elevation * (s3)
|
||||
else:
|
||||
refraction_correction = -20.774 / te
|
||||
|
||||
refraction_correction = refraction_correction / 3600
|
||||
solar_elevation = 90.0 - (degrees(zenith) - refraction_correction)
|
||||
refraction_correction /= 3600
|
||||
elevation = pi/2 - (zenith - radians(refraction_correction))
|
||||
|
||||
else:
|
||||
solar_elevation = 90.0 - degrees(zenith)
|
||||
elevation = pi/2 - zenith
|
||||
|
||||
solar_azimuth = azimuth
|
||||
solar_azimuth += north_offset
|
||||
|
||||
az_north = solar_azimuth
|
||||
theta = math.pi / 2 - radians(solar_elevation)
|
||||
phi = radians(solar_azimuth) * -1
|
||||
azimuth = azimuth
|
||||
elevation = solar_elevation
|
||||
|
||||
return az_north, theta, phi, azimuth, elevation
|
||||
return azimuth, elevation
|
||||
|
||||
|
||||
def get_sun_vector(theta, phi):
|
||||
def get_sun_vector(azimuth, elevation, north_offset):
|
||||
"""
|
||||
Convert the sun coordinates to cartesian
|
||||
"""
|
||||
loc_x = math.sin(phi) * math.sin(-theta)
|
||||
loc_y = math.sin(theta) * math.cos(phi)
|
||||
loc_z = math.cos(theta)
|
||||
phi = -(azimuth + north_offset)
|
||||
theta = pi/2 - elevation
|
||||
|
||||
loc_x = sin(phi) * sin(-theta)
|
||||
loc_y = sin(theta) * cos(phi)
|
||||
loc_z = cos(theta)
|
||||
return Vector((loc_x, loc_y, loc_z))
|
||||
|
||||
|
||||
@ -426,14 +418,14 @@ def calc_sun_declination(t):
|
||||
|
||||
def calc_hour_angle_sunrise(lat, solar_dec):
|
||||
lat_rad = radians(lat)
|
||||
HAarg = (math.cos(radians(90.833)) /
|
||||
(math.cos(lat_rad) * math.cos(solar_dec))
|
||||
- math.tan(lat_rad) * math.tan(solar_dec))
|
||||
HAarg = (cos(radians(90.833)) /
|
||||
(cos(lat_rad) * cos(solar_dec))
|
||||
- tan(lat_rad) * tan(solar_dec))
|
||||
if HAarg < -1.0:
|
||||
HAarg = -1.0
|
||||
elif HAarg > 1.0:
|
||||
HAarg = 1.0
|
||||
HA = math.acos(HAarg)
|
||||
HA = acos(HAarg)
|
||||
return HA
|
||||
|
||||
|
||||
@ -458,8 +450,8 @@ def calc_sunrise_sunset(rise):
|
||||
sun.latitude, sun.longitude)
|
||||
time_local = new_time_UTC + (-zone * 60.0)
|
||||
tl = time_local / 60.0
|
||||
az_north, theta, phi, azimuth, elevation = get_sun_coordinates(
|
||||
tl, sun.latitude, sun.longitude, 0.0,
|
||||
azimuth, elevation = get_sun_coordinates(
|
||||
tl, sun.latitude, sun.longitude,
|
||||
zone, sun.month, sun.day, sun.year,
|
||||
sun.sun_distance)
|
||||
if sun.use_daylight_savings:
|
||||
@ -491,10 +483,10 @@ def get_julian_day(year, month, day):
|
||||
if month <= 2:
|
||||
year -= 1
|
||||
month += 12
|
||||
A = math.floor(year / 100)
|
||||
B = 2 - A + math.floor(A / 4.0)
|
||||
jd = (math.floor((365.25 * (year + 4716.0))) +
|
||||
math.floor(30.6001 * (month + 1)) + day + B - 1524.5)
|
||||
A = floor(year / 100)
|
||||
B = 2 - A + floor(A / 4.0)
|
||||
jd = (floor((365.25 * (year + 4716.0))) +
|
||||
floor(30.6001 * (month + 1)) + day + B - 1524.5)
|
||||
return jd
|
||||
|
||||
|
||||
@ -504,7 +496,7 @@ def calc_time_julian_cent(jd):
|
||||
|
||||
|
||||
def sun_declination(e, L):
|
||||
return (math.asin(math.sin(e) * math.sin(L)))
|
||||
return (asin(sin(e) * sin(L)))
|
||||
|
||||
|
||||
def calc_equation_of_time(t):
|
||||
@ -512,13 +504,13 @@ def calc_equation_of_time(t):
|
||||
ml = radians(mean_longitude_sun(t))
|
||||
e = eccentricity_earth_orbit(t)
|
||||
m = radians(mean_anomaly_sun(t))
|
||||
y = math.tan(radians(epsilon) / 2.0)
|
||||
y = tan(radians(epsilon) / 2.0)
|
||||
y = y * y
|
||||
sin2ml = math.sin(2.0 * ml)
|
||||
cos2ml = math.cos(2.0 * ml)
|
||||
sin4ml = math.sin(4.0 * ml)
|
||||
sinm = math.sin(m)
|
||||
sin2m = math.sin(2.0 * m)
|
||||
sin2ml = sin(2.0 * ml)
|
||||
cos2ml = cos(2.0 * ml)
|
||||
sin4ml = sin(4.0 * ml)
|
||||
sinm = sin(m)
|
||||
sin2m = sin(2.0 * m)
|
||||
etime = (y * sin2ml - 2.0 * e * sinm + 4.0 * e * y *
|
||||
sinm * cos2ml - 0.5 * y ** 2 * sin4ml - 1.25 * e ** 2 * sin2m)
|
||||
return (degrees(etime) * 4)
|
||||
@ -527,7 +519,7 @@ def calc_equation_of_time(t):
|
||||
def obliquity_correction(t):
|
||||
ec = obliquity_of_ecliptic(t)
|
||||
omega = 125.04 - 1934.136 * t
|
||||
return (ec + 0.00256 * math.cos(radians(omega)))
|
||||
return (ec + 0.00256 * cos(radians(omega)))
|
||||
|
||||
|
||||
def obliquity_of_ecliptic(t):
|
||||
@ -542,13 +534,13 @@ def true_longitude_of_sun(t):
|
||||
def calc_sun_apparent_long(t):
|
||||
o = true_longitude_of_sun(t)
|
||||
omega = 125.04 - 1934.136 * t
|
||||
lamb = o - 0.00569 - 0.00478 * math.sin(radians(omega))
|
||||
lamb = o - 0.00569 - 0.00478 * sin(radians(omega))
|
||||
return lamb
|
||||
|
||||
|
||||
def apparent_longitude_of_sun(t):
|
||||
return (radians(true_longitude_of_sun(t) - 0.00569 - 0.00478 *
|
||||
math.sin(radians(125.04 - 1934.136 * t))))
|
||||
sin(radians(125.04 - 1934.136 * t))))
|
||||
|
||||
|
||||
def mean_longitude_sun(t):
|
||||
@ -557,9 +549,9 @@ def mean_longitude_sun(t):
|
||||
|
||||
def equation_of_sun_center(t):
|
||||
m = radians(mean_anomaly_sun(t))
|
||||
c = ((1.914602 - 0.004817 * t - 0.000014 * t**2) * math.sin(m) +
|
||||
(0.019993 - 0.000101 * t) * math.sin(m * 2) +
|
||||
0.000289 * math.sin(m * 3))
|
||||
c = ((1.914602 - 0.004817 * t - 0.000014 * t**2) * sin(m) +
|
||||
(0.019993 - 0.000101 * t) * sin(m * 2) +
|
||||
0.000289 * sin(m * 3))
|
||||
return c
|
||||
|
||||
|
||||
@ -575,13 +567,13 @@ def calc_surface(context):
|
||||
coords = []
|
||||
sun_props = context.scene.sun_pos_properties
|
||||
zone = -sun_props.UTC_zone
|
||||
north_offset = degrees(sun_props.north_offset)
|
||||
north_offset = sun_props.north_offset
|
||||
|
||||
def get_surface_coordinates(time, month):
|
||||
_, theta, phi, _, _ = get_sun_coordinates(
|
||||
time, sun_props.latitude, sun_props.longitude, north_offset,
|
||||
azimuth, elevation = get_sun_coordinates(
|
||||
time, sun_props.latitude, sun_props.longitude,
|
||||
zone, month, 1, sun_props.year, sun_props.sun_distance)
|
||||
sun_vector = get_sun_vector(theta, phi) * sun_props.sun_distance
|
||||
sun_vector = get_sun_vector(azimuth, elevation, north_offset) * sun_props.sun_distance
|
||||
sun_vector.z = max(0, sun_vector.z)
|
||||
return sun_vector
|
||||
|
||||
@ -601,21 +593,20 @@ def calc_analemma(context, h):
|
||||
vertices = []
|
||||
sun_props = context.scene.sun_pos_properties
|
||||
zone = -sun_props.UTC_zone
|
||||
north_offset = degrees(sun_props.north_offset)
|
||||
north_offset = sun_props.north_offset
|
||||
for day_of_year in range(1, 367, 5):
|
||||
day, month = day_of_year_to_month_day(sun_props.year, day_of_year)
|
||||
_, theta, phi, _, _ = get_sun_coordinates(
|
||||
azimuth, elevation = get_sun_coordinates(
|
||||
h, sun_props.latitude, sun_props.longitude,
|
||||
north_offset, zone, month, day, sun_props.year,
|
||||
zone, month, day, sun_props.year,
|
||||
sun_props.sun_distance)
|
||||
sun_vector = get_sun_vector(theta, phi) * sun_props.sun_distance
|
||||
sun_vector = get_sun_vector(azimuth, elevation, north_offset) * sun_props.sun_distance
|
||||
if sun_vector.z > 0:
|
||||
vertices.append(sun_vector)
|
||||
return vertices
|
||||
|
||||
|
||||
def draw_surface(batch, shader):
|
||||
|
||||
blend = gpu.state.blend_get()
|
||||
gpu.state.blend_set("ALPHA")
|
||||
shader.uniform_float("color", (.8, .6, 0, 0.2))
|
||||
@ -630,6 +621,7 @@ def draw_analemmas(batch, shader):
|
||||
|
||||
_handle_surface = None
|
||||
|
||||
|
||||
def surface_update(self, context):
|
||||
global _handle_surface
|
||||
if self.show_surface:
|
||||
@ -648,6 +640,7 @@ def surface_update(self, context):
|
||||
|
||||
_handle_analemmas = None
|
||||
|
||||
|
||||
def analemmas_update(self, context):
|
||||
global _handle_analemmas
|
||||
if self.show_analemmas:
|
||||
@ -664,7 +657,7 @@ def analemmas_update(self, context):
|
||||
|
||||
shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
|
||||
batch = batch_for_shader(shader, 'LINES',
|
||||
{"pos": coords}, indices=indices)
|
||||
{"pos": coords}, indices=indices)
|
||||
|
||||
if _handle_analemmas is not None:
|
||||
bpy.types.SpaceView3D.draw_handler_remove(_handle_analemmas, 'WINDOW')
|
||||
|
@ -4,6 +4,7 @@ import bpy
|
||||
from bpy.types import Operator, Menu
|
||||
from bl_operators.presets import AddPresetBase
|
||||
import os
|
||||
from math import degrees
|
||||
|
||||
from .sun_calc import (format_lat_long, format_time, format_hms, sun)
|
||||
|
||||
@ -79,7 +80,7 @@ class SUNPOS_PT_Panel(bpy.types.Panel):
|
||||
|
||||
def draw_environ_mode_panel(self, context, sp, p, layout):
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True,
|
||||
even_rows=False, align=False)
|
||||
even_rows=False, align=False)
|
||||
|
||||
col = flow.column(align=True)
|
||||
col.label(text="Environment Texture")
|
||||
@ -153,6 +154,7 @@ class SUNPOS_PT_Panel(bpy.types.Panel):
|
||||
col.label(text="Please select World in the World panel.",
|
||||
icon="ERROR")
|
||||
|
||||
|
||||
class SUNPOS_PT_Location(bpy.types.Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
@ -211,10 +213,10 @@ class SUNPOS_PT_Location(bpy.types.Panel):
|
||||
col = flow.column(align=True)
|
||||
split = col.split(factor=0.4, align=True)
|
||||
split.label(text="Azimuth:")
|
||||
split.label(text=str(round(sun.azimuth, 3)) + "°")
|
||||
split.label(text=str(round(degrees(sun.azimuth), 3)) + "°")
|
||||
split = col.split(factor=0.4, align=True)
|
||||
split.label(text="Elevation:")
|
||||
split.label(text=str(round(sun.elevation, 3)) + "°")
|
||||
split.label(text=str(round(degrees(sun.elevation), 3)) + "°")
|
||||
col.separator()
|
||||
|
||||
if p.show_refraction:
|
||||
@ -282,7 +284,6 @@ class SUNPOS_PT_Time(bpy.types.Panel):
|
||||
split.label(text=ut)
|
||||
col.separator()
|
||||
|
||||
|
||||
col = flow.column(align=True)
|
||||
col.alignment = 'CENTER'
|
||||
if p.show_rise_set:
|
||||
|
Loading…
Reference in New Issue
Block a user