1
0

feat: change project layout for new added project

This commit is contained in:
2026-01-30 15:23:01 +08:00
parent 2b9c0296d1
commit 2f59e16590
28 changed files with 161 additions and 36 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,341 @@
#pragma once
#include "BMap.hpp"
#include <algorithm>
/**
@note
# Design Note:
## Function Declaration
All exported interface functions will always return a bool to indicate whether current operations is successful.
The layout of interface functions' parameters is Essential Param -> Input Param -> Out Param.
A example is in there: `BMAP_EXPORT bool BMSomeFunc(BMPARAM_OBJECT_DECL, BMPARAM_IN(LibCmo::CK2::CK_ID, someobj), BMPARAM_OUT(LibCmo::CKSTRING, out_name));`
First param is `BMPARAM_OBJECT_DECL`. It is essential param for this function. In this exmaple, it is the combination of BMFile* and CK_ID. If your provide invalid value for them, the function will failed immediately.
Second param is `BMPARAM_IN(LibCmo::CK2::CK_ID, someobj)`. It declare this function accept a Object ID for underlying function calling.
Last param is `BMPARAM_OUT(LibCmo::CKSTRING, out_name)`. It is the return value of this function. Only will be filled when this function success.
Input Param and Out Param can be multiple. No count limit.
## CK_ID Interface.
We use CK_ID as CKObject visitor to ensure the visiting is safe.
We choose CK_ID because checking a valid CK_ID is more easy and cost lower performance than checking a valid CKObject*.
Another reason is that CKObject* relate to class inheritance and need cast. Use CK_ID can leyt them get safe cast in C++, not in other binding languages.
Each CK_ID also should be used with its corresponding BMFile*, because each BMfile* will create a unique CKContext*. CK_ID between different BMFile* is not shared.
+ We use raw pointer for BMFile and BMMeshTransition
- These 2 class do no involve class inheritance so we can safely pass them to this DLL.
- These 2 class is not a part of CK core. It is more easy to check them validation. It is enough checking them in a std::set.
*/
#pragma region Macros for Exporting Functions
// Reference: https://stackoverflow.com/questions/2164827/explicitly-exporting-shared-library-functions-in-linux
// Generate macro for import and export respectively.
#if defined(_MSC_VER)
// Microsoft
#define BMAP_RAW_EXPORT __declspec(dllexport)
#define BMAP_RAW_IMPORT __declspec(dllimport)
#elif defined(__GNUC__)
// GCC
#define BMAP_RAW_EXPORT __attribute__((visibility("default")))
#define BMAP_RAW_IMPORT
#elif defined(__clang__)
// Clang
#define BMAP_RAW_EXPORT __attribute__((visibility("default")))
#define BMAP_RAW_IMPORT
#else
// Do nothing and hope for the best?
#define BMAP_RAW_EXPORT
#define BMAP_RAW_IMPORT
#error "Unknown dynamic link import/export semantics."
#endif
// Choosee import or export command according to special macro.
#if defined(BMAP_EXPORTING)
#define BMAP_NAKED_EXPORT BMAP_RAW_EXPORT
#else
#define BMAP_NAKED_EXPORT BMAP_RAW_IMPORT
#endif
// Create real export macro according to whether in C++ environment.
#if defined(__cplusplus)
#define BMAP_EXPORT extern "C" BMAP_NAKED_EXPORT
#else
#define BMAP_EXPORT BMAP_NAKED_EXPORT
#endif
#pragma endregion
#pragma region Interface Used Macros
/** The first param used by BMFile function family */
#define BMPARAM_FILE_DECL(_bmfile) BMap::BMFile* _bmfile
/** The first param used by BMMeshTrans function family */
#define BMPARAM_MESHTRANS_DECL(_trans) BMap::BMMeshTransition* _trans
/** The first param used by BMObject, BMGroup, BM3dObject, BMMesh, BMMaterial and BMTexture function family */
#define BMPARAM_OBJECT_DECL(_bmfile, _objid) BMap::BMFile* _bmfile, LibCmo::CK2::CK_ID _objid
/** Declare an input parameter */
#define BMPARAM_IN(_t, _name) _t _name
/**
@brief
Declare an output parameter.
@details
A pointer will be added automatically for caller receive it.
See BMPARAM_OUT_ASSIGN and BMPARAM_OUT_VAL to know how to use output param in function body.
@remark
There is an example:
```
bool some_interface_func(BMPARAM_OUT(Type_t, param_name)) {
BMPARAM_OUT_ASSIGN(param_name, some_value); // assign to out param.
return BMPARAM_OUT_VAL(param_name) != other_value; // use out param value.
}
```
@see BMPARAM_OUT_ASSIGN, BMPARAM_OUT_VAL
*/
#define BMPARAM_OUT(_t, _name) _t* _name
/** Assign value for out param in function body. */
#define BMPARAM_OUT_ASSIGN(_name, _val) (*(_name)) = (_val)
/** Visit value for out param in function body. */
#define BMPARAM_OUT_VAL(_name) (*(_name))
#pragma endregion
#pragma region Init / Dispose
BMAP_EXPORT bool BMInit();
BMAP_EXPORT bool BMDispose();
#pragma endregion
#pragma region BMFile
BMAP_EXPORT bool BMFile_Load(
BMPARAM_IN(LibCmo::CKSTRING, file_name),
BMPARAM_IN(LibCmo::CKSTRING, temp_folder),
BMPARAM_IN(LibCmo::CKSTRING, texture_folder),
BMPARAM_IN(BMap::NakedOutputCallback, raw_callback),
BMPARAM_IN(LibCmo::CKDWORD, encoding_count),
BMPARAM_IN(LibCmo::CKSTRING*, encodings),
BMPARAM_OUT(BMap::BMFile*, out_file)
);
BMAP_EXPORT bool BMFile_Create(
BMPARAM_IN(LibCmo::CKSTRING, temp_folder),
BMPARAM_IN(LibCmo::CKSTRING, texture_folder),
BMPARAM_IN(BMap::NakedOutputCallback, raw_callback),
BMPARAM_IN(LibCmo::CKDWORD, encoding_count),
BMPARAM_IN(LibCmo::CKSTRING*, encodings),
BMPARAM_OUT(BMap::BMFile*, out_file)
);
BMAP_EXPORT bool BMFile_Save(
BMPARAM_IN(BMap::BMFile*, map_file),
BMPARAM_IN(LibCmo::CKSTRING, file_name),
BMPARAM_IN(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS, texture_save_opt),
BMPARAM_IN(bool, use_compress),
BMPARAM_IN(LibCmo::CKINT, compreess_level)
);
BMAP_EXPORT bool BMFile_Free(
BMPARAM_IN(BMap::BMFile*, map_file)
);
BMAP_EXPORT bool BMFile_GetGroupCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_GetGroup(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_CreateGroup(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_Get3dObjectCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_Get3dObject(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_Create3dObject(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_GetMeshCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_GetMesh(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_CreateMesh(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_GetMaterialCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_GetMaterial(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_CreateMaterial(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_GetTextureCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_GetTexture(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_CreateTexture(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_GetTargetLightCount(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMFile_GetTargetLight(BMPARAM_FILE_DECL(bmfile), BMPARAM_IN(LibCmo::CKDWORD, idx), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
BMAP_EXPORT bool BMFile_CreateTargetLight(BMPARAM_FILE_DECL(bmfile), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_id));
#pragma endregion
#pragma region BMMeshTransition
BMAP_EXPORT bool BMMeshTrans_New(BMPARAM_OUT(BMap::BMMeshTransition*, out_trans));
BMAP_EXPORT bool BMMeshTrans_Delete(BMPARAM_IN(BMap::BMMeshTransition*, trans));
BMAP_EXPORT bool BMMeshTrans_PrepareVertexCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMeshTrans_PrepareVertex(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareNormalCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMeshTrans_PrepareNormal(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareUVCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMeshTrans_PrepareUV(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::VxMath::VxVector2*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareMtlSlotCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMeshTrans_PrepareMtlSlot(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CK2::CK_ID*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareFaceCount(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMeshTrans_PrepareFaceVertexIndices(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareFaceNormalIndices(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareFaceUVIndices(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
BMAP_EXPORT bool BMMeshTrans_PrepareFaceMtlSlot(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_OUT(LibCmo::CKDWORD*, out_mem));
BMAP_EXPORT bool BMMeshTrans_Parse(BMPARAM_MESHTRANS_DECL(trans), BMPARAM_IN(BMap::BMFile*, bmfile), BMPARAM_IN(LibCmo::CK2::CK_ID, objid));
#pragma endregion
#pragma region CKObject
BMAP_EXPORT bool BMObject_GetName(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKSTRING, out_name));
BMAP_EXPORT bool BMObject_SetName(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKSTRING, name));
#pragma endregion
#pragma region CKGroup
BMAP_EXPORT bool BMGroup_AddObject(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, memberid));
BMAP_EXPORT bool BMGroup_GetObjectCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMGroup_GetObject(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, pos), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_objid));
#pragma endregion
#pragma region CKTexture
BMAP_EXPORT bool BMTexture_GetFileName(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKSTRING, out_filename));
BMAP_EXPORT bool BMTexture_LoadImage(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKSTRING, filename));
BMAP_EXPORT bool BMTexture_SaveImage(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKSTRING, filename));
BMAP_EXPORT bool BMTexture_GetSaveOptions(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS, out_saveopt));
BMAP_EXPORT bool BMTexture_SetSaveOptions(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS, saveopt));
BMAP_EXPORT bool BMTexture_GetVideoFormat(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VX_PIXELFORMAT, out_vfmt));
BMAP_EXPORT bool BMTexture_SetVideoFormat(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VX_PIXELFORMAT, vfmt));
#pragma endregion
#pragma region CKMaterial
BMAP_EXPORT bool BMMaterial_GetDiffuse(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
BMAP_EXPORT bool BMMaterial_SetDiffuse(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
BMAP_EXPORT bool BMMaterial_GetAmbient(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
BMAP_EXPORT bool BMMaterial_SetAmbient(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
BMAP_EXPORT bool BMMaterial_GetSpecular(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
BMAP_EXPORT bool BMMaterial_SetSpecular(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
BMAP_EXPORT bool BMMaterial_GetEmissive(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
BMAP_EXPORT bool BMMaterial_SetEmissive(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
BMAP_EXPORT bool BMMaterial_GetSpecularPower(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMMaterial_SetSpecularPower(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMMaterial_GetTexture(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_texid));
BMAP_EXPORT bool BMMaterial_SetTexture(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, texid));
BMAP_EXPORT bool BMMaterial_GetTextureBorderColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_val));
BMAP_EXPORT bool BMMaterial_SetTextureBorderColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, val));
BMAP_EXPORT bool BMMaterial_GetTextureBlendMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_BLENDMODE, out_val));
BMAP_EXPORT bool BMMaterial_SetTextureBlendMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_BLENDMODE, val));
BMAP_EXPORT bool BMMaterial_GetTextureMinMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_FILTERMODE, out_val));
BMAP_EXPORT bool BMMaterial_SetTextureMinMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_FILTERMODE, val));
BMAP_EXPORT bool BMMaterial_GetTextureMagMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_FILTERMODE, out_val));
BMAP_EXPORT bool BMMaterial_SetTextureMagMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_FILTERMODE, val));
BMAP_EXPORT bool BMMaterial_GetTextureAddressMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXTEXTURE_ADDRESSMODE, out_val));
BMAP_EXPORT bool BMMaterial_SetTextureAddressMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXTEXTURE_ADDRESSMODE, val));
BMAP_EXPORT bool BMMaterial_GetSourceBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXBLEND_MODE, out_val));
BMAP_EXPORT bool BMMaterial_SetSourceBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXBLEND_MODE, val));
BMAP_EXPORT bool BMMaterial_GetDestBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXBLEND_MODE, out_val));
BMAP_EXPORT bool BMMaterial_SetDestBlend(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXBLEND_MODE, val));
BMAP_EXPORT bool BMMaterial_GetFillMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXFILL_MODE, out_val));
BMAP_EXPORT bool BMMaterial_SetFillMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXFILL_MODE, val));
BMAP_EXPORT bool BMMaterial_GetShadeMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXSHADE_MODE, out_val));
BMAP_EXPORT bool BMMaterial_SetShadeMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXSHADE_MODE, val));
BMAP_EXPORT bool BMMaterial_GetAlphaTestEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
BMAP_EXPORT bool BMMaterial_SetAlphaTestEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
BMAP_EXPORT bool BMMaterial_GetAlphaBlendEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
BMAP_EXPORT bool BMMaterial_SetAlphaBlendEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
BMAP_EXPORT bool BMMaterial_GetPerspectiveCorrectionEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
BMAP_EXPORT bool BMMaterial_SetPerspectiveCorrectionEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
BMAP_EXPORT bool BMMaterial_GetZWriteEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
BMAP_EXPORT bool BMMaterial_SetZWriteEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
BMAP_EXPORT bool BMMaterial_GetTwoSidedEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_val));
BMAP_EXPORT bool BMMaterial_SetTwoSidedEnabled(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, enabled));
BMAP_EXPORT bool BMMaterial_GetAlphaRef(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKBYTE, out_val));
BMAP_EXPORT bool BMMaterial_SetAlphaRef(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKBYTE, val));
BMAP_EXPORT bool BMMaterial_GetAlphaFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXCMPFUNC, out_val));
BMAP_EXPORT bool BMMaterial_SetAlphaFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXCMPFUNC, val));
BMAP_EXPORT bool BMMaterial_GetZFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXCMPFUNC, out_val));
BMAP_EXPORT bool BMMaterial_SetZFunc(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXCMPFUNC, val));
#pragma endregion
#pragma region CKMesh
BMAP_EXPORT bool BMMesh_GetLitMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXMESH_LITMODE, out_mode));
BMAP_EXPORT bool BMMesh_SetLitMode(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXMESH_LITMODE, mode));
BMAP_EXPORT bool BMMesh_GetVertexCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMMesh_SetVertexCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMesh_GetVertexPositions(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
BMAP_EXPORT bool BMMesh_GetVertexNormals(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxVector3*, out_mem));
BMAP_EXPORT bool BMMesh_GetVertexUVs(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxVector2*, out_mem));
BMAP_EXPORT bool BMMesh_GetFaceCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMMesh_SetFaceCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMesh_GetFaceIndices(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKWORD*, out_mem));
BMAP_EXPORT bool BMMesh_GetFaceMaterialSlotIndexs(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKWORD*, out_mem));
BMAP_EXPORT bool BMMesh_GetMaterialSlotCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKDWORD, out_count));
BMAP_EXPORT bool BMMesh_SetMaterialSlotCount(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, count));
BMAP_EXPORT bool BMMesh_GetMaterialSlot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, index), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_mtlid));
BMAP_EXPORT bool BMMesh_SetMaterialSlot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKDWORD, index), BMPARAM_IN(LibCmo::CK2::CK_ID, mtlid));
#pragma endregion
#pragma region CK3dEntity
BMAP_EXPORT bool BM3dEntity_GetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxMatrix, out_mat));
BMAP_EXPORT bool BM3dEntity_SetWorldMatrix(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxMatrix, mat));
BMAP_EXPORT bool BM3dEntity_GetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CK2::CK_ID, out_meshid));
BMAP_EXPORT bool BM3dEntity_SetCurrentMesh(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CK2::CK_ID, meshid));
BMAP_EXPORT bool BM3dEntity_GetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(bool, out_isVisible));
BMAP_EXPORT bool BM3dEntity_SetVisibility(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(bool, is_visible));
#pragma endregion
#pragma region CK3dObject
// nothing
#pragma endregion
#pragma region CKLight
BMAP_EXPORT bool BMLight_GetType(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VXLIGHT_TYPE, out_val));
BMAP_EXPORT bool BMLight_SetType(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VXLIGHT_TYPE, val));
BMAP_EXPORT bool BMLight_GetColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::VxMath::VxColor, out_val));
BMAP_EXPORT bool BMLight_SetColor(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::VxMath::VxColor, col));
BMAP_EXPORT bool BMLight_GetConstantAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetConstantAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetLinearAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetLinearAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetQuadraticAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetQuadraticAttenuation(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetRange(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetRange(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetHotSpot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetHotSpot(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetFalloff(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetFalloff(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
BMAP_EXPORT bool BMLight_GetFalloffShape(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_OUT(LibCmo::CKFLOAT, out_val));
BMAP_EXPORT bool BMLight_SetFalloffShape(BMPARAM_OBJECT_DECL(bmfile, objid), BMPARAM_IN(LibCmo::CKFLOAT, val));
#pragma endregion
#pragma region CKTargetLight
// nothing
#pragma endregion

473
Ballance/BMap/BMap/BMap.cpp Normal file
View File

@@ -0,0 +1,473 @@
#include "BMap.hpp"
namespace BMap {
#pragma region BMfile
BMFile::BMFile(LibCmo::CKSTRING temp_folder, LibCmo::CKSTRING texture_folder, NakedOutputCallback raw_callback, LibCmo::CKDWORD encoding_count, LibCmo::CKSTRING* encodings, bool is_loader) :
m_IsInitError(false), m_IsLoader(is_loader), m_HasLoaded(false), m_HasSaved(false), m_Context(nullptr) {
m_Context = new LibCmo::CK2::CKContext();
// binding callback with lambda wrapper.
// check whether callback is nullptr.
m_IsInitError = m_IsInitError || (raw_callback == nullptr);
if (raw_callback != nullptr) {
m_Context->SetOutputCallback([raw_callback](LibCmo::CKSTRING strl) -> void {
raw_callback(strl);
});
}
// set temp folder and texture folder
auto pm = m_Context->GetPathManager();
m_IsInitError = m_IsInitError || !pm->AddPath(texture_folder);
m_IsInitError = m_IsInitError || !pm->SetTempFolder(temp_folder);
// set encoding
LibCmo::XContainer::XArray<LibCmo::XContainer::XString> cache;
for (LibCmo::CKDWORD i = 0; i < encoding_count; ++i) {
if (encodings[i] != nullptr)
cache.emplace_back(encodings[i]);
}
m_Context->SetEncoding(cache);
m_IsInitError = m_IsInitError || !m_Context->IsValidEncoding();
// set default texture save mode is external
m_Context->SetGlobalImagesSaveOptions(LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_EXTERNAL);
// set default file write mode is whole compressed
m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED);
}
BMFile::~BMFile() {
delete m_Context;
}
#pragma region Safe Check Function
bool BMFile::IsInitError() {
return m_IsInitError;
}
bool BMFile::CanExecLoad() {
// no error, is loader, no prev load
return (!m_IsInitError && m_IsLoader && !m_HasLoaded);
}
bool BMFile::CanExecSave() {
// no error, is saver, no prev save
return (!m_IsInitError && !m_IsLoader && !m_HasSaved);
}
bool BMFile::CanExecLoaderVisitor() {
// no error, is loader, has loaded
return (!m_IsInitError && m_IsLoader && m_HasLoaded);
}
bool BMFile::CanExecSaverVisitor() {
// no error, is saver, not saveed yet
// same as CanExecSave
return (!m_IsInitError && !m_IsLoader && !m_HasSaved);
}
#pragma endregion
#pragma region Help Function
bool BMFile::Load(LibCmo::CKSTRING filename) {
if (!CanExecLoad()) return false;
// create temp ckfile and load
LibCmo::CK2::CKFileReader reader(m_Context);
LibCmo::CK2::CKERROR err = reader.DeepLoad(filename);
// detect error
if (err != LibCmo::CK2::CKERROR::CKERR_OK) {
// failed. clear document and return false
m_Context->ClearAll();
return false;
}
// sync data list to our list
m_ObjGroups.clear();
m_Obj3dObjects.clear();
m_ObjMeshes.clear();
m_ObjMaterials.clear();
m_ObjTextures.clear();
m_ObjTargetLights.clear();
for (const auto& fileobj : reader.GetFileObjects()) {
if (fileobj.ObjPtr == nullptr) continue;
switch (fileobj.ObjectCid) {
case LibCmo::CK2::CK_CLASSID::CKCID_GROUP:
m_ObjGroups.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT:
m_Obj3dObjects.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_MESH:
m_ObjMeshes.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL:
m_ObjMaterials.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE:
m_ObjTextures.emplace_back(fileobj.CreatedObjectId);
break;
case LibCmo::CK2::CK_CLASSID::CKCID_TARGETLIGHT:
m_ObjTargetLights.emplace_back(fileobj.CreatedObjectId);
break;
default:
break; // skip unknow objects
}
}
m_HasLoaded = true;
return true;
}
bool BMFile::Save(LibCmo::CKSTRING filename, LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS texture_save_opt, bool use_compress, LibCmo::CKINT compress_level) {
if (!CanExecSave()) return false;
// create temp writer
LibCmo::CK2::CKFileWriter writer(m_Context);
// fill object data
for (const auto& id : m_ObjGroups) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_Obj3dObjects) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_ObjMeshes) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_ObjMaterials) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id : m_ObjTextures) {
writer.AddSavedObject(m_Context->GetObject(id));
}
for (const auto& id :m_ObjTargetLights) {
writer.AddSavedObject(m_Context->GetObject(id));
}
// set global texture save mode
m_Context->SetGlobalImagesSaveOptions(texture_save_opt);
// set compress level
if (use_compress) {
m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED);
m_Context->SetCompressionLevel(compress_level);
} else {
m_Context->SetFileWriteMode(LibCmo::CK2::CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED);
}
// save to file and detect error
LibCmo::CK2::CKERROR err = writer.Save(filename);
// return with error detect.
m_HasSaved = true;
return err == LibCmo::CK2::CKERROR::CKERR_OK;
}
LibCmo::CK2::ObjImpls::CKObject* BMFile::GetObjectPtr(LibCmo::CK2::CK_ID objid) {
// we fetch object from CKContext to get better performance
LibCmo::CK2::ObjImpls::CKObject* obj = m_Context->GetObject(objid);
// however, we can not directly return the pointer fetched fron CKContext.
// BMFile only provide limited type visiting, we must make sure it provided ID also is existed in out stored list.
// so we check its type here. if type is not matched, we reset it to nullptr.
if (obj != nullptr) {
switch (obj->GetClassID()) {
case LibCmo::CK2::CK_CLASSID::CKCID_GROUP:
case LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT:
case LibCmo::CK2::CK_CLASSID::CKCID_MESH:
case LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL:
case LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE:
case LibCmo::CK2::CK_CLASSID::CKCID_TARGETLIGHT:
break; // okey. do nothing
default:
// this object should not be exposed to outside, reset it to nullptr
obj = nullptr;
break;
}
}
// return result
return obj;
}
#pragma endregion
#pragma region Visitor
LibCmo::CKDWORD BMFile::CommonGetObjectCount(std::vector<LibCmo::CK2::CK_ID>& container) {
// only available in loader
if (!CanExecLoaderVisitor()) return 0;
return static_cast<LibCmo::CKDWORD>(container.size());
}
LibCmo::CK2::CK_ID BMFile::CommonGetObject(std::vector<LibCmo::CK2::CK_ID>& container, LibCmo::CKDWORD idx) {
// only available in loader
if (!CanExecLoaderVisitor()) return 0;
return container[idx];
}
LibCmo::CK2::CK_ID BMFile::CommonCreateObject(std::vector<LibCmo::CK2::CK_ID>& container, LibCmo::CK2::CK_CLASSID cid) {
// only available in saver
if (!CanExecSaverVisitor()) return 0;
// try create object and get its pointer
LibCmo::CK2::ObjImpls::CKObject* obj = m_Context->CreateObject(cid, nullptr);
// check creation validation
if (obj == nullptr) return 0;
// if success, write its id and emplace its id into list
LibCmo::CK2::CK_ID objid = obj->GetID();
container.emplace_back(objid);
return objid;
}
LibCmo::CKDWORD BMFile::GetGroupCount() { return CommonGetObjectCount(m_ObjGroups); }
LibCmo::CK2::CK_ID BMFile::GetGroup(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjGroups, idx); }
LibCmo::CK2::CK_ID BMFile::CreateGroup() { return CommonCreateObject(m_ObjGroups, LibCmo::CK2::CK_CLASSID::CKCID_GROUP); }
LibCmo::CKDWORD BMFile::Get3dObjectCount() { return CommonGetObjectCount(m_Obj3dObjects); }
LibCmo::CK2::CK_ID BMFile::Get3dObject(LibCmo::CKDWORD idx) { return CommonGetObject(m_Obj3dObjects, idx); }
LibCmo::CK2::CK_ID BMFile::Create3dObject() { return CommonCreateObject(m_Obj3dObjects, LibCmo::CK2::CK_CLASSID::CKCID_3DOBJECT); }
LibCmo::CKDWORD BMFile::GetMeshCount() { return CommonGetObjectCount(m_ObjMeshes); }
LibCmo::CK2::CK_ID BMFile::GetMesh(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjMeshes, idx); }
LibCmo::CK2::CK_ID BMFile::CreateMesh() { return CommonCreateObject(m_ObjMeshes, LibCmo::CK2::CK_CLASSID::CKCID_MESH); }
LibCmo::CKDWORD BMFile::GetMaterialCount() { return CommonGetObjectCount(m_ObjMaterials); }
LibCmo::CK2::CK_ID BMFile::GetMaterial(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjMaterials, idx); }
LibCmo::CK2::CK_ID BMFile::CreateMaterial() { return CommonCreateObject(m_ObjMaterials, LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL); }
LibCmo::CKDWORD BMFile::GetTextureCount() { return CommonGetObjectCount(m_ObjTextures); }
LibCmo::CK2::CK_ID BMFile::GetTexture(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjTextures, idx); }
LibCmo::CK2::CK_ID BMFile::CreateTexture() { return CommonCreateObject(m_ObjTextures, LibCmo::CK2::CK_CLASSID::CKCID_TEXTURE); }
LibCmo::CKDWORD BMFile::GetTargetLightCount() { return CommonGetObjectCount(m_ObjTargetLights); }
LibCmo::CK2::CK_ID BMFile::GetTargetLight(LibCmo::CKDWORD idx) { return CommonGetObject(m_ObjTargetLights, idx); }
LibCmo::CK2::CK_ID BMFile::CreateTargetLight() { return CommonCreateObject(m_ObjTargetLights, LibCmo::CK2::CK_CLASSID::CKCID_TARGETLIGHT); }
#pragma endregion
#pragma endregion
#pragma region BMMeshTransition
BMMeshTransition::TransitionVertex::TransitionVertex(
const LibCmo::VxMath::VxVector3& vec,
const LibCmo::VxMath::VxVector3& norm,
const LibCmo::VxMath::VxVector2& uv) :
m_Vertex(vec), m_Norm(norm), m_UV(uv) {}
BMMeshTransition::TransitionFace::TransitionFace(LibCmo::CKDWORD _i1, LibCmo::CKDWORD _i2, LibCmo::CKDWORD _i3, LibCmo::CKDWORD mtl_id) :
m_Idx1(_i1), m_Idx2(_i2), m_Idx3(_i3), m_MtlSlotIdx(mtl_id) {}
bool BMMeshTransition::TransitionVertexCompare::operator()(const TransitionVertex& lhs, const TransitionVertex& rhs) const {
if (auto cmp = std::memcmp(&lhs.m_Vertex, &rhs.m_Vertex, sizeof(LibCmo::VxMath::VxVector3)); cmp != 0) return cmp < 0;
if (auto cmp = std::memcmp(&lhs.m_Norm, &rhs.m_Norm, sizeof(LibCmo::VxMath::VxVector3)); cmp != 0) return cmp < 0;
return std::memcmp(&lhs.m_UV, &rhs.m_UV, sizeof(LibCmo::VxMath::VxVector2)) < 0;
}
BMMeshTransition::BMMeshTransition() :
m_IsVertexOK(false), m_IsNormalOK(false), m_IsUVOK(false), m_IsFaceOK(false), m_IsMtlSlotOK(false),
m_IsParsed(false),
m_Vertexs(), m_Normals(), m_UVs(),
m_MtlSlots(),
m_FaceVertexs(), m_FaceNormals(), m_FaceUVs(), m_FaceMtlSlotIdxs(),
m_ProcVertexs(), m_ProcFaces(), m_ProcDupRemover() {}
BMMeshTransition::~BMMeshTransition() {}
bool BMMeshTransition::PrepareVertexCount(LibCmo::CKDWORD count) {
if (m_IsParsed) return false;
m_Vertexs.resize(count);
m_IsVertexOK = true;
return true;
}
LibCmo::VxMath::VxVector3* BMMeshTransition::PrepareVertex() {
if (m_IsParsed || !m_IsVertexOK) return nullptr;
return m_Vertexs.data();
}
bool BMMeshTransition::PrepareNormalCount(LibCmo::CKDWORD count) {
if (m_IsParsed) return false;
m_Normals.resize(count);
m_IsNormalOK = true;
return true;
}
LibCmo::VxMath::VxVector3* BMMeshTransition::PrepareNormal() {
if (m_IsParsed || !m_IsNormalOK) return nullptr;
return m_Normals.data();
}
bool BMMeshTransition::PrepareUVCount(LibCmo::CKDWORD count) {
if (m_IsParsed) return false;
m_UVs.resize(count);
m_IsUVOK = true;
return true;
}
LibCmo::VxMath::VxVector2* BMMeshTransition::PrepareUV() {
if (m_IsParsed || !m_IsUVOK) return nullptr;
return m_UVs.data();
}
bool BMMeshTransition::PrepareMtlSlotCount(LibCmo::CKDWORD count) {
if (m_IsParsed) return false;
m_MtlSlots.resize(count, 0);
m_IsMtlSlotOK = true;
return true;
}
LibCmo::CK2::CK_ID* BMMeshTransition::PrepareMtlSlot() {
if (m_IsParsed || !m_IsMtlSlotOK) return nullptr;
return m_MtlSlots.data();
}
bool BMMeshTransition::PrepareFaceCount(LibCmo::CKDWORD count) {
if (m_IsParsed) return false;
m_FaceVertexs.resize(count * 3);
m_FaceNormals.resize(count * 3);
m_FaceUVs.resize(count * 3);
m_FaceMtlSlotIdxs.resize(count);
m_IsFaceOK = true;
return true;
}
LibCmo::CKDWORD* BMMeshTransition::PrepareFaceVertexIndices() {
if (m_IsParsed || !m_IsFaceOK) return nullptr;
return m_FaceVertexs.data();
}
LibCmo::CKDWORD* BMMeshTransition::PrepareFaceNormalIndices() {
if (m_IsParsed || !m_IsFaceOK) return nullptr;
return m_FaceNormals.data();
}
LibCmo::CKDWORD* BMMeshTransition::PrepareFaceUVIndices() {
if (m_IsParsed || !m_IsFaceOK) return nullptr;
return m_FaceUVs.data();
}
LibCmo::CKDWORD* BMMeshTransition::PrepareFaceMtlSlot() {
if (m_IsParsed || !m_IsFaceOK) return nullptr;
return m_FaceMtlSlotIdxs.data();
}
bool BMMeshTransition::Parse(BMFile* bmfile, LibCmo::CK2::CK_ID mesh_id) {
// check basic status
if (m_IsParsed || bmfile == nullptr) return false;
if (!m_IsVertexOK || !m_IsNormalOK || !m_IsUVOK || !m_IsFaceOK || !m_IsMtlSlotOK) return false;
// check pointer assign
LibCmo::CK2::ObjImpls::CKObject* writing_mesh = bmfile->GetObjectPtr(mesh_id);
if (writing_mesh == nullptr || writing_mesh->GetClassID() != LibCmo::CK2::CK_CLASSID::CKCID_MESH) return false;
// do parse
m_IsParsed = true;
DoRealParse();
// check vertex overflow
if (m_ProcVertexs.size() > std::numeric_limits<LibCmo::CKWORD>::max()) {
return false;
}
// check mtl slot overflow
if (m_MtlSlots.size() > std::numeric_limits<LibCmo::CKWORD>::max()) {
return false;
}
// apply to mesh
ApplyToMesh(bmfile, static_cast<LibCmo::CK2::ObjImpls::CKMesh*>(writing_mesh));
return true;
}
void BMMeshTransition::DoRealParse() {
// reserve vector to prevent extra mem alloc
// use the most bad situation to reserve
size_t face_size = m_FaceMtlSlotIdxs.size();
m_ProcVertexs.reserve(face_size * 3);
m_ProcFaces.reserve(face_size);
// iterate face
for (size_t faceid = 0; faceid < face_size; ++faceid) {
LibCmo::CKDWORD idx[3] { 0, 0, 0 };
for (int j = 0; j < 3; ++j) {
// create one first
TransitionVertex tvec(
m_Vertexs[m_FaceVertexs[faceid * 3 + j]],
m_Normals[m_FaceNormals[faceid * 3 + j]],
m_UVs[m_FaceUVs[faceid * 3 + j]]
);
// try insert it
auto insert_result = m_ProcDupRemover.try_emplace(tvec, static_cast<LibCmo::CKDWORD>(m_ProcVertexs.size()));
// get the new inserted index or existed index.
idx[j] = insert_result.first->second;
// if insert successfully, append to proc vertexs
if (insert_result.second) {
m_ProcVertexs.emplace_back(tvec);
}
}
// create face
m_ProcFaces.emplace_back(idx[0], idx[1], idx[2], m_FaceMtlSlotIdxs[faceid]);
}
}
void BMMeshTransition::ApplyToMesh(BMFile* bmfile, LibCmo::CK2::ObjImpls::CKMesh* write_into_mesh) {
LibCmo::CKDWORD vec_count = static_cast<LibCmo::CKDWORD>(m_ProcVertexs.size()),
face_count = static_cast<LibCmo::CKDWORD>(m_ProcFaces.size()),
mtl_count = static_cast<LibCmo::CKDWORD>(m_MtlSlots.size());
write_into_mesh->CleanMesh();
// write vertex
write_into_mesh->SetVertexCount(vec_count);
LibCmo::VxMath::VxCopyStructure(
vec_count,
write_into_mesh->GetVertexPositions(),
CKSizeof(LibCmo::VxMath::VxVector3),
CKSizeof(LibCmo::VxMath::VxVector3),
&m_ProcVertexs.data()->m_Vertex,
CKSizeof(TransitionVertex)
);
LibCmo::VxMath::VxCopyStructure(
vec_count,
write_into_mesh->GetVertexNormals(),
CKSizeof(LibCmo::VxMath::VxVector3),
CKSizeof(LibCmo::VxMath::VxVector3),
&m_ProcVertexs.data()->m_Norm,
CKSizeof(TransitionVertex)
);
LibCmo::VxMath::VxCopyStructure(
vec_count,
write_into_mesh->GetVertexUVs(),
CKSizeof(LibCmo::VxMath::VxVector2),
CKSizeof(LibCmo::VxMath::VxVector2),
&m_ProcVertexs.data()->m_UV,
CKSizeof(TransitionVertex)
);
// write face
write_into_mesh->SetFaceCount(face_count);
auto pIndices = write_into_mesh->GetFaceIndices();
auto pMtlIdx = write_into_mesh->GetFaceMaterialSlotIndexs();
for (LibCmo::CKDWORD i = 0; i < face_count; ++i) {
*(pIndices++) = static_cast<LibCmo::CKWORD>(m_ProcFaces[i].m_Idx1);
*(pIndices++) = static_cast<LibCmo::CKWORD>(m_ProcFaces[i].m_Idx2);
*(pIndices++) = static_cast<LibCmo::CKWORD>(m_ProcFaces[i].m_Idx3);
*(pMtlIdx++) = static_cast<LibCmo::CKWORD>(m_ProcFaces[i].m_MtlSlotIdx);
}
// set mtl slot
write_into_mesh->SetMaterialSlotCount(mtl_count);
LibCmo::CK2::ObjImpls::CKMaterial** pMtlSlot = write_into_mesh->GetMaterialSlots();
for (LibCmo::CKDWORD i = 0; i < mtl_count; ++i) {
// convert id to CKMaterial* and check its type
LibCmo::CK2::ObjImpls::CKObject* mtlptr = bmfile->GetObjectPtr(m_MtlSlots[i]);
if (mtlptr != nullptr && mtlptr->GetClassID() == LibCmo::CK2::CK_CLASSID::CKCID_MATERIAL) {
*(pMtlSlot++) = static_cast<LibCmo::CK2::ObjImpls::CKMaterial*>(mtlptr);
} else {
*(pMtlSlot++) = nullptr;
}
}
}
#pragma endregion
}

