finish ballance element

This commit is contained in:
yyc12345 2023-10-26 12:32:08 +08:00
parent c1f92c7244
commit 1eaaedfcbd
3 changed files with 259 additions and 6 deletions

View File

@ -1,6 +1,6 @@
import bpy
import os, typing, enum
from . import UTIL_functions, UTIL_blender_mesh
import os, typing, enum, array
from . import UTIL_functions, UTIL_file_io, UTIL_blender_mesh, UTIL_virtools_types
#region Raw Elements Operations
@ -86,11 +86,97 @@ def get_ballance_elements() -> bpy.types.CollectionProperty:
#endregion
#region
#region Element Loader
def load_element(mesh: bpy.types.Mesh, element_id: int) -> None:
def _save_element(mesh: bpy.types.Mesh, filename: str) -> None:
# todo: if we need add element placeholder save operator,
# write this function and call this function in operator.
pass
def _load_element(mesh: bpy.types.Mesh, element_id: int) -> None:
# resolve mesh path
element_name: str | None = get_ballance_element_name(element_id)
if element_name is None:
raise UTIL_functions.BBPException('invalid element id in _load_element()')
element_filename: str = os.path.join(
os.path.dirname(__file__),
"meshes",
element_name + '.bin'
)
# open file and read
with open(element_filename, 'rb') as fmesh:
# prepare container
vpos: array.array = array.array('f')
vnml: array.array = array.array('f')
face: array.array = array.array('L')
# read data
# position is vector3
vpos_count = UTIL_file_io.read_uint32(fmesh)
vpos.extend(UTIL_file_io.read_float_array(fmesh, vpos_count * 3))
# normal is vector3
vnml_count = UTIL_file_io.read_uint32(fmesh)
vnml.extend(UTIL_file_io.read_float_array(fmesh, vnml_count * 3))
# each face use 6 uint32 to describe,
# they are: pos1, nml1, pos2, nml2, pos3, nml3.
# each item is a 0 based index refering to corresponding list
face_count = UTIL_file_io.read_uint32(fmesh)
face.extend(UTIL_file_io.read_uint32_array(fmesh, face_count * 6))
# open mesh writer and write data
with UTIL_blender_mesh.MeshWriter(mesh) as writer:
# prepare writer essential function
mesh_part: UTIL_blender_mesh.MeshWriter.MeshWriterPartData = UTIL_blender_mesh.MeshWriter.MeshWriterPartData()
def vpos_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]:
v: UTIL_virtools_types.VxVector3 = UTIL_virtools_types.VxVector3()
for i in range(vpos_count):
idx: int = i * 3
v.x = vpos[idx]
v.y = vpos[idx + 1]
v.z = vpos[idx + 2]
yield v
mesh_part.mVertexPosition = vpos_iterator()
def vnml_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]:
v: UTIL_virtools_types.VxVector3 = UTIL_virtools_types.VxVector3()
for i in range(vnml_count):
idx: int = i * 3
v.x = vnml[idx]
v.y = vnml[idx + 1]
v.z = vnml[idx + 2]
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()
yield v
mesh_part.mVertexUV = vuv_iterator()
def mtl_iterator() -> typing.Iterator[bpy.types.Material]:
pass
mesh_part.mMaterial = mtl_iterator()
def face_iterator() -> typing.Iterator[UTIL_blender_mesh.FaceData]:
# create face data with 3 placeholder
f: UTIL_blender_mesh.FaceData = UTIL_blender_mesh.FaceData([UTIL_blender_mesh.FaceVertexData() for i in range(3)])
for i in range(face_count):
idx: int = i * 6
f.mIndices[0].mPosIdx = face[idx]
f.mIndices[0].mNmlIdx = face[idx + 1]
f.mIndices[1].mPosIdx = face[idx + 2]
f.mIndices[1].mNmlIdx = face[idx + 3]
f.mIndices[2].mPosIdx = face[idx + 4]
f.mIndices[2].mNmlIdx = face[idx + 5]
yield f
mesh_part.mFace = face_iterator()
writer.add_part(mesh_part)
# end of with writer
# write mesh data
# end of with fmesh
# close file
#endregion
#region Ballance Elements Operation Help Class & Functions
@ -154,7 +240,7 @@ class BallanceElementsHelper():
raise UTIL_functions.BBPException('invalid element id')
new_mesh: bpy.types.Mesh = bpy.data.meshes.new(get_ballance_element_name(element_id))
load_element(new_mesh, element_id)
_load_element(new_mesh, element_id)
self.__mElementMap[element_id] = new_mesh
return new_mesh
@ -199,7 +285,7 @@ def reset_ballance_elements() -> None:
if eleid is None or item.mesh_ptr is None:
invalid_idx.append(index)
else:
load_element(item.mesh_ptr, eleid)
_load_element(item.mesh_ptr, eleid)
# inc counter
index += 1

