add null normal support in bme. fix rail cret draw()
This commit is contained in:
parent
f9502fe2d4
commit
31aa5c3127
@ -50,9 +50,15 @@ class SharedRailSectionInputProperty():
|
||||
|
||||
@param force_monorail[in] Force this draw method for monorail if True, or for rail if False. Accept None if you want user to choose it.
|
||||
"""
|
||||
# draw title
|
||||
layout = layout.box()
|
||||
layout.label(text = 'Section')
|
||||
|
||||
if force_monorail is None:
|
||||
# show picker to allow user pick
|
||||
layout.prop(self, 'rail_type', expand = True)
|
||||
# force it show horizontal
|
||||
row = layout.row()
|
||||
row.prop(self, 'rail_type', expand = True)
|
||||
# show radius
|
||||
layout.prop(self, "rail_radius")
|
||||
# show span for rail
|
||||
@ -92,6 +98,9 @@ class SharedRailCapInputProperty():
|
||||
) # type: ignore
|
||||
|
||||
def draw_rail_cap_input(self, layout: bpy.types.UILayout) -> None:
|
||||
# draw title
|
||||
layout = layout.box()
|
||||
layout.label(text = 'Cap')
|
||||
row = layout.row()
|
||||
row.prop(self, "rail_start_cap", toggle = 1)
|
||||
row.prop(self, "rail_end_cap", toggle = 1)
|
||||
@ -116,6 +125,9 @@ class SharedStraightRailInputProperty():
|
||||
) # type: ignore
|
||||
|
||||
def draw_straight_rail_input(self, layout: bpy.types.UILayout) -> None:
|
||||
# draw title
|
||||
layout = layout.box()
|
||||
layout.label(text = 'Straight Rail')
|
||||
layout.prop(self, "rail_length")
|
||||
|
||||
def general_get_rail_length(self) -> float:
|
||||
@ -162,6 +174,10 @@ class SharedScrewRailInputProperty():
|
||||
) # type: ignore
|
||||
|
||||
def draw_screw_rail_input(self, layout: bpy.types.UILayout, show_for_screw: bool) -> None:
|
||||
# draw title
|
||||
layout = layout.box()
|
||||
layout.label(text = 'Screw Rail')
|
||||
|
||||
if show_for_screw:
|
||||
# screw do not need angle property
|
||||
layout.prop(self, "rail_screw_screw")
|
||||
@ -375,6 +391,11 @@ def _rail_creator_wrapper(fct_poly_cret: typing.Callable[[bmesh.types.BMesh], No
|
||||
bm.to_mesh(mesh)
|
||||
bm.free()
|
||||
|
||||
# setup smooth for mesh
|
||||
mesh.use_auto_smooth = True
|
||||
mesh.auto_smooth_angle = math.radians(50)
|
||||
mesh.shade_smooth()
|
||||
|
||||
# create object and assoc with it
|
||||
# create info first
|
||||
rail_info: UTIL_naming_convension.BallanceObjectInfo = UTIL_naming_convension.BallanceObjectInfo.create_from_others(
|
||||
|
@ -303,32 +303,61 @@ def create_bme_struct(
|
||||
# create mtl slot remap to help following mesh adding
|
||||
# because mesh writer do not accept string format mtl slot visiting,
|
||||
# it only accept int based mtl slot index.
|
||||
#
|
||||
# Also we build face used mtl slot index at the same time.
|
||||
# So we do not analyse texture field again when providing face data.
|
||||
# The result is in `prebuild_face_mtl_idx` and please note it will store all face's mtl index.
|
||||
# For example: if face 0 is skipped and face 1 is used, the first entry in `prebuild_face_mtl_idx`
|
||||
# will be the mtl slot index used by face 0, not 1. And its length is equal to the face count.
|
||||
# However, because face 0 is skipped, so the entry is not used and default set to 0.
|
||||
#
|
||||
# NOTE: since Python 3.6, the item of builtin dict is ordered by inserting order.
|
||||
# we rely on this to implement following features
|
||||
# we rely on this to implement following features.
|
||||
mtl_remap: dict[str, int] = {}
|
||||
prebuild_face_mtl_idx: list[int] = [0] * len(proto[TOKEN_FACES])
|
||||
for face_idx in valid_face_idx:
|
||||
# eval mtl name
|
||||
mtl_name: str = _eval_others(proto[TOKEN_FACES][face_idx][TOKEN_FACES_TEXTURE], params)
|
||||
# add into remap if not exist
|
||||
# try insert into remap and record to face mtl idx
|
||||
if mtl_name not in mtl_remap:
|
||||
# record index
|
||||
prebuild_face_mtl_idx[face_idx] = len(mtl_remap)
|
||||
# add into remap if not exist
|
||||
mtl_remap[mtl_name] = len(mtl_remap)
|
||||
else:
|
||||
# if existing, no need to add into remap
|
||||
# but we need get its index from remap
|
||||
prebuild_face_mtl_idx[face_idx] = mtl_remap.get(mtl_name, 0)
|
||||
|
||||
# pre-compute vertices data because we may need used later.
|
||||
# Because if face normal data is null, it mean that we need to compute it
|
||||
# by given vertices.
|
||||
# The computed vertices is stored in `prebuild_vec_data` and is NOT like `prebuild_face_mtl_idx`,
|
||||
# we only store valid one in `prebuild_vec_data`.
|
||||
prebuild_vec_data: list[UTIL_virtools_types.ConstVxVector3 | None] = []
|
||||
cache_bv: mathutils.Vector = mathutils.Vector((0, 0, 0))
|
||||
for vec_idx in valid_vec_idx:
|
||||
# but it need mul with transform matrix
|
||||
cache_bv.x, cache_bv.y, cache_bv.z = _eval_others(proto[TOKEN_VERTICES][vec_idx][TOKEN_VERTICES_DATA], params)
|
||||
# mul with transform matrix
|
||||
cache_bv = typing.cast(mathutils.Vector, transform @ cache_bv)
|
||||
# get result
|
||||
prebuild_vec_data.append((cache_bv.x, cache_bv.y, cache_bv.z))
|
||||
|
||||
# prepare mesh part data
|
||||
mesh_part: UTIL_blender_mesh.MeshWriterIngredient = UTIL_blender_mesh.MeshWriterIngredient()
|
||||
def vpos_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]:
|
||||
bv: mathutils.Vector = mathutils.Vector((0, 0, 0))
|
||||
# simply get data from prebuild vec data
|
||||
v: UTIL_virtools_types.VxVector3 = UTIL_virtools_types.VxVector3()
|
||||
for vec_idx in valid_vec_idx:
|
||||
# BME no need to convert co system
|
||||
# but it need mul with transform matrix
|
||||
bv.x, bv.y, bv.z = _eval_others(proto[TOKEN_VERTICES][vec_idx][TOKEN_VERTICES_DATA], params)
|
||||
bv = transform @ bv
|
||||
for vec_data in prebuild_vec_data:
|
||||
# skip skipped vertices
|
||||
if vec_data is None: continue
|
||||
# yield result
|
||||
v.x, v.y, v.z = bv.x, bv.y, bv.z
|
||||
v.x, v.y, v.z = vec_data
|
||||
yield v
|
||||
mesh_part.mVertexPosition = vpos_iterator()
|
||||
def vnml_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]:
|
||||
# calc normal used transform first
|
||||
# prepare normal used transform first
|
||||
# ref: https://zhuanlan.zhihu.com/p/96717729
|
||||
nml_transform: mathutils.Matrix = transform.inverted_safe().transposed()
|
||||
# prepare vars
|
||||
@ -336,15 +365,34 @@ def create_bme_struct(
|
||||
v: UTIL_virtools_types.VxVector3 = UTIL_virtools_types.VxVector3()
|
||||
for face_idx in valid_face_idx:
|
||||
face_data: dict[str, typing.Any] = proto[TOKEN_FACES][face_idx]
|
||||
for i in range(len(face_data[TOKEN_FACES_INDICES])):
|
||||
# BME normals need transform by matrix first,
|
||||
bv.x, bv.y, bv.z = _eval_others(face_data[TOKEN_FACES_NORMALS][i], params)
|
||||
bv = nml_transform @ bv
|
||||
# then normalize it
|
||||
bv.normalize()
|
||||
# yield result
|
||||
face_nml_data: list[str] | None = face_data[TOKEN_FACES_NORMALS]
|
||||
if face_nml_data is None:
|
||||
# nml is null, we need compute by ourselves
|
||||
# get first 3 entries in indices list as the compution ref
|
||||
face_indices_data: list[int] = face_data[TOKEN_FACES_INDICES]
|
||||
# compute it by getting vertices info from prebuild vertices data
|
||||
# because the normals is computed from transformed vertices
|
||||
# so no need to correct its by normal transform.
|
||||
bv.x, bv.y, bv.z = _compute_normals(
|
||||
typing.cast(UTIL_virtools_types.ConstVxVector3, prebuild_vec_data[face_indices_data[0]]),
|
||||
typing.cast(UTIL_virtools_types.ConstVxVector3, prebuild_vec_data[face_indices_data[1]]),
|
||||
typing.cast(UTIL_virtools_types.ConstVxVector3, prebuild_vec_data[face_indices_data[2]])
|
||||
)
|
||||
# yield result with N times (N = indices count)
|
||||
v.x, v.y, v.z = bv.x, bv.y, bv.z
|
||||
yield v
|
||||
for _ in range(len(face_indices_data)):
|
||||
yield v
|
||||
else:
|
||||
# nml is given, analyse programable fields
|
||||
for mtl_data in face_nml_data:
|
||||
# BME normals need transform by matrix first,
|
||||
bv.x, bv.y, bv.z = _eval_others(mtl_data, params)
|
||||
bv = typing.cast(mathutils.Vector, nml_transform @ bv)
|
||||
# then normalize it
|
||||
bv.normalize()
|
||||
# yield result
|
||||
v.x, v.y, v.z = bv.x, bv.y, bv.z
|
||||
yield v
|
||||
mesh_part.mVertexNormal = vnml_iterator()
|
||||
def vuv_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector2]:
|
||||
v: UTIL_virtools_types.VxVector2 = UTIL_virtools_types.VxVector2()
|
||||
@ -396,8 +444,7 @@ def create_bme_struct(
|
||||
face_counter += indices_count
|
||||
|
||||
# fill texture data
|
||||
mtl_name: str = _eval_others(face_data[TOKEN_FACES_TEXTURE], params)
|
||||
f.mMtlIdx = mtl_remap[mtl_name]
|
||||
f.mMtlIdx = prebuild_face_mtl_idx[face_idx]
|
||||
|
||||
# return data once
|
||||
yield f
|
||||
@ -428,3 +475,28 @@ def create_bme_struct(
|
||||
)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Creation Assist Functions
|
||||
|
||||
def _compute_normals(
|
||||
point1: UTIL_virtools_types.ConstVxVector3,
|
||||
point2: UTIL_virtools_types.ConstVxVector3,
|
||||
point3: UTIL_virtools_types.ConstVxVector3) -> UTIL_virtools_types.ConstVxVector3:
|
||||
# build vector
|
||||
p1: mathutils.Vector = mathutils.Vector(point1)
|
||||
p2: mathutils.Vector = mathutils.Vector(point2)
|
||||
p3: mathutils.Vector = mathutils.Vector(point3)
|
||||
|
||||
vector1: mathutils.Vector = p2 - p1
|
||||
vector2: mathutils.Vector = p3 - p2
|
||||
|
||||
# do vector x mutiply
|
||||
# vector1 x vector2
|
||||
corss_mul: mathutils.Vector = vector1.cross(vector2)
|
||||
|
||||
# do a normalization
|
||||
corss_mul.normalize()
|
||||
return (corss_mul.x, corss_mul.y, corss_mul.z)
|
||||
|
||||
|
||||
#endregion
|
||||
|
@ -68,12 +68,7 @@
|
||||
"(uv_border_texture, uv_length)",
|
||||
"(uv_border_texture, 0)"
|
||||
],
|
||||
"normals": [
|
||||
"(0, sink, 2.5)",
|
||||
"(0, sink, 2.5)",
|
||||
"(0, sink, 2.5)",
|
||||
"(0, sink, 2.5)"
|
||||
]
|
||||
"normals": null
|
||||
}
|
||||
],
|
||||
"instances": [
|
||||
|
@ -75,11 +75,7 @@
|
||||
"(NXNY_uv, 0)",
|
||||
"(PXPY_uv, 0)"
|
||||
],
|
||||
"normals": [
|
||||
"(0, PXPY_sink - NXNY_sink, 2.5)",
|
||||
"(0, PXPY_sink - NXNY_sink, 2.5)",
|
||||
"(0, PXPY_sink - NXNY_sink, 2.5)"
|
||||
]
|
||||
"normals": null
|
||||
},
|
||||
{
|
||||
"skip": "not face[0]",
|
||||
@ -90,11 +86,7 @@
|
||||
"(PXPY_uv, 0)",
|
||||
"(NXNY_uv, 0)"
|
||||
],
|
||||
"normals": [
|
||||
"(PXPY_sink - NXNY_sink, 0, 2.5)",
|
||||
"(PXPY_sink - NXNY_sink, 0, 2.5)",
|
||||
"(PXPY_sink - NXNY_sink, 0, 2.5)"
|
||||
]
|
||||
"normals": null
|
||||
}
|
||||
],
|
||||
"instances": [
|
||||
|
@ -92,12 +92,7 @@
|
||||
"(uv_height - uv_right_sink, uv_length)",
|
||||
"(0, uv_length)"
|
||||
],
|
||||
"normals": [
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)"
|
||||
]
|
||||
"normals": null
|
||||
},
|
||||
{
|
||||
"skip": "skip_long_side",
|
||||
@ -109,12 +104,7 @@
|
||||
"(1 - uv_left_sink, uv_length)",
|
||||
"(0, uv_length)"
|
||||
],
|
||||
"normals": [
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)"
|
||||
]
|
||||
"normals": null
|
||||
},
|
||||
{
|
||||
"skip": "skip_long_side",
|
||||
@ -126,12 +116,7 @@
|
||||
"(uv_height - 1.0, uv_length)",
|
||||
"(0, uv_length)"
|
||||
],
|
||||
"normals": [
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)"
|
||||
]
|
||||
"normals": null
|
||||
}
|
||||
],
|
||||
"instances": []
|
||||
@ -189,12 +174,7 @@
|
||||
"(uv_width, uv_length)",
|
||||
"(0, uv_length)"
|
||||
],
|
||||
"normals": [
|
||||
"(0, 0, -1)",
|
||||
"(0, 0, -1)",
|
||||
"(0, 0, -1)",
|
||||
"(0, 0, -1)"
|
||||
]
|
||||
"normals": null
|
||||
}
|
||||
],
|
||||
"instances": []
|
||||
|
@ -68,12 +68,7 @@
|
||||
"(1, 1)",
|
||||
"(0, 1)"
|
||||
],
|
||||
"normals": [
|
||||
"(0, 0, 1)",
|
||||
"(0, 0, 1)",
|
||||
"(0, 0, 1)",
|
||||
"(0, 0, 1)"
|
||||
]
|
||||
"normals": null
|
||||
},
|
||||
{
|
||||
"skip": "(not face[1]) or height == 0.0",
|
||||
@ -85,12 +80,7 @@
|
||||
"(1, 1)",
|
||||
"(0, 1)"
|
||||
],
|
||||
"normals": [
|
||||
"(0, 0, -1)",
|
||||
"(0, 0, -1)",
|
||||
"(0, 0, -1)",
|
||||
"(0, 0, -1)"
|
||||
]
|
||||
"normals": null
|
||||
},
|
||||
{
|
||||
"skip": "(not face[2]) or height == 0.0",
|
||||
@ -102,12 +92,7 @@
|
||||
"(uv_height, 1)",
|
||||
"(0, 1)"
|
||||
],
|
||||
"normals": [
|
||||
"(-1, 0, 0)",
|
||||
"(-1, 0, 0)",
|
||||
"(-1, 0, 0)",
|
||||
"(-1, 0, 0)"
|
||||
]
|
||||
"normals": null
|
||||
},
|
||||
{
|
||||
"skip": "(not face[3]) or height == 0.0",
|
||||
@ -119,12 +104,7 @@
|
||||
"(uv_height, 1)",
|
||||
"(0, 1)"
|
||||
],
|
||||
"normals": [
|
||||
"(1, 0, 0)",
|
||||
"(1, 0, 0)",
|
||||
"(1, 0, 0)",
|
||||
"(1, 0, 0)"
|
||||
]
|
||||
"normals": null
|
||||
},
|
||||
{
|
||||
"skip": "(not face[4]) or height == 0.0",
|
||||
@ -136,12 +116,7 @@
|
||||
"(uv_height, 1)",
|
||||
"(0, 1)"
|
||||
],
|
||||
"normals": [
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)",
|
||||
"(0, -1, 0)"
|
||||
]
|
||||
"normals": null
|
||||
},
|
||||
{
|
||||
"skip": "(not face[5]) or height == 0.0",
|
||||
@ -153,12 +128,7 @@
|
||||
"(uv_height, 1)",
|
||||
"(0, 1)"
|
||||
],
|
||||
"normals": [
|
||||
"(0, 1, 0)",
|
||||
"(0, 1, 0)",
|
||||
"(0, 1, 0)",
|
||||
"(0, 1, 0)"
|
||||
]
|
||||
"normals": null
|
||||
}
|
||||
],
|
||||
"instances": []
|
||||
|
Loading…
x
Reference in New Issue
Block a user