207
Ballance/BMap/BMap/BMap.hpp Normal file
View File

@@ -0,0 +1,207 @@
#pragma once
#include <VTAll.hpp>
#include <yycc.hpp>
#include <yycc/macro/class_copy_move.hpp>
#include <vector>
#include <cstdint>
#include <cinttypes>
#include <type_traits>
namespace BMap {
using NakedOutputCallback = void(*)(LibCmo::CKSTRING);
class BMFile {
public:
BMFile(LibCmo::CKSTRING temp_folder, LibCmo::CKSTRING texture_folder, NakedOutputCallback raw_callback, LibCmo::CKDWORD encoding_count, LibCmo::CKSTRING* encodings, bool is_reader);
~BMFile();
YYCC_DELETE_COPY_MOVE(BMFile)
// ===== Safe Check Function =====
/*
Safe Check Function will make sure this class is visited in safe mode.
Some of them are exposed to outside to report current status of this class, for example, whether there is a issue when initialize this class.
And some of them are used by internal functions to make sure there is a safe environment to execute corresponding functions.
For example, #Load function will use #CanExecLoad to detect whether it can execute loading process.
*/
public:
/**
* @brief Check whether there is an error when initializing this class.
* @details
* This class is exposed for outside code to check.
* Internal code should use one of following 4 private check functions to check environment.
* @return True if there is an error when initializing this class.
*/
bool IsInitError();
private:
/**
* @brief Check whether it's okey to execute #Load function.
* @return True if it is okey.
*/
bool CanExecLoad();
/**
* @brief Check whether it's okey to execute #Save function.
* @return True if it is okey.
*/
bool CanExecSave();
/**
* @brief Check whether it's okey to execute Loader-related function.
* @details
* Due to implementation, saving file and loading file are use the same class, BMFile to represent.
* So obviously you can visit loader-related function in a saver.
* This operation is illegal. So we need block these operation.
* This is what this function does. Provide the condition which raise blocking.
* @return True if it is okey.
*/
bool CanExecLoaderVisitor();
/**
* @brief Check whether it's okey to execute Saver-related function.
* @return True if it is okey.
* @see CanExecLoaderVisitor
*/
bool CanExecSaverVisitor();
private:
bool m_IsInitError; /**< True if an error occurs when initializing this class. */
bool m_IsLoader; /**< True if this class is a reader. */
bool m_HasLoaded; /**< True if this class has read. It's undefined behavior when visiting this variable if this class is not reader. */
bool m_HasSaved; /**< True if this class has written. It's undefined behavior when visiting this variable if this class is not writer. */
// ===== Help Function =====
public:
/**
* @brief Load document to this class.
* @param[in] filename The path to file.
* @return True if no error, otherwise false.
*/
bool Load(LibCmo::CKSTRING filename);
/**
* @brief Save current class into document.
* @param[in] filename The path to file.
* @param[in] texture_save_opt Global texture save option
* @param[in] use_compress True if use compression when saving.
* @param[in] compress_level The compress level if you choose using compression in file.
* @return
*/
bool Save(LibCmo::CKSTRING filename, LibCmo::CK2::CK_TEXTURE_SAVEOPTIONS texture_save_opt, bool use_compress, LibCmo::CKINT compress_level);
/**
* @brief Get object pointer from given ID.
* @details
* This function is specially exposed to outside for detecting whether given ID is valid in BMFile.
* Also used by BMMeshTransition to get essential objects.
* @param[in] objid The ID of object.
* @return The pointer to given ID represented object. nullptr if not found.
*/
LibCmo::CK2::ObjImpls::CKObject* GetObjectPtr(LibCmo::CK2::CK_ID objid);
// ===== Visitor =====
private:
LibCmo::CKDWORD CommonGetObjectCount(std::vector<LibCmo::CK2::CK_ID>& container);
LibCmo::CK2::CK_ID CommonGetObject(std::vector<LibCmo::CK2::CK_ID>& container, LibCmo::CKDWORD idx);
LibCmo::CK2::CK_ID CommonCreateObject(std::vector<LibCmo::CK2::CK_ID>& container, LibCmo::CK2::CK_CLASSID cid);
public:
LibCmo::CKDWORD GetGroupCount();
LibCmo::CK2::CK_ID GetGroup(LibCmo::CKDWORD idx);
LibCmo::CK2::CK_ID CreateGroup();
LibCmo::CKDWORD Get3dObjectCount();
LibCmo::CK2::CK_ID Get3dObject(LibCmo::CKDWORD idx);
LibCmo::CK2::CK_ID Create3dObject();
LibCmo::CKDWORD GetMeshCount();
LibCmo::CK2::CK_ID GetMesh(LibCmo::CKDWORD idx);
LibCmo::CK2::CK_ID CreateMesh();
LibCmo::CKDWORD GetMaterialCount();
LibCmo::CK2::CK_ID GetMaterial(LibCmo::CKDWORD idx);
LibCmo::CK2::CK_ID CreateMaterial();
LibCmo::CKDWORD GetTextureCount();
LibCmo::CK2::CK_ID GetTexture(LibCmo::CKDWORD idx);
LibCmo::CK2::CK_ID CreateTexture();
LibCmo::CKDWORD GetTargetLightCount();
LibCmo::CK2::CK_ID GetTargetLight(LibCmo::CKDWORD idx);
LibCmo::CK2::CK_ID CreateTargetLight();
private:
LibCmo::CK2::CKContext* m_Context;
std::vector<LibCmo::CK2::CK_ID> m_ObjGroups;
std::vector<LibCmo::CK2::CK_ID> m_Obj3dObjects;
std::vector<LibCmo::CK2::CK_ID> m_ObjMeshes;
std::vector<LibCmo::CK2::CK_ID> m_ObjMaterials;
std::vector<LibCmo::CK2::CK_ID> m_ObjTextures;
std::vector<LibCmo::CK2::CK_ID> m_ObjTargetLights;
};
class BMMeshTransition {
private:
struct TransitionVertex {
TransitionVertex(
const LibCmo::VxMath::VxVector3& vec,
const LibCmo::VxMath::VxVector3& norm,
const LibCmo::VxMath::VxVector2& uv);
LibCmo::VxMath::VxVector3 m_Vertex;
LibCmo::VxMath::VxVector3 m_Norm;
LibCmo::VxMath::VxVector2 m_UV;
};
struct TransitionFace {
TransitionFace(LibCmo::CKDWORD _i1, LibCmo::CKDWORD _i2, LibCmo::CKDWORD _i3, LibCmo::CKDWORD mtl_id);
LibCmo::CKDWORD m_Idx1, m_Idx2, m_Idx3;
LibCmo::CKDWORD m_MtlSlotIdx;
};
struct TransitionVertexCompare {
bool operator()(const TransitionVertex& lhs, const TransitionVertex& rhs) const;
};
public:
BMMeshTransition();
~BMMeshTransition();
YYCC_DELETE_COPY_MOVE(BMMeshTransition)
bool PrepareVertexCount(LibCmo::CKDWORD count);
LibCmo::VxMath::VxVector3* PrepareVertex();
bool PrepareNormalCount(LibCmo::CKDWORD count);
LibCmo::VxMath::VxVector3* PrepareNormal();
bool PrepareUVCount(LibCmo::CKDWORD count);
LibCmo::VxMath::VxVector2* PrepareUV();
bool PrepareMtlSlotCount(LibCmo::CKDWORD count);
LibCmo::CK2::CK_ID* PrepareMtlSlot();
bool PrepareFaceCount(LibCmo::CKDWORD count);
LibCmo::CKDWORD* PrepareFaceVertexIndices();
LibCmo::CKDWORD* PrepareFaceNormalIndices();
LibCmo::CKDWORD* PrepareFaceUVIndices();
LibCmo::CKDWORD* PrepareFaceMtlSlot();
bool Parse(BMFile* bmfile, LibCmo::CK2::CK_ID mesh_id);
private:
void DoRealParse();
void ApplyToMesh(BMFile* bmfile, LibCmo::CK2::ObjImpls::CKMesh* write_into_mesh);
bool m_IsVertexOK, m_IsNormalOK, m_IsUVOK, m_IsFaceOK, m_IsMtlSlotOK;
bool m_IsParsed;
std::vector<LibCmo::VxMath::VxVector3> m_Vertexs, m_Normals;
std::vector<LibCmo::VxMath::VxVector2> m_UVs;
std::vector<LibCmo::CKDWORD> m_FaceVertexs, m_FaceNormals, m_FaceUVs;
std::vector<LibCmo::CKDWORD> m_FaceMtlSlotIdxs;
std::vector<LibCmo::CK2::CK_ID> m_MtlSlots;
std::vector<TransitionVertex> m_ProcVertexs;
std::vector<TransitionFace> m_ProcFaces;
/**
@brief The core duplication vertex remover.
@remark
unordered_map have performance problem when dealing with massive data (in this case, big mesh).
so we use map to get stable time cost.
*/
std::map<TransitionVertex, LibCmo::CKDWORD, TransitionVertexCompare> m_ProcDupRemover;
};
}

