finish virtools file importer
This commit is contained in:
parent
8fad643dd9
commit
1299a14f3b
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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):
|
||||
|
@ -33,9 +33,42 @@ class FaceData():
|
||||
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))
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user