Skip to content

Commit beb8808

Browse files
committed
Full Model to DB methods
1 parent e1350c5 commit beb8808

File tree

1 file changed

+357
-0
lines changed
  • xivModdingFramework/Models/DataContainers

1 file changed

+357
-0
lines changed

xivModdingFramework/Models/DataContainers/TTModel.cs

Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,363 @@ public void SaveToFile(string filePath, Action<bool, string> loggingFunction = n
10881088
ModelModifiers.MakeImportReady(this, loggingFunction);
10891089
}
10901090

1091+
/// <summary>
1092+
/// Saves a TTModel to a .DB file for use with external importers/exporters.
1093+
/// </summary>
1094+
/// <param name="filePath"></param>
1095+
/// <param name="loggingFunction"></param>
1096+
public void SaveFullToFile(string filePath, Action<bool, string> loggingFunction = null)
1097+
{
1098+
if (loggingFunction == null)
1099+
{
1100+
loggingFunction = ModelModifiers.NoOp;
1101+
}
1102+
1103+
var directory = Path.GetDirectoryName(filePath);
1104+
1105+
ModelModifiers.MakeExportReady(this, loggingFunction);
1106+
1107+
var connectionString = "Data Source=" + filePath + ";Pooling=False;";
1108+
try
1109+
{
1110+
var boneDict = ResolveBoneHeirarchy();
1111+
1112+
// Spawn a DB connection to do the raw queries.
1113+
// Using statements help ensure we don't accidentally leave any connections open and lock the file handle.
1114+
using (var db = new SQLiteConnection(connectionString))
1115+
{
1116+
db.Open();
1117+
1118+
// Write the Data.
1119+
using (var transaction = db.BeginTransaction())
1120+
{
1121+
// Get the model Ids already in the DB
1122+
var modelList = new List<int>();
1123+
var getModelQuery = "SELECT model FROM models";
1124+
using (var cmd = new SQLiteCommand(getModelQuery, db))
1125+
{
1126+
var sqReader = cmd.ExecuteReader();
1127+
1128+
while (sqReader.Read())
1129+
{
1130+
modelList.Add(sqReader.GetInt32(0));
1131+
}
1132+
}
1133+
1134+
var modelIdx = modelList.Any() ? modelList.Max() + 1 : 0;
1135+
var modelName = Path.GetFileNameWithoutExtension(Source);
1136+
1137+
//Models
1138+
var query = @"insert into models (model, name) values ($model, $name);";
1139+
using (var cmd = new SQLiteCommand(query, db))
1140+
{
1141+
cmd.Parameters.AddWithValue("model", modelIdx);
1142+
cmd.Parameters.AddWithValue("name", modelName);
1143+
1144+
cmd.ExecuteScalar();
1145+
}
1146+
1147+
// Get the skeleton names already in the DB
1148+
var skelList = new List<string>();
1149+
var getSkelQuery = "SELECT name FROM skeleton";
1150+
using (var cmd = new SQLiteCommand(getSkelQuery, db))
1151+
{
1152+
var sqReader = cmd.ExecuteReader();
1153+
1154+
while (sqReader.Read())
1155+
{
1156+
skelList.Add(sqReader.GetString(0));
1157+
}
1158+
}
1159+
1160+
// Skeleton
1161+
query = @"insert into skeleton (name, parent, matrix_0, matrix_1, matrix_2, matrix_3, matrix_4, matrix_5, matrix_6, matrix_7, matrix_8, matrix_9, matrix_10, matrix_11, matrix_12, matrix_13, matrix_14, matrix_15)
1162+
values ($name, $parent, $matrix_0, $matrix_1, $matrix_2, $matrix_3, $matrix_4, $matrix_5, $matrix_6, $matrix_7, $matrix_8, $matrix_9, $matrix_10, $matrix_11, $matrix_12, $matrix_13, $matrix_14, $matrix_15);";
1163+
1164+
using (var cmd = new SQLiteCommand(query, db))
1165+
{
1166+
foreach (var b in boneDict)
1167+
{
1168+
// Skip the bone if it's already in the DB
1169+
if (skelList.Contains(b.Value.BoneName)) continue;
1170+
1171+
var parent = boneDict.FirstOrDefault(x => x.Value.BoneNumber == b.Value.BoneParent);
1172+
var parentName = parent.Key == null ? null : parent.Key;
1173+
cmd.Parameters.AddWithValue("name", b.Value.BoneName);
1174+
cmd.Parameters.AddWithValue("parent", parentName);
1175+
1176+
for (int i = 0; i < 16; i++)
1177+
{
1178+
cmd.Parameters.AddWithValue("matrix_" + i.ToString(), b.Value.PoseMatrix[i]);
1179+
}
1180+
1181+
cmd.ExecuteScalar();
1182+
}
1183+
}
1184+
1185+
// Get the material ids already in the DB
1186+
var matIdList = new List<int>();
1187+
var getMatIdQuery = "SELECT material_id FROM materials";
1188+
using (var cmd = new SQLiteCommand(getMatIdQuery, db))
1189+
{
1190+
var sqReader = cmd.ExecuteReader();
1191+
1192+
while (sqReader.Read())
1193+
{
1194+
matIdList.Add(sqReader.GetInt32(0));
1195+
}
1196+
}
1197+
1198+
// Start from the last material ID in the DB
1199+
var matIdx = matIdList.Any() ? matIdList.Max() + 1 : 0;
1200+
var tempMatDict = new Dictionary<string, int>();
1201+
foreach (var material in Materials)
1202+
{
1203+
// Materials
1204+
query = @"insert into materials (material_id, name, diffuse, normal, specular, opacity, emissive) values ($material_id, $name, $diffuse, $normal, $specular, $opacity, $emissive);";
1205+
using (var cmd = new SQLiteCommand(query, db))
1206+
{
1207+
var mtrl_prefix = directory + "\\" + Path.GetFileNameWithoutExtension(material.Substring(1)) + "_";
1208+
var mtrl_suffix = ".png";
1209+
var name = material;
1210+
try
1211+
{
1212+
name = Path.GetFileNameWithoutExtension(material);
1213+
}
1214+
catch
1215+
{
1216+
1217+
}
1218+
cmd.Parameters.AddWithValue("material_id", matIdx);
1219+
cmd.Parameters.AddWithValue("name", name);
1220+
cmd.Parameters.AddWithValue("diffuse", mtrl_prefix + "d" + mtrl_suffix);
1221+
cmd.Parameters.AddWithValue("normal", mtrl_prefix + "n" + mtrl_suffix);
1222+
cmd.Parameters.AddWithValue("specular", mtrl_prefix + "s" + mtrl_suffix);
1223+
cmd.Parameters.AddWithValue("emissive", mtrl_prefix + "e" + mtrl_suffix);
1224+
cmd.Parameters.AddWithValue("opacity", mtrl_prefix + "o" + mtrl_suffix);
1225+
cmd.ExecuteScalar();
1226+
}
1227+
tempMatDict.Add(Path.GetFileNameWithoutExtension(material), matIdx);
1228+
matIdx++;
1229+
}
1230+
1231+
// Get the mesh ids already in the DB for Bones
1232+
var meshIdList = new List<int>();
1233+
var getMeshIdQuery = "SELECT mesh FROM bones";
1234+
using (var cmd = new SQLiteCommand(getMeshIdQuery, db))
1235+
{
1236+
var sqReader = cmd.ExecuteReader();
1237+
1238+
while (sqReader.Read())
1239+
{
1240+
meshIdList.Add(sqReader.GetInt32(0));
1241+
}
1242+
}
1243+
1244+
// Start from the last mesh ID in the DB
1245+
var meshIdx = meshIdList.Any() ? meshIdList.Max() + 1 : 0;
1246+
foreach (var m in MeshGroups)
1247+
{
1248+
// Bones
1249+
query = @"insert into bones (mesh, bone_id, name) values ($mesh, $bone_id, $name);";
1250+
var bIdx = 0;
1251+
foreach (var b in m.Bones)
1252+
{
1253+
using (var cmd = new SQLiteCommand(query, db))
1254+
{
1255+
cmd.Parameters.AddWithValue("name", b);
1256+
cmd.Parameters.AddWithValue("bone_id", bIdx);
1257+
cmd.Parameters.AddWithValue("parent_id", null);
1258+
cmd.Parameters.AddWithValue("mesh", meshIdx);
1259+
cmd.ExecuteScalar();
1260+
}
1261+
bIdx++;
1262+
}
1263+
1264+
// Meshes
1265+
query = @"insert into meshes (mesh, model, name, material_id) values ($mesh, $model, $name, $material_id);";
1266+
using (var cmd = new SQLiteCommand(query, db))
1267+
{
1268+
cmd.Parameters.AddWithValue("name", m.Name);
1269+
cmd.Parameters.AddWithValue("model", modelIdx);
1270+
cmd.Parameters.AddWithValue("mesh", meshIdx);
1271+
cmd.Parameters.AddWithValue("material_id", tempMatDict[Path.GetFileNameWithoutExtension(m.Material)]);
1272+
cmd.ExecuteScalar();
1273+
}
1274+
1275+
1276+
// Parts
1277+
var partIdx = 0;
1278+
foreach (var p in m.Parts)
1279+
{
1280+
// Parts
1281+
query = @"insert into parts (mesh, part, name) values ($mesh, $part, $name);";
1282+
using (var cmd = new SQLiteCommand(query, db))
1283+
{
1284+
cmd.Parameters.AddWithValue("name", p.Name);
1285+
cmd.Parameters.AddWithValue("part", partIdx);
1286+
cmd.Parameters.AddWithValue("mesh", meshIdx);
1287+
cmd.ExecuteScalar();
1288+
}
1289+
1290+
// Vertices
1291+
var vIdx = 0;
1292+
foreach (var v in p.Vertices)
1293+
{
1294+
query = @"insert into vertices ( mesh, part, vertex_id, position_x, position_y, position_z, normal_x, normal_y, normal_z, color_r, color_g, color_b, color_a, uv_1_u, uv_1_v, uv_2_u, uv_2_v, bone_1_id, bone_1_weight, bone_2_id, bone_2_weight, bone_3_id, bone_3_weight, bone_4_id, bone_4_weight)
1295+
values ($mesh, $part, $vertex_id, $position_x, $position_y, $position_z, $normal_x, $normal_y, $normal_z, $color_r, $color_g, $color_b, $color_a, $uv_1_u, $uv_1_v, $uv_2_u, $uv_2_v, $bone_1_id, $bone_1_weight, $bone_2_id, $bone_2_weight, $bone_3_id, $bone_3_weight, $bone_4_id, $bone_4_weight);";
1296+
using (var cmd = new SQLiteCommand(query, db))
1297+
{
1298+
cmd.Parameters.AddWithValue("part", partIdx);
1299+
cmd.Parameters.AddWithValue("mesh", meshIdx);
1300+
cmd.Parameters.AddWithValue("vertex_id", vIdx);
1301+
1302+
cmd.Parameters.AddWithValue("position_x", v.Position.X);
1303+
cmd.Parameters.AddWithValue("position_y", v.Position.Y);
1304+
cmd.Parameters.AddWithValue("position_z", v.Position.Z);
1305+
1306+
cmd.Parameters.AddWithValue("normal_x", v.Normal.X);
1307+
cmd.Parameters.AddWithValue("normal_y", v.Normal.Y);
1308+
cmd.Parameters.AddWithValue("normal_z", v.Normal.Z);
1309+
1310+
cmd.Parameters.AddWithValue("color_r", v.VertexColor[0] / 255f);
1311+
cmd.Parameters.AddWithValue("color_g", v.VertexColor[1] / 255f);
1312+
cmd.Parameters.AddWithValue("color_b", v.VertexColor[2] / 255f);
1313+
cmd.Parameters.AddWithValue("color_a", v.VertexColor[3] / 255f);
1314+
1315+
cmd.Parameters.AddWithValue("uv_1_u", v.UV1.X);
1316+
cmd.Parameters.AddWithValue("uv_1_v", v.UV1.Y);
1317+
cmd.Parameters.AddWithValue("uv_2_u", v.UV2.X);
1318+
cmd.Parameters.AddWithValue("uv_2_v", v.UV2.Y);
1319+
1320+
1321+
cmd.Parameters.AddWithValue("bone_1_id", v.BoneIds[0]);
1322+
cmd.Parameters.AddWithValue("bone_1_weight", v.Weights[0] / 255f);
1323+
1324+
cmd.Parameters.AddWithValue("bone_2_id", v.BoneIds[1]);
1325+
cmd.Parameters.AddWithValue("bone_2_weight", v.Weights[1] / 255f);
1326+
1327+
cmd.Parameters.AddWithValue("bone_3_id", v.BoneIds[2]);
1328+
cmd.Parameters.AddWithValue("bone_3_weight", v.Weights[2] / 255f);
1329+
1330+
cmd.Parameters.AddWithValue("bone_4_id", v.BoneIds[3]);
1331+
cmd.Parameters.AddWithValue("bone_4_weight", v.Weights[3] / 255f);
1332+
1333+
cmd.ExecuteScalar();
1334+
vIdx++;
1335+
}
1336+
}
1337+
1338+
// Indices
1339+
for (var i = 0; i < p.TriangleIndices.Count; i++)
1340+
{
1341+
query = @"insert into indices (mesh, part, index_id, vertex_id) values ($mesh, $part, $index_id, $vertex_id);";
1342+
using (var cmd = new SQLiteCommand(query, db))
1343+
{
1344+
cmd.Parameters.AddWithValue("part", partIdx);
1345+
cmd.Parameters.AddWithValue("mesh", meshIdx);
1346+
cmd.Parameters.AddWithValue("index_id", i);
1347+
cmd.Parameters.AddWithValue("vertex_id", p.TriangleIndices[i]);
1348+
cmd.ExecuteScalar();
1349+
}
1350+
}
1351+
1352+
partIdx++;
1353+
}
1354+
1355+
meshIdx++;
1356+
1357+
1358+
}
1359+
transaction.Commit();
1360+
}
1361+
}
1362+
}
1363+
catch (Exception Ex)
1364+
{
1365+
ModelModifiers.MakeImportReady(this, loggingFunction);
1366+
throw Ex;
1367+
}
1368+
1369+
// Undo the export ready at the start.
1370+
ModelModifiers.MakeImportReady(this, loggingFunction);
1371+
}
1372+
1373+
/// <summary>
1374+
/// Create the DB and set the Meta Data for the full model
1375+
/// </summary>
1376+
/// <param name="filePath">The DB file path</param>
1377+
/// <param name="fullModelName">The name of the full model</param>
1378+
public void SetFullModelDBMetaData(string filePath, string fullModelName)
1379+
{
1380+
var connectionString = "Data Source=" + filePath + ";Pooling=False;";
1381+
1382+
try
1383+
{
1384+
const string creationScript = "CreateImportDB.sql";
1385+
1386+
using (var db = new SQLiteConnection(connectionString))
1387+
{
1388+
db.Open();
1389+
1390+
// Create the DB
1391+
var lines = File.ReadAllLines("Resources\\SQL\\" + creationScript);
1392+
var sqlCmd = String.Join("\n", lines);
1393+
1394+
using (var cmd = new SQLiteCommand(sqlCmd, db))
1395+
{
1396+
cmd.ExecuteScalar();
1397+
}
1398+
1399+
using (var transaction = db.BeginTransaction())
1400+
{
1401+
// Metadata.
1402+
var query = @"insert into meta (key, value) values ($key, $value)";
1403+
using (var cmd = new SQLiteCommand(query, db))
1404+
{
1405+
// FFXIV stores stuff in Meters.
1406+
cmd.Parameters.AddWithValue("key", "unit");
1407+
cmd.Parameters.AddWithValue("value", "meter");
1408+
cmd.ExecuteScalar();
1409+
1410+
// Application that created the db.
1411+
cmd.Parameters.AddWithValue("key", "application");
1412+
cmd.Parameters.AddWithValue("value", "ffxiv_tt");
1413+
cmd.ExecuteScalar();
1414+
1415+
// Does the framework NOT have a version identifier? I couldn't find one, so the Cache version works.
1416+
cmd.Parameters.AddWithValue("key", "version");
1417+
cmd.Parameters.AddWithValue("value", XivCache.CacheVersion);
1418+
cmd.ExecuteScalar();
1419+
1420+
// Axis information
1421+
cmd.Parameters.AddWithValue("key", "up");
1422+
cmd.Parameters.AddWithValue("value", "y");
1423+
cmd.ExecuteScalar();
1424+
1425+
cmd.Parameters.AddWithValue("key", "front");
1426+
cmd.Parameters.AddWithValue("value", "z");
1427+
cmd.ExecuteScalar();
1428+
1429+
cmd.Parameters.AddWithValue("key", "handedness");
1430+
cmd.Parameters.AddWithValue("value", "r");
1431+
cmd.ExecuteScalar();
1432+
1433+
// FFXIV stores stuff in Meters.
1434+
cmd.Parameters.AddWithValue("key", "name");
1435+
cmd.Parameters.AddWithValue("value", fullModelName);
1436+
cmd.ExecuteScalar();
1437+
}
1438+
transaction.Commit();
1439+
}
1440+
}
1441+
}
1442+
catch (Exception ex)
1443+
{
1444+
1445+
}
1446+
}
1447+
10911448
/// <summary>
10921449
/// Creates and populates a TTModel object from a raw XivMdl
10931450
/// </summary>

0 commit comments

Comments
 (0)