View File

@@ -0,0 +1,67 @@
# Create shared library
add_library(BMap SHARED "")
# Setup sources
target_sources(BMap
PRIVATE
BMap/BMap.cpp
BMap/BMExports.cpp
)
# Setup headers
target_sources(BMap
PUBLIC
FILE_SET HEADERS
FILES
BMap/BMap.hpp
BMap/BMExports.hpp
)
# Setup header infomation
target_include_directories(BMap
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
# Setup linked library infomation
target_link_libraries(BMap
PRIVATE
YYCC::YYCCommonplace
LibCmo
)
# Enable export macro
target_compile_definitions(BMap
PRIVATE
BMAP_EXPORTING
)
# Install binary and headers
install(TARGETS BMap
EXPORT BMapTargets
LIBRARY DESTINATION ${NEMO_INSTALL_LIB_PATH}
ARCHIVE DESTINATION ${NEMO_INSTALL_LIB_PATH}
INCLUDES DESTINATION ${NEMO_INSTALL_INCLUDE_PATH}
FILE_SET HEADERS DESTINATION ${NEMO_INSTALL_INCLUDE_PATH}
)
# Install target
install(EXPORT BMapTargets
FILE BMapTargets.cmake
NAMESPACE NeMo::
DESTINATION ${NEMO_INSTALL_LIB_PATH}/cmake/BMap
)
# Package configuration file
write_basic_package_version_file(
BMapConfigVersion.cmake
VERSION ${PACKAGE_VERSION}
COMPATIBILITY SameMinorVersion
)
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/../../CMake/BMapConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/BMapConfig.cmake"
INSTALL_DESTINATION ${NEMO_INSTALL_LIB_PATH}/cmake/BMap
)
# Copy package files to install destination
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/BMapConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/BMapConfigVersion.cmake"
DESTINATION
${NEMO_INSTALL_LIB_PATH}/cmake/BMap
)

View File

@@ -0,0 +1,4 @@
int main(int argc, char *argv[]) {
return 0;
}

View File

@@ -0,0 +1,32 @@
# Create executable
add_executable(BMapInspector "")
# Setup sources
target_sources(BMapInspector
PRIVATE
BMapInspector.cpp
Utils.cpp
)
# Setup headers
target_sources(BMapInspector
PRIVATE
FILE_SET HEADERS
FILES
Utils.hpp
Rule.hpp
)
# Setup header infomation
target_include_directories(BMapInspector
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}"
)
# Setup linked library infomation
target_link_libraries(BMapInspector
PRIVATE
YYCC::YYCCommonplace
LibCmo
)
# Install BMapInspector
install(TARGETS BMapInspector
RUNTIME DESTINATION ${YYCC_INSTALL_BIN_PATH}
)

View File

View File

View File

View File

6
Ballance/CMakeLists.txt Normal file
View File

@@ -0,0 +1,6 @@
if (NEMO_BUILD_BMAP)
add_subdirectory(BMap)
endif ()
if (NEMO_BUILD_BMAPINSPECTOR)
add_subdirectory(BMapInspector)
endif ()