From 1299a14f3b5e8032b3bda559738965ce1650159f Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Fri, 10 Nov 2023 12:26:04 +0800 Subject: [PATCH] finish virtools file importer --- bbp_ng/OP_IMPORT_virtools.py | 138 +++++++++++++++++++++++++++++-- bbp_ng/PROP_ballance_element.py | 8 +- bbp_ng/PROP_virtools_material.py | 10 +-- bbp_ng/PyBMap/bmap.py | 9 +- bbp_ng/PyBMap/bmap_wrapper.py | 13 +-- bbp_ng/PyBMap/virtools_types.py | 32 +++---- bbp_ng/UTIL_blender_mesh.py | 71 +++++++++------- bbp_ng/UTIL_file_io.py | 2 +- bbp_ng/UTIL_virtools_types.py | 42 ++++------ 9 files changed, 230 insertions(+), 95 deletions(-) diff --git a/bbp_ng/OP_IMPORT_virtools.py b/bbp_ng/OP_IMPORT_virtools.py index 190ab28..47b1c8d 100644 --- a/bbp_ng/OP_IMPORT_virtools.py +++ b/bbp_ng/OP_IMPORT_virtools.py @@ -1,6 +1,6 @@ import bpy from bpy_extras.wm_utils.progress_report import ProgressReport -import tempfile, os +import tempfile, os, typing from . import PROP_preferences from . import UTIL_virtools_types, UTIL_functions, UTIL_file_browser, UTIL_blender_mesh, UTIL_ballance_texture from . import PROP_ballance_element, PROP_virtools_group, PROP_virtools_material @@ -37,6 +37,8 @@ class BBP_OT_import_virtools(bpy.types.Operator, UTIL_file_browser.ImportVirtool def _import_virtools(file_name_: str, encodings_: tuple[str]) -> None: # create temp folder with tempfile.TemporaryDirectory() as vt_temp_folder: + print(f'Virtools Engine Temp: {vt_temp_folder}') + # create virtools reader context with bmap.BMFileReader( file_name_, @@ -48,7 +50,7 @@ def _import_virtools(file_name_: str, encodings_: tuple[str]) -> None: with ProgressReport(wm = bpy.context.window_manager) as progress: # import textures texture_cret_map: dict[bmap.BMTexture, bpy.types.Image] = _import_virtools_textures( - reader, progress, texture_cret_map) + reader, progress) # import materials material_cret_map: dict[bmap.BMMaterial, bpy.types.Material] = _import_virtools_materials( reader, progress, texture_cret_map) @@ -71,6 +73,7 @@ def _import_virtools_textures( # create another temp folder for raw data virtools texture importing with tempfile.TemporaryDirectory() as rawdata_temp: + print(f'Texture Raw Data Temp: {rawdata_temp}') for vttexture in reader.get_textures(): # if this image is raw data, save it in external folder before loading @@ -174,8 +177,78 @@ def _import_virtools_meshes( progress.enter_substeps(reader.get_material_count(), "Loading Meshes") for vtmesh in reader.get_meshs(): + # create mesh + mesh: bpy.types.Mesh = bpy.data.meshes.new( + UTIL_functions.virtools_name_regulator(vtmesh.get_name()) + ) + + # open mesh writer + with UTIL_blender_mesh.MeshWriter(mesh) as meshoper: + # construct data provider + data_prov: UTIL_blender_mesh.MeshWriterIngredient = UTIL_blender_mesh.MeshWriterIngredient() + + # constructor data itor + def pos_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]: + for v in vtmesh.get_vertex_positions(): + UTIL_virtools_types.vxvector3_conv_co(v) + yield v + def nml_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]: + for v in vtmesh.get_vertex_normals(): + UTIL_virtools_types.vxvector3_conv_co(v) + yield v + def uv_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector2]: + for v in vtmesh.get_vertex_uvs(): + UTIL_virtools_types.vxvector2_conv_co(v) + yield v + def face_iterator() -> typing.Iterator[UTIL_blender_mesh.FaceData]: + face: UTIL_blender_mesh.FaceData = UTIL_blender_mesh.FaceData( + [UTIL_blender_mesh.FaceVertexData() for i in range(3)] + ) + + findices_itor = vtmesh.get_face_indices() + fmtl_itor = vtmesh.get_face_material_slot_indexs() + for _ in range(vtmesh.get_face_count()): + # set indices data + vtindices = next(findices_itor) + face.mIndices[0].mPosIdx = vtindices.i1 + face.mIndices[0].mNmlIdx = vtindices.i1 + face.mIndices[0].mUvIdx = vtindices.i1 + face.mIndices[1].mPosIdx = vtindices.i2 + face.mIndices[1].mNmlIdx = vtindices.i2 + face.mIndices[1].mUvIdx = vtindices.i2 + face.mIndices[2].mPosIdx = vtindices.i3 + face.mIndices[2].mNmlIdx = vtindices.i3 + face.mIndices[2].mUvIdx = vtindices.i3 + # swap indices + face.conv_co() + + # set mtl data + vtmtl = next(fmtl_itor) + face.mMtlIdx = vtmtl + + # return + yield face + def mtl_iterator() -> typing.Iterator[bpy.types.Material]: + for vtmtl in vtmesh.get_material_slots(): + if vtmtl: + yield material_cret_map.get(vtmtl, None) + else: + yield None + + # assign to data provider + data_prov.mVertexPosition = pos_iterator() + data_prov.mVertexNormal = nml_iterator() + data_prov.mVertexUV = uv_iterator() + data_prov.mFace = face_iterator() + data_prov.mMaterial = mtl_iterator() + + # add part + meshoper.add_ingredient(data_prov) + + # end of mesh writer + # add into map and step - #mesh_cret_map[vtmaterial] = mtl + mesh_cret_map[vtmesh] = mesh progress.step() # leave progress and return @@ -191,9 +264,30 @@ def _import_virtools_3dobjects( obj3d_cret_map: dict[bmap.BM3dObject, bpy.types.Object] = {} progress.enter_substeps(reader.get_material_count(), "Loading 3dObjects") + # get some essential blender data + blender_view_layer = bpy.context.view_layer + blender_collection = blender_view_layer.active_layer_collection.collection + for vt3dobj in reader.get_3dobjects(): + # create 3d object with mesh + obj3d: bpy.types.Object = bpy.data.objects.new( + UTIL_functions.virtools_name_regulator(vt3dobj.get_name()), + mesh_cret_map.get(vt3dobj.get_current_mesh(), None) + ) + + # link to collection + blender_collection.objects.link(obj3d) + + # set world matrix + vtmat = vt3dobj.get_world_matrix() + UTIL_virtools_types.vxmatrix_conv_co(vtmat) + obj3d.matrix_world = UTIL_virtools_types.vxmatrix_to_blender(vtmat) + + # set visibility + obj3d.hide_set(not vt3dobj.get_visibility()) + # add into map and step - #obj3d_cret_map[vtmaterial] = mtl + obj3d_cret_map[vt3dobj] = obj3d progress.step() # leave progress and return @@ -205,17 +299,49 @@ def _import_virtools_groups( progress: ProgressReport, obj3d_cret_map: dict[bmap.BM3dObject, bpy.types.Object] ) -> dict[bmap.BM3dObject, bpy.types.Object]: + # we need iterate all groups to construct a reversed map + # to indicate which groups should this 3dobject be grouped into. + reverse_map: dict[bmap.BM3dObject, set[str]] = {} + # prepare progress progress.enter_substeps(reader.get_material_count(), "Loading Groups") for vtgroup in reader.get_groups(): - # add into map and step - #obj3d_cret_map[vtmaterial] = mtl + # if this group do not have name, skip it + group_name: str | None = vtgroup.get_name() + if group_name is None: continue + + for item in vtgroup.get_objects(): + # get or create set + objgroups: set[str] = reverse_map.get(item, None) + if objgroups is None: + objgroups = set() + reverse_map[item] = objgroups + + # add into list + objgroups.add(group_name) + + # step progress.step() # leave progress progress.leave_substeps() + # now we can assign 3dobject group data by reverse map + progress.enter_substeps(reader.get_material_count(), "Applying Groups") + for mapk, mapv in reverse_map.items(): + # check object + assoc_obj = obj3d_cret_map.get(mapk, None) + if assoc_obj is None: continue + + # assign group + with PROP_virtools_group.VirtoolsGroupsHelper(assoc_obj) as gpoper: + gpoper.clear_all_groups() + gpoper.add_groups(mapv) + + progress.leave_substeps() + + def register() -> None: bpy.utils.register_class(BBP_OT_import_virtools) diff --git a/bbp_ng/PROP_ballance_element.py b/bbp_ng/PROP_ballance_element.py index 2d9e525..b38a18f 100644 --- a/bbp_ng/PROP_ballance_element.py +++ b/bbp_ng/PROP_ballance_element.py @@ -128,7 +128,7 @@ def _load_element(mesh: bpy.types.Mesh, element_id: int) -> None: # 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() + mesh_part: UTIL_blender_mesh.MeshWriterIngredient = UTIL_blender_mesh.MeshWriterIngredient() def vpos_iterator() -> typing.Iterator[UTIL_virtools_types.VxVector3]: v: UTIL_virtools_types.VxVector3 = UTIL_virtools_types.VxVector3() for i in range(vpos_count): @@ -154,7 +154,9 @@ def _load_element(mesh: bpy.types.Mesh, element_id: int) -> None: mesh_part.mMaterial = iter(tuple()) 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)]) + 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] @@ -166,7 +168,7 @@ def _load_element(mesh: bpy.types.Mesh, element_id: int) -> None: yield f mesh_part.mFace = face_iterator() - writer.add_part(mesh_part) + writer.add_ingredient(mesh_part) # end of with writer # write mesh data diff --git a/bbp_ng/PROP_virtools_material.py b/bbp_ng/PROP_virtools_material.py index 36d0e2d..994982f 100644 --- a/bbp_ng/PROP_virtools_material.py +++ b/bbp_ng/PROP_virtools_material.py @@ -413,14 +413,14 @@ def get_raw_virtools_material(mtl: bpy.types.Material) -> RawVirtoolsMaterial: props: BBP_PG_virtools_material = get_virtools_material(mtl) rawdata: RawVirtoolsMaterial = RawVirtoolsMaterial() - rawdata.mDiffuse.from_tuple_rgba(props.diffuse) - rawdata.mAmbient.from_tuple_rgb(props.ambient) - rawdata.mSpecular.from_tuple_rgb(props.specular) - rawdata.mEmissive.from_tuple_rgb(props.emissive) + rawdata.mDiffuse.from_const_rgba(props.diffuse) + rawdata.mAmbient.from_const_rgb(props.ambient) + rawdata.mSpecular.from_const_rgb(props.specular) + rawdata.mEmissive.from_const_rgb(props.emissive) rawdata.mSpecularPower = props.specular_power rawdata.mTexture = props.texture - rawdata.mTextureBorderColor.from_tuple_rgba(props.texture_border_color) + rawdata.mTextureBorderColor.from_const_rgba(props.texture_border_color) rawdata.mTextureBlendMode = UTIL_virtools_types.VXTEXTURE_BLENDMODE(int(props.texture_blend_mode)) rawdata.mTextureMinMode = UTIL_virtools_types.VXTEXTURE_FILTERMODE(int(props.texture_min_mode)) diff --git a/bbp_ng/PyBMap/bmap.py b/bbp_ng/PyBMap/bmap.py index 1b6c7af..0ed4285 100644 --- a/bbp_ng/PyBMap/bmap.py +++ b/bbp_ng/PyBMap/bmap.py @@ -46,6 +46,7 @@ class bm_VxVector3(ctypes.Structure): ('z', bm_CKFLOAT), ] bm_VxVector3_p = ctypes.POINTER(bm_VxVector3) +bm_VxVector3_pp = ctypes.POINTER(bm_VxVector3_p) class bm_VxColor(ctypes.Structure): _fields_ = [ ('r', bm_CKFLOAT), @@ -223,7 +224,7 @@ BMMeshTrans_PrepareVertexCount = _create_bmap_func('BMMeshTrans_PrepareVertexCou # @param trans[in] Type: BMap::BMMeshTransition*. The pointer to corresponding BMMeshTransition. # @param out_mem[out] Type: LibCmo::VxMath::VxVector3*. Use ctypes.byref(data) pass it. # @return True if no error, otherwise False. -BMMeshTrans_PrepareVertex = _create_bmap_func('BMMeshTrans_PrepareVertex', [bm_void_p, bm_VxVector2_pp]) +BMMeshTrans_PrepareVertex = _create_bmap_func('BMMeshTrans_PrepareVertex', [bm_void_p, bm_VxVector3_pp]) ## BMMeshTrans_PrepareNormalCount # @param trans[in] Type: BMap::BMMeshTransition*. The pointer to corresponding BMMeshTransition. # @param count[in] Type: LibCmo::CKDWORD. @@ -233,7 +234,7 @@ BMMeshTrans_PrepareNormalCount = _create_bmap_func('BMMeshTrans_PrepareNormalCou # @param trans[in] Type: BMap::BMMeshTransition*. The pointer to corresponding BMMeshTransition. # @param out_mem[out] Type: LibCmo::VxMath::VxVector3*. Use ctypes.byref(data) pass it. # @return True if no error, otherwise False. -BMMeshTrans_PrepareNormal = _create_bmap_func('BMMeshTrans_PrepareNormal', [bm_void_p, bm_VxVector2_pp]) +BMMeshTrans_PrepareNormal = _create_bmap_func('BMMeshTrans_PrepareNormal', [bm_void_p, bm_VxVector3_pp]) ## BMMeshTrans_PrepareUVCount # @param trans[in] Type: BMap::BMMeshTransition*. The pointer to corresponding BMMeshTransition. # @param count[in] Type: LibCmo::CKDWORD. @@ -651,13 +652,13 @@ BMMesh_SetVertexCount = _create_bmap_func('BMMesh_SetVertexCount', [bm_void_p, b # @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing. # @param out_mem[out] Type: LibCmo::VxMath::VxVector3*. Use ctypes.byref(data) pass it. # @return True if no error, otherwise False. -BMMesh_GetVertexPositions = _create_bmap_func('BMMesh_GetVertexPositions', [bm_void_p, bm_CKID, bm_VxVector2_pp]) +BMMesh_GetVertexPositions = _create_bmap_func('BMMesh_GetVertexPositions', [bm_void_p, bm_CKID, bm_VxVector3_pp]) ## BMMesh_GetVertexNormals # @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile. # @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing. # @param out_mem[out] Type: LibCmo::VxMath::VxVector3*. Use ctypes.byref(data) pass it. # @return True if no error, otherwise False. -BMMesh_GetVertexNormals = _create_bmap_func('BMMesh_GetVertexNormals', [bm_void_p, bm_CKID, bm_VxVector2_pp]) +BMMesh_GetVertexNormals = _create_bmap_func('BMMesh_GetVertexNormals', [bm_void_p, bm_CKID, bm_VxVector3_pp]) ## BMMesh_GetVertexUVs # @param bmfile[in] Type: BMap::BMFile*. The pointer to corresponding BMFile. # @param objid[in] Type: LibCmo::CK2::CK_ID. The CKID of object you accessing. diff --git a/bbp_ng/PyBMap/bmap_wrapper.py b/bbp_ng/PyBMap/bmap_wrapper.py index b51f758..1e3886a 100644 --- a/bbp_ng/PyBMap/bmap_wrapper.py +++ b/bbp_ng/PyBMap/bmap_wrapper.py @@ -48,13 +48,15 @@ class _AbstractCKObject(_AbstractPointer): return bmap.bm_CKID(self.__mCKID) def __eq__(self, obj: object) -> bool: + if not _AbstractPointer.__eq__(self, obj): return False + if isinstance(obj, self.__class__): - return obj.__mRawPointer == self.__mRawPointer and obj.__mCKID == self.__mCKID + return obj.__mCKID == self.__mCKID else: return False def __hash__(self) -> int: - return hash((self.__mRawPointer, self.__mCKID)) + return hash((_AbstractPointer.__hash__(self), self.__mCKID)) #endregion @@ -119,6 +121,7 @@ def _ckfaceindices_iterator(pindices: bmap.bm_CKDWORD_p, count: int) -> typing.I ret.i2 = pindices[idx + 1] ret.i3 = pindices[idx + 2] idx += 3 + yield ret #endregion @@ -429,7 +432,7 @@ class BMMesh(BMObject): def get_vertex_uvs(self) -> typing.Iterator[virtools_types.VxVector2]: raw_vector: bmap.bm_VxVector2_p = bmap.bm_VxVector2_p() bmap.BMMesh_GetVertexUVs(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_vector)) - _vxvector2_iterator(raw_vector, self.get_vertex_count()) + return _vxvector2_iterator(raw_vector, self.get_vertex_count()) def set_vertex_uvs(self, itor: typing.Iterator[virtools_types.VxVector2]) -> None: raw_vector: bmap.bm_VxVector2_p = bmap.bm_VxVector2_p() @@ -457,13 +460,13 @@ class BMMesh(BMObject): def get_face_material_slot_indexs(self) -> typing.Iterator[int]: raw_idx: bmap.bm_CKWORD_p = bmap.bm_CKWORD_p() - bmap.BMMesh_GetFaceIndices(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_idx)) + bmap.BMMesh_GetFaceMaterialSlotIndexs(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_idx)) for i in range(self.get_face_count()): yield raw_idx[i] def set_face_material_slot_indexs(self, itor: typing.Iterator[int]) -> None: raw_idx: bmap.bm_CKWORD_p = bmap.bm_CKWORD_p() - bmap.BMMesh_GetFaceIndices(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_idx)) + bmap.BMMesh_GetFaceMaterialSlotIndexs(self._get_pointer(), self._get_ckid(), ctypes.byref(raw_idx)) for i in range(self.get_face_count()): raw_idx[i] = next(itor) diff --git a/bbp_ng/PyBMap/virtools_types.py b/bbp_ng/PyBMap/virtools_types.py index 7f943b4..bdff974 100644 --- a/bbp_ng/PyBMap/virtools_types.py +++ b/bbp_ng/PyBMap/virtools_types.py @@ -136,42 +136,42 @@ class VxMatrix(): The Matrix representation. The bracket statement exactly equal with Virtools. """ - __mData: list[list[float]] + data: list[list[float]] def __init__(self): # init array - self.__mData = [[0] * 4 for i in range(4)] + self.data = [[0] * 4 for i in range(4)] # set to identy self.reset() def _get_raw(self) -> list[list[float]]: - return self.__mData + return self.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.data[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 + self.data[0][0] = 1.0 + self.data[1][1] = 1.0 + self.data[2][2] = 1.0 + self.data[3][3] = 1.0 def from_const(self, cm: ConstVxMatrix) -> 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] + self.data[0][0], self.data[0][1], self.data[0][2], self.data[0][3], + self.data[1][0], self.data[1][1], self.data[1][2], self.data[1][3], + self.data[2][0], self.data[2][1], self.data[2][2], self.data[2][3], + self.data[3][0], self.data[3][1], self.data[3][2], self.data[3][3] ) = cm def to_const(self) -> ConstVxMatrix: 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] + self.data[0][0], self.data[0][1], self.data[0][2], self.data[0][3], + self.data[1][0], self.data[1][1], self.data[1][2], self.data[1][3], + self.data[2][0], self.data[2][1], self.data[2][2], self.data[2][3], + self.data[3][0], self.data[3][1], self.data[3][2], self.data[3][3] ) class CK_TEXTURE_SAVEOPTIONS(enum.IntEnum): diff --git a/bbp_ng/UTIL_blender_mesh.py b/bbp_ng/UTIL_blender_mesh.py index 434b42b..01e1ca1 100644 --- a/bbp_ng/UTIL_blender_mesh.py +++ b/bbp_ng/UTIL_blender_mesh.py @@ -32,10 +32,43 @@ class FaceData(): def __init__(self, indices: tuple[FaceVertexData] | list[FaceVertexData] = tuple(), mtlidx: int = 0): self.mIndices = indices self.mMtlIdx = mtlidx + + def conv_co(self) -> None: + """ + Change indice order between Virtools and Blender + """ + if isinstance(self.mIndices, list): + self.mIndices.reverse() + elif isinstance(self.mIndices, tuple): + self.mIndices = self.mIndices[::-1] + else: + raise UTIL_functions.BBPException('invalid indices container.') def is_indices_legal(self) -> bool: return len(self.mIndices) >= 3 +class MeshWriterIngredient(): + mVertexPosition: typing.Iterator[UTIL_virtools_types.VxVector3] | None + mVertexNormal: typing.Iterator[UTIL_virtools_types.VxVector3] | None + mVertexUV: typing.Iterator[UTIL_virtools_types.VxVector2] | None + mFace: typing.Iterator[FaceData] | None + mMaterial: typing.Iterator[bpy.types.Material] | None + + def __init__(self): + self.mVertexPosition = None + self.mVertexNormal = None + self.mVertexUV = None + self.mFace = None + self.mMaterial = None + + def is_valid(self) -> bool: + if self.mVertexPosition is None: return False + if self.mVertexNormal is None: return False + if self.mVertexUV is None: return False + if self.mFace is None: return False + if self.mMaterial is None: return False + return True + def _flat_vxvector3(it: typing.Iterator[UTIL_virtools_types.VxVector3]) -> typing.Iterator[float]: for entry in it: yield entry.x @@ -268,7 +301,7 @@ class MeshReader(): pass def __triangulate_mesh(self) -> None: - bm = bmesh.new() + bm: bmesh.types.BMesh = bmesh.new() bm.from_mesh(self.__mAssocMesh) bmesh.ops.triangulate(bm, faces = bm.faces) bm.to_mesh(self.__mAssocMesh) @@ -281,28 +314,6 @@ class MeshWriter(): then refer it to all face uv. """ - class MeshWriterPartData(): - mVertexPosition: typing.Iterator[UTIL_virtools_types.VxVector3] | None - mVertexNormal: typing.Iterator[UTIL_virtools_types.VxVector3] | None - mVertexUV: typing.Iterator[UTIL_virtools_types.VxVector2] | None - mFace: typing.Iterator[FaceData] | None - mMaterial: typing.Iterator[bpy.types.Material] | None - - def __init__(self): - self.mVertexPosition = None - self.mVertexNormal = None - self.mVertexUV = None - self.mFace = None - self.mMaterial = None - - def is_valid(self) -> bool: - if self.mVertexPosition is None: return False - if self.mVertexNormal is None: return False - if self.mVertexUV is None: return False - if self.mFace is None: return False - if self.mMaterial is None: return False - return True - __mAssocMesh: bpy.types.Mesh | None ##< The binding mesh for this writer. None if this writer is invalid. __mVertexPos: array.array ##< Array item is float(f). Length must be an integer multiple of 3. @@ -365,25 +376,25 @@ class MeshWriter(): # reset mesh self.__mAssocMesh = None - def add_part(self, data: MeshWriterPartData): + def add_ingredient(self, data: MeshWriterIngredient): if not self.is_valid(): raise UTIL_functions.BBPException('try to call an invalid MeshWriter.') if not data.is_valid(): raise UTIL_functions.BBPException('invalid mesh part data.') # add vertex data - prev_vertex_pos_count: int = len(self.__mVertexPos) + prev_vertex_pos_count: int = len(self.__mVertexPos) // 3 self.__mVertexPos.extend(_flat_vxvector3(data.mVertexPosition)) - prev_vertex_nml_count: int = len(self.__mVertexNormal) + prev_vertex_nml_count: int = len(self.__mVertexNormal) // 3 self.__mVertexNormal.extend(_flat_vxvector3(data.mVertexNormal)) - prev_vertex_uv_count: int = len(self.__mVertexUV) + prev_vertex_uv_count: int = len(self.__mVertexUV) // 2 self.__mVertexUV.extend(_flat_vxvector2(data.mVertexUV)) # add material slot data and create mtl remap mtl_remap: list[int] = [] for mtl in data.mMaterial: idx: int | None = self.__mMtlSlotMap.get(mtl, None) - if idx: + if idx is not None: mtl_remap.append(idx) else: self.__mMtlSlotMap[mtl] = len(self.__mMtlSlot) @@ -405,7 +416,7 @@ class MeshWriter(): # add face mtl with remap mtl_idx: int = face.mMtlIdx - if mtl_idx < 0 or mtl_idx > len(mtl_remap): + if mtl_idx < 0 or mtl_idx >= len(mtl_remap): # fall back. add 0 self.__mFaceMtlIdx.append(0) else: @@ -423,7 +434,7 @@ class MeshWriter(): self.__mAssocMesh.materials.append(mtl) # add corresponding count for vertex position - self.__mAssocMesh.vertices.add(len(self.__mVertexPos)) + self.__mAssocMesh.vertices.add(len(self.__mVertexPos) // 3) # add loops data, it is the sum count of indices # we use face pos indices size to get it self.__mAssocMesh.loops.add(len(self.__mFacePosIndices)) diff --git a/bbp_ng/UTIL_file_io.py b/bbp_ng/UTIL_file_io.py index 7f18e24..a887d29 100644 --- a/bbp_ng/UTIL_file_io.py +++ b/bbp_ng/UTIL_file_io.py @@ -74,7 +74,7 @@ def read_world_materix(fs: _FileReader_t, mat: UTIL_virtools_types.VxMatrix) -> 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))) + target.from_const_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') diff --git a/bbp_ng/UTIL_virtools_types.py b/bbp_ng/UTIL_virtools_types.py index 37dceef..4512f22 100644 --- a/bbp_ng/UTIL_virtools_types.py +++ b/bbp_ng/UTIL_virtools_types.py @@ -10,52 +10,48 @@ from .PyBMap.virtools_types import * #region VxVector2 Patch -def _vxvector2_conv_co(self: VxVector2) -> None: +def vxvector2_conv_co(self: VxVector2) -> None: """ Convert UV coordinate system between Virtools and Blender. """ self.y = -self.y -VxVector2.conv_co = _vxvector2_conv_co - #endregion #region VxVector3 Patch -def _vxvector3_conv_co(self: VxVector3) -> None: +def vxvector3_conv_co(self: VxVector3) -> None: """ Convert Position or Normal coordinate system between Virtools and Blender. """ self.y, self.z = self.z, self.y -VxVector3.conv_co = _vxvector3_conv_co - #endregion #region VxMatrix Patch -def _vxmatrix_conv_co(self: VxMatrix) -> None: +def vxmatrix_conv_co(self: VxMatrix) -> None: """ Convert World Matrix coordinate system between Virtools and Blender. """ # 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] + self.data[i][1], self.data[i][2] = self.data[i][2], self.data[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] + self.data[1][i], self.data[2][i] = self.data[2][i], self.data[1][i] -def _vxmatrix_from_blender(self: VxMatrix, data_: mathutils.Matrix) -> None: +def vxmatrix_from_blender(self: VxMatrix, data_: mathutils.Matrix) -> None: """ Set matrix by blender matrix. """ # 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] + self.data[0][0], self.data[0][1], self.data[0][2], self.data[0][3], + self.data[1][0], self.data[1][1], self.data[1][2], self.data[1][3], + self.data[2][0], self.data[2][1], self.data[2][2], self.data[2][3], + self.data[3][0], self.data[3][1], self.data[3][2], self.data[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], @@ -63,23 +59,19 @@ def _vxmatrix_from_blender(self: VxMatrix, data_: mathutils.Matrix) -> None: data[3][0], data[3][1], data[3][2], data[3][3] ) -def _vxmatrix_to_blender(self: VxMatrix) -> mathutils.Matrix: +def vxmatrix_to_blender(self: VxMatrix) -> mathutils.Matrix: """ Get blender matrix from this 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]), - ) + data: mathutils.Matrix = mathutils.Matrix(( + (self.data[0][0], self.data[0][1], self.data[0][2], self.data[0][3]), + (self.data[1][0], self.data[1][1], self.data[1][2], self.data[1][3]), + (self.data[2][0], self.data[2][1], self.data[2][2], self.data[2][3]), + (self.data[3][0], self.data[3][1], self.data[3][2], self.data[3][3]), + )) # transpose self data.transpose() return data -VxMatrix.conv_co = _vxmatrix_conv_co -VxMatrix.from_blender = _vxmatrix_from_blender -VxMatrix.to_blender = _vxmatrix_to_blender - #endregion