feat: add blc params in exporter. fix bme.
- add ballance params section and successive switch in virtools file exporter to allow user manually cancel sector group ensurance which give user a way to export component, not the whole level. - add mirror matrix detection in bme creation. a mirror matrix will reverse triangle indice order. we need reverse it again when facing mirror matrix. this resolves the issue when applying term 3. - use mirror, not rotation to create straight floor in bme which give a better looks in game.
This commit is contained in:
parent
3a1a0fb0f6
commit
07298fd21c
@ -20,19 +20,26 @@ class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtool
|
|||||||
description = "Decide how texture saved if texture is specified as Use Global as its Save Options.",
|
description = "Decide how texture saved if texture is specified as Use Global as its Save Options.",
|
||||||
items = _g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.generate_items(),
|
items = _g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.generate_items(),
|
||||||
default = _g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.to_selection(UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_EXTERNAL)
|
default = _g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.to_selection(UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS.CKTEXTURE_EXTERNAL)
|
||||||
)
|
) # type: ignore
|
||||||
|
|
||||||
use_compress: bpy.props.BoolProperty(
|
use_compress: bpy.props.BoolProperty(
|
||||||
name="Use Compress",
|
name="Use Compress",
|
||||||
|
description = "Whether use ZLib to compress result when saving composition.",
|
||||||
default = True,
|
default = True,
|
||||||
)
|
) # type: ignore
|
||||||
|
|
||||||
compress_level: bpy.props.IntProperty(
|
compress_level: bpy.props.IntProperty(
|
||||||
name = "Compress Level",
|
name = "Compress Level",
|
||||||
description = "The ZLib compress level used by Virtools Engine when saving composition.",
|
description = "The ZLib compress level used by Virtools Engine when saving composition.",
|
||||||
min = 1, max = 9,
|
min = 1, max = 9,
|
||||||
default = 5,
|
default = 5,
|
||||||
)
|
) # type: ignore
|
||||||
|
|
||||||
|
successive_sector: bpy.props.BoolProperty(
|
||||||
|
name="Successive Sector",
|
||||||
|
description = "Whether order exporter to use document specified sector count to make sure sector is successive.",
|
||||||
|
default = True,
|
||||||
|
) # type: ignore
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(self, context):
|
def poll(self, context):
|
||||||
@ -59,6 +66,7 @@ class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtool
|
|||||||
_g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.get_selection(self.texture_save_opt),
|
_g_EnumHelper_CK_TEXTURE_SAVEOPTIONS.get_selection(self.texture_save_opt),
|
||||||
self.use_compress,
|
self.use_compress,
|
||||||
self.compress_level,
|
self.compress_level,
|
||||||
|
self.successive_sector,
|
||||||
objls
|
objls
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -86,8 +94,11 @@ class BBP_OT_export_virtools(bpy.types.Operator, UTIL_file_browser.ExportVirtool
|
|||||||
|
|
||||||
# show sector info to notice user
|
# show sector info to notice user
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
layout.label(text = 'Ballance Params')
|
||||||
|
box = layout.box()
|
||||||
map_info: PROP_ballance_map_info.RawBallanceMapInfo = PROP_ballance_map_info.get_raw_ballance_map_info(bpy.context.scene)
|
map_info: PROP_ballance_map_info.RawBallanceMapInfo = PROP_ballance_map_info.get_raw_ballance_map_info(bpy.context.scene)
|
||||||
layout.label(text = f'Map Sectors: {map_info.mSectorCount}')
|
box.prop(self, 'successive_sector')
|
||||||
|
box.label(text = f'Map Sectors: {map_info.mSectorCount}')
|
||||||
|
|
||||||
_TObj3dPair = tuple[bpy.types.Object, bmap.BM3dObject]
|
_TObj3dPair = tuple[bpy.types.Object, bmap.BM3dObject]
|
||||||
_TMeshPair = tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh]
|
_TMeshPair = tuple[bpy.types.Object, bpy.types.Mesh, bmap.BMMesh]
|
||||||
@ -100,6 +111,7 @@ def _export_virtools(
|
|||||||
texture_save_opt_: UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS,
|
texture_save_opt_: UTIL_virtools_types.CK_TEXTURE_SAVEOPTIONS,
|
||||||
use_compress_: bool,
|
use_compress_: bool,
|
||||||
compress_level_: int,
|
compress_level_: int,
|
||||||
|
successive_sector_: bool,
|
||||||
export_objects: tuple[bpy.types.Object, ...]
|
export_objects: tuple[bpy.types.Object, ...]
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
@ -119,7 +131,7 @@ def _export_virtools(
|
|||||||
obj3d_crets: tuple[_TObj3dPair, ...] = _prepare_virtools_3dobjects(
|
obj3d_crets: tuple[_TObj3dPair, ...] = _prepare_virtools_3dobjects(
|
||||||
writer, progress, export_objects)
|
writer, progress, export_objects)
|
||||||
# export group and 3dobject by prepared 3dobject
|
# export group and 3dobject by prepared 3dobject
|
||||||
_export_virtools_groups(writer, progress, obj3d_crets)
|
_export_virtools_groups(writer, progress, successive_sector_, obj3d_crets)
|
||||||
mesh_crets: tuple[_TMeshPair, ...] = _export_virtools_3dobjects(
|
mesh_crets: tuple[_TMeshPair, ...] = _export_virtools_3dobjects(
|
||||||
writer, progress, obj3d_crets)
|
writer, progress, obj3d_crets)
|
||||||
# export mesh
|
# export mesh
|
||||||
@ -168,6 +180,7 @@ def _prepare_virtools_3dobjects(
|
|||||||
def _export_virtools_groups(
|
def _export_virtools_groups(
|
||||||
writer: bmap.BMFileWriter,
|
writer: bmap.BMFileWriter,
|
||||||
progress: ProgressReport,
|
progress: ProgressReport,
|
||||||
|
successive_sector: bool,
|
||||||
obj3d_crets: tuple[_TObj3dPair, ...]
|
obj3d_crets: tuple[_TObj3dPair, ...]
|
||||||
) -> None:
|
) -> None:
|
||||||
# create virtools group
|
# create virtools group
|
||||||
@ -175,7 +188,7 @@ def _export_virtools_groups(
|
|||||||
# start saving
|
# start saving
|
||||||
progress.enter_substeps(len(obj3d_crets), "Saving Groups")
|
progress.enter_substeps(len(obj3d_crets), "Saving Groups")
|
||||||
|
|
||||||
# create sector group first
|
# create sector group first if user ordered
|
||||||
# This step is designed for ensure that the created sector group is successive.
|
# This step is designed for ensure that the created sector group is successive.
|
||||||
#
|
#
|
||||||
# Due to the design of Ballance, Ballance rely on checking the existance of Sector_XX to get how many sectors this map have.
|
# Due to the design of Ballance, Ballance rely on checking the existance of Sector_XX to get how many sectors this map have.
|
||||||
@ -183,14 +196,16 @@ def _export_virtools_groups(
|
|||||||
# or be ended at a accident sector.
|
# or be ended at a accident sector.
|
||||||
#
|
#
|
||||||
# So we create all needed sector group in here to make sure exported virtools file can be read by Ballancde correctly.
|
# So we create all needed sector group in here to make sure exported virtools file can be read by Ballancde correctly.
|
||||||
map_info: PROP_ballance_map_info.RawBallanceMapInfo = PROP_ballance_map_info.get_raw_ballance_map_info(bpy.context.scene)
|
if successive_sector:
|
||||||
for i in range(map_info.mSectorCount):
|
map_info: PROP_ballance_map_info.RawBallanceMapInfo
|
||||||
gp_name: str = UTIL_naming_convension.build_name_from_sector_index(i + 1)
|
map_info = PROP_ballance_map_info.get_raw_ballance_map_info(bpy.context.scene)
|
||||||
vtgroup: bmap.BMGroup | None = group_cret_map.get(gp_name, None)
|
for i in range(map_info.mSectorCount):
|
||||||
if vtgroup is None:
|
gp_name: str = UTIL_naming_convension.build_name_from_sector_index(i + 1)
|
||||||
vtgroup = writer.create_group()
|
vtgroup: bmap.BMGroup | None = group_cret_map.get(gp_name, None)
|
||||||
vtgroup.set_name(gp_name)
|
if vtgroup is None:
|
||||||
group_cret_map[gp_name] = vtgroup
|
vtgroup = writer.create_group()
|
||||||
|
vtgroup.set_name(gp_name)
|
||||||
|
group_cret_map[gp_name] = vtgroup
|
||||||
|
|
||||||
for obj3d, vtobj3d in obj3d_crets:
|
for obj3d, vtobj3d in obj3d_crets:
|
||||||
# open group visitor
|
# open group visitor
|
||||||
|
@ -344,6 +344,12 @@ def create_bme_struct(
|
|||||||
cache_bv = typing.cast(mathutils.Vector, transform @ cache_bv)
|
cache_bv = typing.cast(mathutils.Vector, transform @ cache_bv)
|
||||||
# get result
|
# get result
|
||||||
prebuild_vec_data.append((cache_bv.x, cache_bv.y, cache_bv.z))
|
prebuild_vec_data.append((cache_bv.x, cache_bv.y, cache_bv.z))
|
||||||
|
|
||||||
|
# Check whether given transform is mirror matrix
|
||||||
|
# because mirror matrix will reverse triangle indice order.
|
||||||
|
# If matrix is mirror matrix, we need reverse it again in following procession,
|
||||||
|
# including getting uv, calculating normal and providing face data.
|
||||||
|
mirror_matrix: bool = _is_mirror_matrix(transform)
|
||||||
|
|
||||||
# prepare mesh part data
|
# prepare mesh part data
|
||||||
mesh_part: UTIL_blender_mesh.MeshWriterIngredient = UTIL_blender_mesh.MeshWriterIngredient()
|
mesh_part: UTIL_blender_mesh.MeshWriterIngredient = UTIL_blender_mesh.MeshWriterIngredient()
|
||||||
@ -370,7 +376,12 @@ def create_bme_struct(
|
|||||||
if face_nml_data is None:
|
if face_nml_data is None:
|
||||||
# nml is null, we need compute by ourselves
|
# nml is null, we need compute by ourselves
|
||||||
# get first 3 entries in indices list as the compution ref
|
# get first 3 entries in indices list as the compution ref
|
||||||
face_indices_data: list[int] = face_data[TOKEN_FACES_INDICES]
|
# please note that we may need reverse it
|
||||||
|
face_indices_data: list[int]
|
||||||
|
if mirror_matrix:
|
||||||
|
face_indices_data = face_data[TOKEN_FACES_INDICES][::-1]
|
||||||
|
else:
|
||||||
|
face_indices_data = face_data[TOKEN_FACES_INDICES][:]
|
||||||
# compute it by getting vertices info from prebuild vertices data
|
# compute it by getting vertices info from prebuild vertices data
|
||||||
# because the normals is computed from transformed vertices
|
# because the normals is computed from transformed vertices
|
||||||
# so no need to correct its by normal transform.
|
# so no need to correct its by normal transform.
|
||||||
@ -399,7 +410,9 @@ def create_bme_struct(
|
|||||||
v: UTIL_virtools_types.VxVector2 = UTIL_virtools_types.VxVector2()
|
v: UTIL_virtools_types.VxVector2 = UTIL_virtools_types.VxVector2()
|
||||||
for face_idx in valid_face_idx:
|
for face_idx in valid_face_idx:
|
||||||
face_data: dict[str, typing.Any] = proto[TOKEN_FACES][face_idx]
|
face_data: dict[str, typing.Any] = proto[TOKEN_FACES][face_idx]
|
||||||
for i in range(len(face_data[TOKEN_FACES_INDICES])):
|
# iterate uv list considering mirror matrix
|
||||||
|
indices_count: int = len(face_data[TOKEN_FACES_INDICES])
|
||||||
|
for i in (range(indices_count)[::-1] if mirror_matrix else range(indices_count)):
|
||||||
# BME uv do not need any extra process
|
# BME uv do not need any extra process
|
||||||
v.x, v.y = _eval_others(face_data[TOKEN_FACES_UVS][i], params)
|
v.x, v.y = _eval_others(face_data[TOKEN_FACES_UVS][i], params)
|
||||||
yield v
|
yield v
|
||||||
@ -424,8 +437,13 @@ def create_bme_struct(
|
|||||||
# get face data
|
# get face data
|
||||||
face_data: dict[str, typing.Any] = proto[TOKEN_FACES][face_idx]
|
face_data: dict[str, typing.Any] = proto[TOKEN_FACES][face_idx]
|
||||||
|
|
||||||
|
# get face indices considering the mirror matrix
|
||||||
|
face_indices: list[int]
|
||||||
|
if mirror_matrix:
|
||||||
|
face_indices = face_data[TOKEN_FACES_INDICES][::-1]
|
||||||
|
else:
|
||||||
|
face_indices = face_data[TOKEN_FACES_INDICES][:]
|
||||||
# calc indices count
|
# calc indices count
|
||||||
face_indices: list[int] = face_data[TOKEN_FACES_INDICES]
|
|
||||||
indices_count: int = len(face_indices)
|
indices_count: int = len(face_indices)
|
||||||
# resize face data to fulfill req
|
# resize face data to fulfill req
|
||||||
while len(f.mIndices) > indices_count:
|
while len(f.mIndices) > indices_count:
|
||||||
@ -499,5 +517,18 @@ def _compute_normals(
|
|||||||
corss_mul.normalize()
|
corss_mul.normalize()
|
||||||
return (corss_mul.x, corss_mul.y, corss_mul.z)
|
return (corss_mul.x, corss_mul.y, corss_mul.z)
|
||||||
|
|
||||||
|
def _is_mirror_matrix(mat: mathutils.Matrix) -> bool:
|
||||||
|
"""
|
||||||
|
Reflection matrix (aka. mirror matrix) is a special scaling matrix.
|
||||||
|
In this matrix, 1 or 3 scaling factor is minus number.
|
||||||
|
|
||||||
|
Mirror matrix will cause the inverse of triangle indice order.
|
||||||
|
So we need detect it and re-reverse when creating bm struct.
|
||||||
|
This function can detect whether given matrix is mirror matrix.
|
||||||
|
|
||||||
|
Reference: https://zhuanlan.zhihu.com/p/96717729
|
||||||
|
"""
|
||||||
|
return mat.is_negative
|
||||||
|
#return mat.to_3x3().determinant() < 0
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user