87
bbp_ng/UTIL_file_io.py Normal file
View File

@ -0,0 +1,87 @@
import bpy, mathutils
import struct, os, io, typing
from . import UTIL_virtools_types
_FileWriter_t = io.BufferedWriter
_FileReader_t = io.BufferedReader
#region Writer Functions
def write_string(fs: _FileWriter_t, strl: str) -> None:
count = len(strl)
write_uint32(fs, count)
fs.write(strl.encode("utf_32_le"))
def write_uint8(fs: _FileWriter_t, num: int) -> None:
fs.write(struct.pack("<B", num))
def write_uint32(fs: _FileWriter_t, num: int) -> None:
fs.write(struct.pack("<I", num))
def write_uint64(fs: _FileWriter_t, num: int) -> None:
fs.write(struct.pack("<Q", num))
def write_bool(fs: _FileWriter_t, boolean: bool) -> None:
if boolean:
write_uint8(fs, 1)
else:
write_uint8(fs, 0)
def write_float(fs: _FileWriter_t, fl: float) -> None:
fs.write(struct.pack("<f", fl))
def write_world_matrix(fs: _FileWriter_t, mat: UTIL_virtools_types.VxMatrix) -> None:
fs.write(struct.pack("<16f", *mat.to_tuple()))
def write_color(fs: _FileWriter_t, colors: UTIL_virtools_types.VxColor) -> None:
fs.write(struct.pack("<fff", *colors.to_tuple_rgb()))
def write_uint32_array(fs: _FileWriter_t, vals: typing.Iterable[int], count: int) -> None:
fs.write(struct.pack('<' + str(count) + 'I', *vals))
def write_float_array(fs: _FileWriter_t, vals: typing.Iterable[float], count: int) -> None:
fs.write(struct.pack('<' + str(count) + 'f', *vals))
#endregion
#region Reader Functions
def peek_stream(fs: _FileReader_t) -> bytes:
res = fs.read(1)
fs.seek(-1, os.SEEK_CUR)
return res
def read_float(fs: _FileReader_t) -> float:
return struct.unpack("f", fs.read(4))[0]
def read_uint8(fs: _FileReader_t) -> int:
return struct.unpack("B", fs.read(1))[0]
def read_uint32(fs: _FileReader_t) -> int:
return struct.unpack("I", fs.read(4))[0]
def read_uint64(fs: _FileReader_t) -> int:
return struct.unpack("Q", fs.read(8))[0]
def read_string(fs: _FileReader_t) -> str:
count = read_uint32(fs)
return fs.read(count * 4).decode("utf_32_le")
def read_bool(fs: _FileReader_t) -> None:
return read_uint8(fs) != 0
def read_world_materix(fs: _FileReader_t, mat: UTIL_virtools_types.VxMatrix) -> None:
mat.from_tuple(struct.unpack("<16f", fs.read(16 * 4)))
def read_color(fs: _FileReader_t, target: UTIL_virtools_types.VxColor) -> None:
target.from_tuple_rgb(struct.unpack("fff", fs.read(3 * 4)))
def read_uint32_array(fs: _FileReader_t, count: int) -> tuple[int, ...]:
fmt: struct.Struct = struct.Struct('<' + str(count) + 'I')
return fmt.unpack(fs.read(fmt.size))
def read_float_array(fs: _FileReader_t, count: int) -> tuple[float, ...]:
fmt: struct.Struct = struct.Struct('<' + str(count) + 'f')
return fmt.unpack(fs.read(fmt.size))
#endregion

