glTF: fix a few typos #104607
@ -2,12 +2,12 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Author : Clemens Barth (Blendphys@root-1.de)
|
# Author : Clemens Barth (Blendphys@root-1.de)
|
||||||
# Homepage(Wiki) : http://development.root-1.de/Atomic_Blender.php
|
# Homepage(Wiki) : https://docs.blender.org/manual/en/dev/addons/import_export/mesh_atomic.html
|
||||||
#
|
#
|
||||||
# Start of project : 2011-08-31 by CB
|
# Start of project : 2011-08-31 by CB
|
||||||
# First publication in Blender : 2011-11-11 by CB
|
# First publication in Blender : 2011-11-11 by CB
|
||||||
# Fusion of the PDB, XYZ and Panel : 2019-03-22 by CB
|
# Fusion of the PDB, XYZ and Panel : 2019-03-22 by CB
|
||||||
# Last modified : 2019-05-17
|
# Last modified : 2023-05-19
|
||||||
#
|
#
|
||||||
# Contributing authors
|
# Contributing authors
|
||||||
# ====================
|
# ====================
|
||||||
|
@ -96,8 +96,8 @@ class IMPORT_OT_pdb(Operator, ImportHelper):
|
|||||||
name="Bonds", default=False,
|
name="Bonds", default=False,
|
||||||
description="Show double and triple bonds")
|
description="Show double and triple bonds")
|
||||||
sticks_dist: FloatProperty(
|
sticks_dist: FloatProperty(
|
||||||
name="", default = 1.1, min=1.0, max=3.0,
|
name="", default = 0.8, min=0.0, max=3.0,
|
||||||
description="Distance between sticks measured in stick diameter")
|
description="Distance between sticks (double or tripple bonds) measured in stick diameter")
|
||||||
use_sticks_one_object: BoolProperty(
|
use_sticks_one_object: BoolProperty(
|
||||||
name="One object", default=False,
|
name="One object", default=False,
|
||||||
description="All sticks are one object")
|
description="All sticks are one object")
|
||||||
@ -184,7 +184,10 @@ class IMPORT_OT_pdb(Operator, ImportHelper):
|
|||||||
col = row.column()
|
col = row.column()
|
||||||
col.active = self.use_sticks_one_object
|
col.active = self.use_sticks_one_object
|
||||||
col.prop(self, "use_sticks_one_object_nr")
|
col.prop(self, "use_sticks_one_object_nr")
|
||||||
|
row = box.row()
|
||||||
|
row.active = self.use_sticks and self.use_sticks_bonds
|
||||||
|
row.label(text="Distance")
|
||||||
|
row.prop(self, "sticks_dist")
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
# Switch to 'OBJECT' mode when in 'EDIT' mode.
|
# Switch to 'OBJECT' mode when in 'EDIT' mode.
|
||||||
|
@ -556,7 +556,7 @@ def camera_light_source(use_camera,
|
|||||||
|
|
||||||
camera_factor = 15.0
|
camera_factor = 15.0
|
||||||
|
|
||||||
# If chosen a camera is put into the scene.
|
# If chosen, a camera is put into the scene.
|
||||||
if use_camera == True:
|
if use_camera == True:
|
||||||
|
|
||||||
# Assume that the object is put into the global origin. Then, the
|
# Assume that the object is put into the global origin. Then, the
|
||||||
@ -850,7 +850,7 @@ def draw_sticks_dupliverts(all_atoms,
|
|||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
# What follows is school mathematics! :-) We construct equidistant
|
# What follows is school mathematics! :-) We construct equidistant
|
||||||
# planes, on which the stcik sections (cylinders) are perpendicular on.
|
# planes, on which the stick sections (cylinders) are perpendicular on.
|
||||||
for stick in stick_list:
|
for stick in stick_list:
|
||||||
|
|
||||||
dv = stick[2]
|
dv = stick[2]
|
||||||
@ -1100,6 +1100,7 @@ def draw_sticks_normal(all_atoms,
|
|||||||
center,
|
center,
|
||||||
Stick_diameter,
|
Stick_diameter,
|
||||||
Stick_sectors,
|
Stick_sectors,
|
||||||
|
Stick_dist,
|
||||||
use_sticks_smooth,
|
use_sticks_smooth,
|
||||||
use_sticks_one_object,
|
use_sticks_one_object,
|
||||||
use_sticks_one_object_nr,
|
use_sticks_one_object_nr,
|
||||||
@ -1117,60 +1118,104 @@ def draw_sticks_normal(all_atoms,
|
|||||||
list_group = []
|
list_group = []
|
||||||
list_group_sub = []
|
list_group_sub = []
|
||||||
counter = 0
|
counter = 0
|
||||||
for stick in all_sticks:
|
for i, stick in enumerate(all_sticks):
|
||||||
|
|
||||||
# The vectors of the two atoms
|
# We treat here single, double and tripple bonds: stick.number <= 3
|
||||||
atom1 = all_atoms[stick.atom1-1].location-center
|
for repeat in range(stick.number):
|
||||||
atom2 = all_atoms[stick.atom2-1].location-center
|
|
||||||
# Location
|
|
||||||
location = (atom1 + atom2) * 0.5
|
|
||||||
# The difference of both vectors
|
|
||||||
v = (atom2 - atom1)
|
|
||||||
# Angle with respect to the z-axis
|
|
||||||
angle = v.angle(up_axis, 0)
|
|
||||||
# Cross-product between v and the z-axis vector. It is the
|
|
||||||
# vector of rotation.
|
|
||||||
axis = up_axis.cross(v)
|
|
||||||
# Calculate Euler angles
|
|
||||||
euler = Matrix.Rotation(angle, 4, axis).to_euler()
|
|
||||||
# Create stick
|
|
||||||
stick = bpy.ops.mesh.primitive_cylinder_add(vertices=Stick_sectors,
|
|
||||||
radius=Stick_diameter,
|
|
||||||
depth=v.length,
|
|
||||||
end_fill_type='NGON',
|
|
||||||
align='WORLD',
|
|
||||||
enter_editmode=False,
|
|
||||||
location=location,
|
|
||||||
rotation=(0, 0, 0))
|
|
||||||
# Put the stick into the scene ...
|
|
||||||
stick = bpy.context.view_layer.objects.active
|
|
||||||
# ... and rotate the stick.
|
|
||||||
stick.rotation_euler = euler
|
|
||||||
# ... and name
|
|
||||||
stick.name = "Stick_Cylinder"
|
|
||||||
counter += 1
|
|
||||||
|
|
||||||
# Smooth the cylinder.
|
# The vectors of the two atoms
|
||||||
if use_sticks_smooth == True:
|
atom1 = copy(all_atoms[stick.atom1-1].location)-center
|
||||||
bpy.ops.object.select_all(action='DESELECT')
|
atom2 = copy(all_atoms[stick.atom2-1].location)-center
|
||||||
stick.select_set(True)
|
|
||||||
bpy.ops.object.shade_smooth()
|
|
||||||
|
|
||||||
list_group_sub.append(stick)
|
dist = Stick_diameter * Stick_dist
|
||||||
|
|
||||||
if use_sticks_one_object == True:
|
# The two sticks are on the left and right of the middle connection.
|
||||||
if counter == use_sticks_one_object_nr:
|
if stick.number == 2:
|
||||||
|
if repeat == 0:
|
||||||
|
atom1 += (stick.dist * dist)
|
||||||
|
atom2 += (stick.dist * dist)
|
||||||
|
if repeat == 1:
|
||||||
|
atom1 -= (stick.dist * dist)
|
||||||
|
atom2 -= (stick.dist * dist)
|
||||||
|
|
||||||
|
if stick.number == 3:
|
||||||
|
if repeat == 0:
|
||||||
|
atom1 += (stick.dist * dist)
|
||||||
|
atom2 += (stick.dist * dist)
|
||||||
|
if repeat == 2:
|
||||||
|
atom1 -= (stick.dist * dist)
|
||||||
|
atom2 -= (stick.dist * dist)
|
||||||
|
|
||||||
|
# Vector pointing along the stick direction
|
||||||
|
dv = atom1 - atom2
|
||||||
|
# The normalized vector of this, with lenght 1
|
||||||
|
n = dv / dv.length
|
||||||
|
# Starting point of the stick
|
||||||
|
location = (atom1 + atom2) * 0.5
|
||||||
|
# Angle with respect to the z-axis
|
||||||
|
angle = dv.angle(up_axis, 0)
|
||||||
|
# Cross-product between v and the z-axis vector. It is the
|
||||||
|
# vector of rotation.
|
||||||
|
axis = up_axis.cross(dv)
|
||||||
|
# Calculate Euler angles
|
||||||
|
euler = Matrix.Rotation(angle, 4, axis).to_euler()
|
||||||
|
# Create stick
|
||||||
|
stick_obj = bpy.ops.mesh.primitive_cylinder_add(vertices=Stick_sectors,
|
||||||
|
radius=Stick_diameter,
|
||||||
|
depth=dv.length,
|
||||||
|
end_fill_type='NGON',
|
||||||
|
align='WORLD',
|
||||||
|
enter_editmode=False,
|
||||||
|
location=location,
|
||||||
|
rotation=(0, 0, 0))
|
||||||
|
# Put the stick into the scene ...
|
||||||
|
stick_obj = bpy.context.view_layer.objects.active
|
||||||
|
# ... and rotate the stick.
|
||||||
|
stick_obj.rotation_euler = euler
|
||||||
|
# ... and name
|
||||||
|
if stick.number == 1:
|
||||||
|
stick_obj.name = "Stick_Cylinder_%04d" %(i)
|
||||||
|
elif stick.number == 2:
|
||||||
|
if repeat == 0:
|
||||||
|
stick_obj.name = "Stick_Cylinder_%04d" %(i) + "_left"
|
||||||
|
elif repeat == 1:
|
||||||
|
stick_obj.name = "Stick_Cylinder_%04d" %(i) + "_right"
|
||||||
|
elif stick.number == 3:
|
||||||
|
if repeat == 0:
|
||||||
|
stick_obj.name = "Stick_Cylinder_%04d" %(i) + "_left"
|
||||||
|
elif repeat == 1:
|
||||||
|
stick_obj.name = "Stick_Cylinder_%04d" %(i) + "_middle"
|
||||||
|
elif repeat == 2:
|
||||||
|
stick_obj.name = "Stick_Cylinder_%04d" %(i) + "_right"
|
||||||
|
# Never occurs:
|
||||||
|
else:
|
||||||
|
stick_obj.name = "Stick_Cylinder"
|
||||||
|
# Never occurs:
|
||||||
|
else:
|
||||||
|
stick_obj.name = "Stick_Cylinder"
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
# Smooth the cylinder.
|
||||||
|
if use_sticks_smooth == True:
|
||||||
bpy.ops.object.select_all(action='DESELECT')
|
bpy.ops.object.select_all(action='DESELECT')
|
||||||
for stick in list_group_sub:
|
stick_obj.select_set(True)
|
||||||
stick.select_set(True)
|
bpy.ops.object.shade_smooth()
|
||||||
bpy.ops.object.join()
|
|
||||||
list_group.append(bpy.context.view_layer.objects.active)
|
list_group_sub.append(stick_obj)
|
||||||
bpy.ops.object.select_all(action='DESELECT')
|
|
||||||
list_group_sub = []
|
if use_sticks_one_object == True:
|
||||||
counter = 0
|
if counter == use_sticks_one_object_nr:
|
||||||
else:
|
bpy.ops.object.select_all(action='DESELECT')
|
||||||
# Material ...
|
for stick_select in list_group_sub:
|
||||||
stick.active_material = stick_material
|
stick_select.select_set(True)
|
||||||
|
bpy.ops.object.join()
|
||||||
|
list_group.append(bpy.context.view_layer.objects.active)
|
||||||
|
bpy.ops.object.select_all(action='DESELECT')
|
||||||
|
list_group_sub = []
|
||||||
|
counter = 0
|
||||||
|
else:
|
||||||
|
# Material ...
|
||||||
|
stick_obj.active_material = stick_material
|
||||||
|
|
||||||
if use_sticks_one_object == True:
|
if use_sticks_one_object == True:
|
||||||
bpy.ops.object.select_all(action='DESELECT')
|
bpy.ops.object.select_all(action='DESELECT')
|
||||||
@ -1184,7 +1229,7 @@ def draw_sticks_normal(all_atoms,
|
|||||||
group.select_set(True)
|
group.select_set(True)
|
||||||
bpy.ops.object.join()
|
bpy.ops.object.join()
|
||||||
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY',
|
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY',
|
||||||
center='MEDIAN')
|
center='MEDIAN')
|
||||||
sticks = bpy.context.view_layer.objects.active
|
sticks = bpy.context.view_layer.objects.active
|
||||||
sticks.active_material = stick_material
|
sticks.active_material = stick_material
|
||||||
|
|
||||||
@ -1531,6 +1576,7 @@ def import_pdb(Ball_type,
|
|||||||
object_center_vec,
|
object_center_vec,
|
||||||
Stick_diameter,
|
Stick_diameter,
|
||||||
Stick_sectors,
|
Stick_sectors,
|
||||||
|
Stick_dist,
|
||||||
use_sticks_smooth,
|
use_sticks_smooth,
|
||||||
use_sticks_one_object,
|
use_sticks_one_object,
|
||||||
use_sticks_one_object_nr,
|
use_sticks_one_object_nr,
|
||||||
|
@ -157,7 +157,7 @@ def sane_name(name):
|
|||||||
new_name = new_name_clean + '.%.3d' % i
|
new_name = new_name_clean + '.%.3d' % i
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
# note, appending the 'str' version.
|
# note, appending the 'str' version
|
||||||
name_unique.append(new_name)
|
name_unique.append(new_name)
|
||||||
name_mapping[name] = new_name = new_name.encode("ASCII", "replace")
|
name_mapping[name] = new_name = new_name.encode("ASCII", "replace")
|
||||||
return new_name
|
return new_name
|
||||||
@ -166,14 +166,13 @@ def sane_name(name):
|
|||||||
def uv_key(uv):
|
def uv_key(uv):
|
||||||
return round(uv[0], 6), round(uv[1], 6)
|
return round(uv[0], 6), round(uv[1], 6)
|
||||||
|
|
||||||
# size defines:
|
# size defines
|
||||||
SZ_SHORT = 2
|
SZ_SHORT = 2
|
||||||
SZ_INT = 4
|
SZ_INT = 4
|
||||||
SZ_FLOAT = 4
|
SZ_FLOAT = 4
|
||||||
|
|
||||||
class _3ds_ushort(object):
|
class _3ds_ushort(object):
|
||||||
"""Class representing a short (2-byte integer) for a 3ds file.
|
"""Class representing a short (2-byte integer) for a 3ds file."""
|
||||||
*** This looks like an unsigned short H is unsigned from the struct docs - Cam***"""
|
|
||||||
__slots__ = ("value", )
|
__slots__ = ("value", )
|
||||||
|
|
||||||
def __init__(self, val=0):
|
def __init__(self, val=0):
|
||||||
@ -308,7 +307,7 @@ class _3ds_float_color(object):
|
|||||||
return 3 * SZ_FLOAT
|
return 3 * SZ_FLOAT
|
||||||
|
|
||||||
def write(self, file):
|
def write(self, file):
|
||||||
file.write(struct.pack('3f', self.r, self.g, self.b))
|
file.write(struct.pack('<3f', self.r, self.g, self.b))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{%f, %f, %f}' % (self.r, self.g, self.b)
|
return '{%f, %f, %f}' % (self.r, self.g, self.b)
|
||||||
@ -342,9 +341,7 @@ class _3ds_face(object):
|
|||||||
def get_size(self):
|
def get_size(self):
|
||||||
return 4 * SZ_SHORT
|
return 4 * SZ_SHORT
|
||||||
|
|
||||||
# no need to validate every face vert. the oversized array will
|
# no need to validate every face vert, the oversized array will catch this problem
|
||||||
# catch this problem
|
|
||||||
|
|
||||||
def write(self, file):
|
def write(self, file):
|
||||||
# The last short is used for face flags
|
# The last short is used for face flags
|
||||||
file.write(struct.pack('<4H', self.vindex[0], self.vindex[1], self.vindex[2], self.flag))
|
file.write(struct.pack('<4H', self.vindex[0], self.vindex[1], self.vindex[2], self.flag))
|
||||||
@ -355,15 +352,14 @@ class _3ds_face(object):
|
|||||||
|
|
||||||
class _3ds_array(object):
|
class _3ds_array(object):
|
||||||
"""Class representing an array of variables for a 3ds file.
|
"""Class representing an array of variables for a 3ds file.
|
||||||
Consists of a _3ds_ushort to indicate the number of items, followed by the items themselves.
|
Consists of a _3ds_ushort to indicate the number of items, followed by the items themselves."""
|
||||||
"""
|
|
||||||
__slots__ = "values", "size"
|
__slots__ = "values", "size"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.values = []
|
self.values = []
|
||||||
self.size = SZ_SHORT
|
self.size = SZ_SHORT
|
||||||
|
|
||||||
# add an item:
|
# add an item
|
||||||
def add(self, item):
|
def add(self, item):
|
||||||
self.values.append(item)
|
self.values.append(item)
|
||||||
self.size += item.get_size()
|
self.size += item.get_size()
|
||||||
@ -380,7 +376,7 @@ class _3ds_array(object):
|
|||||||
value.write(file)
|
value.write(file)
|
||||||
|
|
||||||
# To not overwhelm the output in a dump, a _3ds_array only
|
# To not overwhelm the output in a dump, a _3ds_array only
|
||||||
# outputs the number of items, not all of the actual items.
|
# outputs the number of items, not all of the actual items
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '(%d items)' % len(self.values)
|
return '(%d items)' % len(self.values)
|
||||||
|
|
||||||
@ -583,7 +579,7 @@ def make_material_texture_chunk(chunk_id, texslots, pct):
|
|||||||
0x40 activates alpha source, 0x80 activates tinting, 0x100 ignores alpha, 0x200 activates RGB tint.
|
0x40 activates alpha source, 0x80 activates tinting, 0x100 ignores alpha, 0x200 activates RGB tint.
|
||||||
Bits 0x80, 0x100, and 0x200 are only used with TEXMAP, TEX2MAP, and SPECMAP chunks.
|
Bits 0x80, 0x100, and 0x200 are only used with TEXMAP, TEX2MAP, and SPECMAP chunks.
|
||||||
0x40, when used with a TEXMAP, TEX2MAP, or SPECMAP chunk must be accompanied with a tint bit,
|
0x40, when used with a TEXMAP, TEX2MAP, or SPECMAP chunk must be accompanied with a tint bit,
|
||||||
either 0x100 or 0x200, tintcolor will be processed if colorchunks are present"""
|
either 0x100 or 0x200, tintcolor will be processed if tintflags are present"""
|
||||||
|
|
||||||
mapflags = 0
|
mapflags = 0
|
||||||
if texslot.extension == 'EXTEND':
|
if texslot.extension == 'EXTEND':
|
||||||
@ -632,9 +628,8 @@ def make_material_texture_chunk(chunk_id, texslots, pct):
|
|||||||
rgb.add_variable("mapcolor", _3ds_rgb_color(spec if texslot.socket_dst.identifier == 'Specular' else base))
|
rgb.add_variable("mapcolor", _3ds_rgb_color(spec if texslot.socket_dst.identifier == 'Specular' else base))
|
||||||
mat_sub.add_subchunk(rgb)
|
mat_sub.add_subchunk(rgb)
|
||||||
|
|
||||||
# store all textures for this mapto in order. This at least is what
|
# store all textures for this mapto in order. This at least is what the
|
||||||
# the 3DS exporter did so far, afaik most readers will just skip
|
# 3DS exporter did so far, afaik most readers will just skip over 2nd textures
|
||||||
# over 2nd textures.
|
|
||||||
for slot in texslots:
|
for slot in texslots:
|
||||||
if slot.image is not None:
|
if slot.image is not None:
|
||||||
add_texslot(slot)
|
add_texslot(slot)
|
||||||
@ -685,9 +680,9 @@ def make_material_chunk(material, image):
|
|||||||
primary_tex = False
|
primary_tex = False
|
||||||
|
|
||||||
if wrap.base_color_texture:
|
if wrap.base_color_texture:
|
||||||
d_pct = 0.7 + sum(wrap.base_color[:]) * 0.1
|
|
||||||
color = [wrap.base_color_texture]
|
color = [wrap.base_color_texture]
|
||||||
matmap = make_material_texture_chunk(MAT_DIFFUSEMAP, color, d_pct)
|
c_pct = 0.7 + sum(wrap.base_color[:]) * 0.1
|
||||||
|
matmap = make_material_texture_chunk(MAT_DIFFUSEMAP, color, c_pct)
|
||||||
if matmap:
|
if matmap:
|
||||||
material_chunk.add_subchunk(matmap)
|
material_chunk.add_subchunk(matmap)
|
||||||
primary_tex = True
|
primary_tex = True
|
||||||
@ -729,8 +724,8 @@ def make_material_chunk(material, image):
|
|||||||
material_chunk.add_subchunk(matmap)
|
material_chunk.add_subchunk(matmap)
|
||||||
|
|
||||||
if wrap.emission_color_texture:
|
if wrap.emission_color_texture:
|
||||||
e_pct = wrap.emission_strength
|
|
||||||
emission = [wrap.emission_color_texture]
|
emission = [wrap.emission_color_texture]
|
||||||
|
e_pct = wrap.emission_strength
|
||||||
matmap = make_material_texture_chunk(MAT_SELFIMAP, emission, e_pct)
|
matmap = make_material_texture_chunk(MAT_SELFIMAP, emission, e_pct)
|
||||||
if matmap:
|
if matmap:
|
||||||
material_chunk.add_subchunk(matmap)
|
material_chunk.add_subchunk(matmap)
|
||||||
@ -849,8 +844,7 @@ def remove_face_uv(verts, tri_list):
|
|||||||
need to be converted to vertex uv coordinates. That means that vertices need to be duplicated when
|
need to be converted to vertex uv coordinates. That means that vertices need to be duplicated when
|
||||||
there are multiple uv coordinates per vertex."""
|
there are multiple uv coordinates per vertex."""
|
||||||
|
|
||||||
# initialize a list of UniqueLists, one per vertex:
|
# initialize a list of UniqueLists, one per vertex
|
||||||
# uv_list = [UniqueList() for i in xrange(len(verts))]
|
|
||||||
unique_uvs = [{} for i in range(len(verts))]
|
unique_uvs = [{} for i in range(len(verts))]
|
||||||
|
|
||||||
# for each face uv coordinate, add it to the UniqueList of the vertex
|
# for each face uv coordinate, add it to the UniqueList of the vertex
|
||||||
@ -861,7 +855,6 @@ def remove_face_uv(verts, tri_list):
|
|||||||
|
|
||||||
context_uv_vert = unique_uvs[tri.vertex_index[i]]
|
context_uv_vert = unique_uvs[tri.vertex_index[i]]
|
||||||
uvkey = tri.faceuvs[i]
|
uvkey = tri.faceuvs[i]
|
||||||
|
|
||||||
offset_index__uv_3ds = context_uv_vert.get(uvkey)
|
offset_index__uv_3ds = context_uv_vert.get(uvkey)
|
||||||
|
|
||||||
if not offset_index__uv_3ds:
|
if not offset_index__uv_3ds:
|
||||||
@ -869,11 +862,9 @@ def remove_face_uv(verts, tri_list):
|
|||||||
|
|
||||||
tri.offset[i] = offset_index__uv_3ds[0]
|
tri.offset[i] = offset_index__uv_3ds[0]
|
||||||
|
|
||||||
# At this point, each vertex has a UniqueList containing every uv coordinate that is associated with it
|
# At this point, each vertex has a UniqueList containing every uv coordinate associated with it only once
|
||||||
# only once.
|
|
||||||
|
|
||||||
# Now we need to duplicate every vertex as many times as it has uv coordinates and make sure the
|
# Now we need to duplicate every vertex as many times as it has uv coordinates and make sure the
|
||||||
# faces refer to the new face indices:
|
# faces refer to the new face indices
|
||||||
vert_index = 0
|
vert_index = 0
|
||||||
vert_array = _3ds_array()
|
vert_array = _3ds_array()
|
||||||
uv_array = _3ds_array()
|
uv_array = _3ds_array()
|
||||||
@ -884,22 +875,21 @@ def remove_face_uv(verts, tri_list):
|
|||||||
pt = _3ds_point_3d(vert.co) # reuse, should be ok
|
pt = _3ds_point_3d(vert.co) # reuse, should be ok
|
||||||
uvmap = [None] * len(unique_uvs[i])
|
uvmap = [None] * len(unique_uvs[i])
|
||||||
for ii, uv_3ds in unique_uvs[i].values():
|
for ii, uv_3ds in unique_uvs[i].values():
|
||||||
# add a vertex duplicate to the vertex_array for every uv associated with this vertex:
|
# add a vertex duplicate to the vertex_array for every uv associated with this vertex
|
||||||
vert_array.add(pt)
|
vert_array.add(pt)
|
||||||
# add the uv coordinate to the uv array:
|
# add the uv coordinate to the uv array, this for loop does not give
|
||||||
# This for loop does not give uv's ordered by ii, so we create a new map
|
# uv's ordered by ii, so we create a new map and add the uv's later
|
||||||
# and add the uv's later
|
|
||||||
# uv_array.add(uv_3ds)
|
# uv_array.add(uv_3ds)
|
||||||
uvmap[ii] = uv_3ds
|
uvmap[ii] = uv_3ds
|
||||||
|
|
||||||
# Add the uv's in the correct order
|
# Add the uv's in the correct order
|
||||||
for uv_3ds in uvmap:
|
for uv_3ds in uvmap:
|
||||||
# add the uv coordinate to the uv array:
|
# add the uv coordinate to the uv array
|
||||||
uv_array.add(uv_3ds)
|
uv_array.add(uv_3ds)
|
||||||
|
|
||||||
vert_index += len(unique_uvs[i])
|
vert_index += len(unique_uvs[i])
|
||||||
|
|
||||||
# Make sure the triangle vertex indices now refer to the new vertex list:
|
# Make sure the triangle vertex indices now refer to the new vertex list
|
||||||
for tri in tri_list:
|
for tri in tri_list:
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
tri.offset[i] += index_list[tri.vertex_index[i]]
|
tri.offset[i] += index_list[tri.vertex_index[i]]
|
||||||
@ -1003,30 +993,30 @@ def make_uv_chunk(uv_array):
|
|||||||
def make_mesh_chunk(ob, mesh, matrix, materialDict, translation):
|
def make_mesh_chunk(ob, mesh, matrix, materialDict, translation):
|
||||||
"""Make a chunk out of a Blender mesh."""
|
"""Make a chunk out of a Blender mesh."""
|
||||||
|
|
||||||
# Extract the triangles from the mesh:
|
# Extract the triangles from the mesh
|
||||||
tri_list = extract_triangles(mesh)
|
tri_list = extract_triangles(mesh)
|
||||||
|
|
||||||
if mesh.uv_layers:
|
if mesh.uv_layers:
|
||||||
# Remove the face UVs and convert it to vertex UV:
|
# Remove the face UVs and convert it to vertex UV
|
||||||
vert_array, uv_array, tri_list = remove_face_uv(mesh.vertices, tri_list)
|
vert_array, uv_array, tri_list = remove_face_uv(mesh.vertices, tri_list)
|
||||||
else:
|
else:
|
||||||
# Add the vertices to the vertex array:
|
# Add the vertices to the vertex array
|
||||||
vert_array = _3ds_array()
|
vert_array = _3ds_array()
|
||||||
for vert in mesh.vertices:
|
for vert in mesh.vertices:
|
||||||
vert_array.add(_3ds_point_3d(vert.co))
|
vert_array.add(_3ds_point_3d(vert.co))
|
||||||
# no UV at all:
|
# no UV at all
|
||||||
uv_array = None
|
uv_array = None
|
||||||
|
|
||||||
# create the chunk:
|
# create the chunk
|
||||||
mesh_chunk = _3ds_chunk(OBJECT_MESH)
|
mesh_chunk = _3ds_chunk(OBJECT_MESH)
|
||||||
|
|
||||||
# add vertex chunk:
|
# add vertex chunk
|
||||||
mesh_chunk.add_subchunk(make_vert_chunk(vert_array))
|
mesh_chunk.add_subchunk(make_vert_chunk(vert_array))
|
||||||
|
|
||||||
# add faces chunk:
|
# add faces chunk
|
||||||
mesh_chunk.add_subchunk(make_faces_chunk(tri_list, mesh, materialDict))
|
mesh_chunk.add_subchunk(make_faces_chunk(tri_list, mesh, materialDict))
|
||||||
|
|
||||||
# if available, add uv chunk:
|
# if available, add uv chunk
|
||||||
if uv_array:
|
if uv_array:
|
||||||
mesh_chunk.add_subchunk(make_uv_chunk(uv_array))
|
mesh_chunk.add_subchunk(make_uv_chunk(uv_array))
|
||||||
|
|
||||||
@ -1200,15 +1190,15 @@ def save(operator,
|
|||||||
if bpy.ops.object.mode_set.poll():
|
if bpy.ops.object.mode_set.poll():
|
||||||
bpy.ops.object.mode_set(mode='OBJECT')
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
# Initialize the main chunk (primary):
|
# Initialize the main chunk (primary)
|
||||||
primary = _3ds_chunk(PRIMARY)
|
primary = _3ds_chunk(PRIMARY)
|
||||||
|
|
||||||
# Add version chunk:
|
# Add version chunk
|
||||||
version_chunk = _3ds_chunk(VERSION)
|
version_chunk = _3ds_chunk(VERSION)
|
||||||
version_chunk.add_variable("version", _3ds_uint(3))
|
version_chunk.add_variable("version", _3ds_uint(3))
|
||||||
primary.add_subchunk(version_chunk)
|
primary.add_subchunk(version_chunk)
|
||||||
|
|
||||||
# Init main object info chunk:
|
# Init main object info chunk
|
||||||
object_info = _3ds_chunk(OBJECTINFO)
|
object_info = _3ds_chunk(OBJECTINFO)
|
||||||
mesh_version = _3ds_chunk(MESHVERSION)
|
mesh_version = _3ds_chunk(MESHVERSION)
|
||||||
mesh_version.add_variable("mesh", _3ds_uint(3))
|
mesh_version.add_variable("mesh", _3ds_uint(3))
|
||||||
@ -1233,7 +1223,7 @@ def save(operator,
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
# Make a list of all materials used in the selected meshes (use a dictionary,
|
# Make a list of all materials used in the selected meshes (use a dictionary,
|
||||||
# each material is added once):
|
# each material is added once)
|
||||||
materialDict = {}
|
materialDict = {}
|
||||||
mesh_objects = []
|
mesh_objects = []
|
||||||
|
|
||||||
@ -1270,7 +1260,7 @@ def save(operator,
|
|||||||
ma_ls = data.materials
|
ma_ls = data.materials
|
||||||
ma_ls_len = len(ma_ls)
|
ma_ls_len = len(ma_ls)
|
||||||
|
|
||||||
# get material/image tuples.
|
# get material/image tuples
|
||||||
if data.uv_layers:
|
if data.uv_layers:
|
||||||
if not ma_ls:
|
if not ma_ls:
|
||||||
ma = ma_name = None
|
ma = ma_name = None
|
||||||
@ -1291,7 +1281,7 @@ def save(operator,
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
for ma in ma_ls:
|
for ma in ma_ls:
|
||||||
if ma: # material may be None so check its not.
|
if ma: # material may be None so check its not
|
||||||
materialDict.setdefault((ma.name, None), (ma, None))
|
materialDict.setdefault((ma.name, None), (ma, None))
|
||||||
|
|
||||||
# Why 0 Why!
|
# Why 0 Why!
|
||||||
@ -1300,14 +1290,14 @@ def save(operator,
|
|||||||
f.material_index = 0
|
f.material_index = 0
|
||||||
|
|
||||||
|
|
||||||
# Make material chunks for all materials used in the meshes:
|
# Make material chunks for all materials used in the meshes
|
||||||
for ma_image in materialDict.values():
|
for ma_image in materialDict.values():
|
||||||
object_info.add_subchunk(make_material_chunk(ma_image[0], ma_image[1]))
|
object_info.add_subchunk(make_material_chunk(ma_image[0], ma_image[1]))
|
||||||
|
|
||||||
# Collect translation for transformation matrix
|
# Collect translation for transformation matrix
|
||||||
translation = {}
|
translation = {}
|
||||||
|
|
||||||
# Give all objects a unique ID and build a dictionary from object name to object id:
|
# Give all objects a unique ID and build a dictionary from object name to object id
|
||||||
# name_to_id = {}
|
# name_to_id = {}
|
||||||
|
|
||||||
for ob, data, matrix in mesh_objects:
|
for ob, data, matrix in mesh_objects:
|
||||||
@ -1318,7 +1308,7 @@ def save(operator,
|
|||||||
translation[ob.name] = ob.location
|
translation[ob.name] = ob.location
|
||||||
# name_to_id[ob.name]= len(name_to_id)
|
# name_to_id[ob.name]= len(name_to_id)
|
||||||
|
|
||||||
# Create object chunks for all meshes:
|
# Create object chunks for all meshes
|
||||||
i = 0
|
i = 0
|
||||||
for ob, mesh, matrix in mesh_objects:
|
for ob, mesh, matrix in mesh_objects:
|
||||||
# create a new object chunk
|
# create a new object chunk
|
||||||
@ -1327,12 +1317,11 @@ def save(operator,
|
|||||||
# set the object name
|
# set the object name
|
||||||
object_chunk.add_variable("name", _3ds_string(sane_name(ob.name)))
|
object_chunk.add_variable("name", _3ds_string(sane_name(ob.name)))
|
||||||
|
|
||||||
# make a mesh chunk out of the mesh:
|
# make a mesh chunk out of the mesh
|
||||||
object_chunk.add_subchunk(make_mesh_chunk(ob, mesh, matrix, materialDict, translation))
|
object_chunk.add_subchunk(make_mesh_chunk(ob, mesh, matrix, materialDict, translation))
|
||||||
|
|
||||||
# ensure the mesh has no over sized arrays
|
# Ensure the mesh has no over sized arrays, skip ones that do!
|
||||||
# skip ones that do!, otherwise we cant write since the array size wont
|
# Otherwise we cant write since the array size wont fit into USHORT
|
||||||
# fit into USHORT.
|
|
||||||
if object_chunk.validate():
|
if object_chunk.validate():
|
||||||
object_info.add_subchunk(object_chunk)
|
object_info.add_subchunk(object_chunk)
|
||||||
else:
|
else:
|
||||||
@ -1345,7 +1334,7 @@ def save(operator,
|
|||||||
|
|
||||||
i += i
|
i += i
|
||||||
|
|
||||||
# Create chunks for all empties:
|
# Create chunks for all empties
|
||||||
''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX
|
''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX
|
||||||
for ob in empty_objects:
|
for ob in empty_objects:
|
||||||
# Empties only require a kf object node:
|
# Empties only require a kf object node:
|
||||||
@ -1408,7 +1397,7 @@ def save(operator,
|
|||||||
object_chunk.add_subchunk(camera_chunk)
|
object_chunk.add_subchunk(camera_chunk)
|
||||||
object_info.add_subchunk(object_chunk)
|
object_info.add_subchunk(object_chunk)
|
||||||
|
|
||||||
# Add main object info chunk to primary chunk:
|
# Add main object info chunk to primary chunk
|
||||||
primary.add_subchunk(object_info)
|
primary.add_subchunk(object_info)
|
||||||
|
|
||||||
''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX
|
''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX
|
||||||
@ -1416,27 +1405,27 @@ def save(operator,
|
|||||||
primary.add_subchunk(kfdata)
|
primary.add_subchunk(kfdata)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# At this point, the chunk hierarchy is completely built.
|
# At this point, the chunk hierarchy is completely built
|
||||||
# Check the size:
|
# Check the size
|
||||||
primary.get_size()
|
primary.get_size()
|
||||||
|
|
||||||
# Open the file for writing:
|
# Open the file for writing
|
||||||
file = open(filepath, 'wb')
|
file = open(filepath, 'wb')
|
||||||
|
|
||||||
# Recursively write the chunks to file:
|
# Recursively write the chunks to file
|
||||||
primary.write(file)
|
primary.write(file)
|
||||||
|
|
||||||
# Close the file:
|
# Close the file
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
# Clear name mapping vars, could make locals too
|
# Clear name mapping vars, could make locals too
|
||||||
del name_unique[:]
|
del name_unique[:]
|
||||||
name_mapping.clear()
|
name_mapping.clear()
|
||||||
|
|
||||||
# Debugging only: report the exporting time:
|
# Debugging only: report the exporting time
|
||||||
print("3ds export time: %.2f" % (time.time() - duration))
|
print("3ds export time: %.2f" % (time.time() - duration))
|
||||||
|
|
||||||
# Debugging only: dump the chunk hierarchy:
|
# Debugging only: dump the chunk hierarchy
|
||||||
# primary.dump()
|
# primary.dump()
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Sun Position",
|
"name": "Sun Position",
|
||||||
"author": "Michael Martin, Damien Picard",
|
"author": "Michael Martin, Damien Picard",
|
||||||
"version": (3, 5, 0),
|
"version": (3, 5, 2),
|
||||||
"blender": (3, 2, 0),
|
"blender": (3, 2, 0),
|
||||||
"location": "World > Sun Position",
|
"location": "World > Sun Position",
|
||||||
"description": "Show sun position with objects and/or sky texture",
|
"description": "Show sun position with objects and/or sky texture",
|
||||||
|
@ -10,34 +10,8 @@ from mathutils import Vector
|
|||||||
from math import sqrt, pi, atan2, asin
|
from math import sqrt, pi, atan2, asin
|
||||||
|
|
||||||
|
|
||||||
vertex_shader = '''
|
image_shader = gpu.shader.from_builtin('2D_IMAGE_COLOR')
|
||||||
uniform mat4 ModelViewProjectionMatrix;
|
line_shader = gpu.shader.from_builtin('2D_FLAT_COLOR')
|
||||||
|
|
||||||
/* Keep in sync with intern/opencolorio/gpu_shader_display_transform_vertex.glsl */
|
|
||||||
in vec2 texCoord;
|
|
||||||
in vec2 pos;
|
|
||||||
out vec2 texCoord_interp;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
gl_Position = ModelViewProjectionMatrix * vec4(pos.xy, 0.0f, 1.0f);
|
|
||||||
gl_Position.z = 1.0f;
|
|
||||||
texCoord_interp = texCoord;
|
|
||||||
}'''
|
|
||||||
|
|
||||||
fragment_shader = '''
|
|
||||||
in vec2 texCoord_interp;
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
uniform sampler2D image;
|
|
||||||
uniform float exposure;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
fragColor = texture(image, texCoord_interp) * vec4(exposure, exposure, exposure, 1.0f);
|
|
||||||
}'''
|
|
||||||
|
|
||||||
# shader = gpu.types.GPUShader(vertex_shader, fragment_shader)
|
|
||||||
|
|
||||||
|
|
||||||
def draw_callback_px(self, context):
|
def draw_callback_px(self, context):
|
||||||
@ -49,9 +23,6 @@ def draw_callback_px(self, context):
|
|||||||
if self.area != context.area:
|
if self.area != context.area:
|
||||||
return
|
return
|
||||||
|
|
||||||
if image.gl_load():
|
|
||||||
raise Exception()
|
|
||||||
|
|
||||||
bottom = 0
|
bottom = 0
|
||||||
top = context.area.height
|
top = context.area.height
|
||||||
right = context.area.width
|
right = context.area.width
|
||||||
@ -59,39 +30,36 @@ def draw_callback_px(self, context):
|
|||||||
position = Vector((right, top)) / 2 + self.offset
|
position = Vector((right, top)) / 2 + self.offset
|
||||||
scale = Vector((context.area.width, context.area.width / 2)) * self.scale
|
scale = Vector((context.area.width, context.area.width / 2)) * self.scale
|
||||||
|
|
||||||
shader = gpu.types.GPUShader(vertex_shader, fragment_shader)
|
|
||||||
|
|
||||||
coords = ((-0.5, -0.5), (0.5, -0.5), (0.5, 0.5), (-0.5, 0.5))
|
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))
|
uv_coords = ((0, 0), (1, 0), (1, 1), (0, 1))
|
||||||
batch = batch_for_shader(shader, 'TRI_FAN',
|
batch = batch_for_shader(image_shader, 'TRI_FAN',
|
||||||
{"pos": coords, "texCoord": uv_coords})
|
{"pos": coords, "texCoord": uv_coords})
|
||||||
|
|
||||||
with gpu.matrix.push_pop():
|
with gpu.matrix.push_pop():
|
||||||
gpu.matrix.translate(position)
|
gpu.matrix.translate(position)
|
||||||
gpu.matrix.scale(scale)
|
gpu.matrix.scale(scale)
|
||||||
|
|
||||||
shader.bind()
|
image_shader.bind()
|
||||||
shader.uniform_sampler("image", texture)
|
image_shader.uniform_sampler("image", texture)
|
||||||
shader.uniform_float("exposure", self.exposure)
|
image_shader.uniform_float("color", (self.exposure, self.exposure, self.exposure, 1.0))
|
||||||
batch.draw(shader)
|
batch.draw(image_shader)
|
||||||
|
|
||||||
# Crosshair
|
# Crosshair
|
||||||
# vertical
|
# vertical
|
||||||
coords = ((self.mouse_position[0], bottom), (self.mouse_position[0], top))
|
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(line_shader, 'LINES',
|
||||||
batch = batch_for_shader(shader, 'LINES',
|
|
||||||
{"pos": coords, "color": colors})
|
{"pos": coords, "color": colors})
|
||||||
shader.bind()
|
line_shader.bind()
|
||||||
batch.draw(shader)
|
batch.draw(line_shader)
|
||||||
|
|
||||||
# horizontal
|
# horizontal
|
||||||
if bottom <= self.mouse_position[1] <= top:
|
if bottom <= self.mouse_position[1] <= top:
|
||||||
coords = ((0, self.mouse_position[1]), (context.area.width, self.mouse_position[1]))
|
coords = ((0, self.mouse_position[1]), (context.area.width, self.mouse_position[1]))
|
||||||
batch = batch_for_shader(shader, 'LINES',
|
batch = batch_for_shader(line_shader, 'LINES',
|
||||||
{"pos": coords, "color": colors})
|
{"pos": coords, "color": colors})
|
||||||
shader.bind()
|
line_shader.bind()
|
||||||
batch.draw(shader)
|
batch.draw(line_shader)
|
||||||
|
|
||||||
|
|
||||||
class SUNPOS_OT_ShowHdr(bpy.types.Operator):
|
class SUNPOS_OT_ShowHdr(bpy.types.Operator):
|
||||||
|
@ -311,7 +311,7 @@ class SunPosAddonPreferences(AddonPreferences):
|
|||||||
box = layout.box()
|
box = layout.box()
|
||||||
col = box.column()
|
col = box.column()
|
||||||
|
|
||||||
col.label(text="Show options or labels:")
|
col.label(text="Show options and info:")
|
||||||
flow = col.grid_flow(columns=0, even_columns=True, even_rows=False, align=False)
|
flow = col.grid_flow(columns=0, even_columns=True, even_rows=False, align=False)
|
||||||
flow.prop(self, "show_refraction")
|
flow.prop(self, "show_refraction")
|
||||||
flow.prop(self, "show_overlays")
|
flow.prop(self, "show_overlays")
|
||||||
|
@ -432,10 +432,10 @@ translations_tuple = (
|
|||||||
("fr_FR", "Projection inconnue",
|
("fr_FR", "Projection inconnue",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Show options or labels:"),
|
(("*", "Show options and info:"),
|
||||||
(("scripts/addons/sun_position/properties.py:297",),
|
(("scripts/addons/sun_position/properties.py:297",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Afficher les options et étiquettes :",
|
("fr_FR", "Afficher les options et infos :",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "ERROR: Could not parse coordinates"),
|
(("*", "ERROR: Could not parse coordinates"),
|
||||||
|
Loading…
Reference in New Issue
Block a user