View File

@ -1,3 +1,4 @@
import mathutils
import typing, enum
from . import UTIL_functions
@ -100,6 +101,85 @@ class VxColor():
self.g = UTIL_functions.clamp_float(self.g, 0.0, 1.0)
self.b = UTIL_functions.clamp_float(self.b, 0.0, 1.0)
class VxMatrix():
"""
The Matrix representation.
The bracket statement exactly equal with Virtools.
"""
__mData: list[list[float]]
def __init__(self):
# init array
self.__mData = [[0] * 4 for i in range(4)]
# set to identy
self.reset()
def from_tuple(self, data: tuple[float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float]) -> None:
(
self.__mData[0][0], self.__mData[0][1], self.__mData[0][2], self.__mData[0][3],
self.__mData[1][0], self.__mData[1][1], self.__mData[1][2], self.__mData[1][3],
self.__mData[2][0], self.__mData[2][1], self.__mData[2][2], self.__mData[2][3],
self.__mData[3][0], self.__mData[3][1], self.__mData[3][2], self.__mData[3][3]
) = data
def from_blender(self, data_: mathutils.Matrix) -> None:
# transposed first
data: mathutils.Matrix = data_.transposed()
(
self.__mData[0][0], self.__mData[0][1], self.__mData[0][2], self.__mData[0][3],
self.__mData[1][0], self.__mData[1][1], self.__mData[1][2], self.__mData[1][3],
self.__mData[2][0], self.__mData[2][1], self.__mData[2][2], self.__mData[2][3],
self.__mData[3][0], self.__mData[3][1], self.__mData[3][2], self.__mData[3][3]
) = (
data[0][0], data[0][1], data[0][2], data[0][3],
data[1][0], data[1][1], data[1][2], data[1][3],
data[2][0], data[2][1], data[2][2], data[2][3],
data[3][0], data[3][1], data[3][2], data[3][3]
)
def to_tuple(self) -> tuple[float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float]:
return (
self.__mData[0][0], self.__mData[0][1], self.__mData[0][2], self.__mData[0][3],
self.__mData[1][0], self.__mData[1][1], self.__mData[1][2], self.__mData[1][3],
self.__mData[2][0], self.__mData[2][1], self.__mData[2][2], self.__mData[2][3],
self.__mData[3][0], self.__mData[3][1], self.__mData[3][2], self.__mData[3][3]
)
def to_tuple(self) -> mathutils.Matrix:
data: mathutils.Matrix = mathutils.Matrix(
(self.__mData[0][0], self.__mData[0][1], self.__mData[0][2], self.__mData[0][3]),
(self.__mData[1][0], self.__mData[1][1], self.__mData[1][2], self.__mData[1][3]),
(self.__mData[2][0], self.__mData[2][1], self.__mData[2][2], self.__mData[2][3]),
(self.__mData[3][0], self.__mData[3][1], self.__mData[3][2], self.__mData[3][3]),
)
# transpose self
data.transpose()
return data
def reset(self) -> None:
# reset to identy
for i in range(4):
for j in range(4):
self.__mData[i][j] = 0.0
self.__mData[0][0] = 1.0
self.__mData[1][1] = 1.0
self.__mData[2][2] = 1.0
self.__mData[3][3] = 1.0
def __swap_row_column(self) -> None:
# swap column 1 and 2
for i in range(4):
self.__mData[i][1], self.__mData[i][2] = self.__mData[i][2], self.__mData[i][1]
# swap row 1 and 2
for i in range(4):
self.__mData[1][i], self.__mData[2][i] = self.__mData[2][i], self.__mData[1][i]
def to_virtools_matrix(self) -> None:
self.__swap_row_column()
def to_blender_matrix(self) -> None:
self.__swap_row_column()
class VXTEXTURE_BLENDMODE(enum.IntEnum):
"""!