...
 
Commits (1)
......@@ -178,6 +178,8 @@ module.exports = class App extends App_Base
filePath = this.args.file;
}
filePath = "C:/Users/Max/.ice-spear-projects/test/shrines/unpacked/Dungeon063.pack.unpacked/Model/DgnMrgPrt_Dungeon063.sbfres";
if(filePath != "")
await this.openFile(filePath);
}
......
......@@ -73,11 +73,11 @@
<tbody>
<tr>
<td>HashId</td>
<td><input class="form-control data-actor-params-HashId" type="text" /></td>
<td><input class="form-control data-actor-params-HashId" type="text" readonly /></td>
</tr>
<tr>
<td>SRTHash</td>
<td><input class="form-control data-actor-params-SRTHash" type="text" /></td>
<td><input class="form-control data-actor-params-SRTHash" type="text" readonly /></td>
</tr>
</tbody>
</table>
......
......@@ -108,11 +108,26 @@ module.exports = class Editor_Model
this.node.querySelector(".data-header-fmatCount").innerHTML = this.entry.parser.header.fmatCount;
this.node.querySelector(".data-header-userDataCount").innerHTML = this.entry.parser.header.userDataCount;
console.log(this.threeJsRenderer);
this.threeJsRenderer.start();
/////// TEST ///////
const HK = require("./../../hk_coll/loader");
const hk = new HK();
const collFile = "C:/Users/Max/.ice-spear-projects/test/shrines/Dungeon063.hksc";
hk.load(collFile);
const meshArr = hk.getMesh();
for(let m of meshArr)
this.threeJsRenderer.addObject(m);
//return;
/////// TEST ///////
for(let i in this.entry.parser.models)
{
const subModel = this.threeJsRenderer.createModel(this.entry.parser.models[i]);
subModel.material.opacity = 0.75;
this.threeJsRenderer.addObject(subModel);
}
......
{
"magic": { "type": "u8", "count": 4 },
"__UNKNOWN_00": { "type": "u8", "count": 35 },
"versionName": {"type": "string"},
"__UNKNOWN_01": { "type": "u32", "default": 255 },
"__UNKNOWN_02": { "type": "u8", "count": 21 },
"sections": { "type": "structure", "count": 3,
"structure": {
"sectionName": {"type": "string", "length": 16},
"offsetMaster": {"type": "u32"},
"offsets": {"type": "u32", "count": 7},
"__PADDING_00": {"type": "u8", "count": 16}
}
}
}
\ No newline at end of file
{
"__PADDING": {"type": "u8", "count": 8},
"__UNKNOWN": {"type": "u8", "count": 4},
"from": {"type": "u32"},
"to": {"type": "u32"}
}
\ No newline at end of file
/**
* @copyright 2018 - Max Bebök
* @author Max Bebök
* @license GNU-GPLv3 - see the "LICENSE" file in the root directory
*/
const Binary_File = require("binary-file");
const structureHeader = require("./header.json");
const structureIndex = require("./index.json");
module.exports = class HK_Loader
{
constructor()
{
this.meshArray = [];
}
getMesh()
{
return this.meshArray;
}
_idToHex(id)
{
return id.toString("16").toUpperCase().padStart(8, "0");
}
f16ToF32(binary)
{
var exponent = (binary & 0x7C00) >> 10,
fraction = binary & 0x03FF;
return (binary >> 15 ? -1 : 1) * (
exponent ?
(
exponent === 0x1F ?
fraction ? NaN : Infinity :
Math.pow(2, exponent - 15) * (1 + fraction / 0x400)
) :
6.103515625e-5 * (fraction / 0x400)
);
}
load(hkPath)
{
this.meshArray = [];
const parser = new Binary_File.Parser(hkPath);
parser.file.setEndian("big");
const res = parser.parse(structureHeader);
console.log(res);
console.log(res.sections);
const buff = parser.file.buffer;
const actorDataView = new DataView(buff.buffer, buff.byteOffset + 0x180);
let actorDataViewPos = 0;
const actorInfo = {};
for(let i=0; i<169; ++i)
{
let id = this._idToHex(actorDataView.getUint32(actorDataViewPos));
actorDataViewPos += 8;
let index = this._idToHex(actorDataView.getUint32(actorDataViewPos));
actorDataViewPos += 8;
actorInfo[id] = index;
}
console.log(actorInfo);
/*
// @ 0x1A50 floats
// @ 0xD340 / 0xD3D0 floats
// @ 0xD830 s32?
console.log("ACTOR INSTANCES");
const FLOAT_OFFSET = 0x1A70; // 0x1A70 <-> 0x456F
const VERTEX_POS_INDEX = 0;
const numPoly = 172; // correct, @
//const numPoly = 3 * 3;
const numFloats = 3 * numPoly;
let indexArray = new Uint32Array(numPoly * 3);
let indexArrayPos = 0;
let vertexArray = new Float32Array(numFloats);
let vertexArrayPos = 0;
const dataView = new DataView(buff.buffer, buff.byteOffset + FLOAT_OFFSET);
let dataViewPos = 0;
const vertexObject = [];
for(let p=0; p<numPoly; ++p)
{
const vertData = [];
for(let vertexNum=0; vertexNum<3; ++vertexNum)
{
for(let floatNum=0; floatNum<3; ++floatNum)
{
const floatVal = dataView.getFloat32(dataViewPos, false);
dataViewPos += 4;
//const floatVal = dataView.getFloat32(dataViewPos + 8 - (floatNum * 4), false);
if(vertexNum == VERTEX_POS_INDEX)
{
vertData.push(floatVal);
vertexArray[vertexArrayPos++] = floatVal;
}
}
dataViewPos += 4;
//dataViewPos += 16;
if(vertexNum == VERTEX_POS_INDEX)
{
indexArray[indexArrayPos] = indexArrayPos;
++indexArrayPos;
}
}
dataViewPos += 12; // 00000000 00000000 FFFFFFFF xxxxxxxx | xxxxxxxx = counter u32
const vertexId = dataView.getUint32(dataViewPos, false);
dataViewPos += 4;
if(vertexId != vertexObject.length)console.warn(vertexId);
vertexObject[vertexId] = vertData;
}
console.log(vertexObject);
const indexCount = 3 * 10;
const indexDataView = new DataView(buff.buffer, buff.byteOffset + 0x24550);
indexArray = new Uint32Array(indexCount);
for(let i=0; i<indexCount; ++i)
{
indexArray[i] = indexDataView.getUint16(i * 2);
}
*/
/* Torches
const numVert = 4;
let vertexArray = new Float32Array(numVert * 3);
let vertexArrayPos = 0;
const dataView = new DataView(buff.buffer, buff.byteOffset + 0x2C650);
let dataViewPos = 0;
for(let i=0; i<numVert; ++i)
{
for(let e=0; e<3; ++e)
{
const val = dataView.getFloat32(dataViewPos, false);
vertexArray[vertexArrayPos++] = val;
dataViewPos += 4;
}
dataViewPos += 4;
dataViewPos += 48;
}
*/
/*
// collision objects definitions?
let vertexArray = [];
vertexArray.push(...this._readCollMesh(buff, 0xDE30, 16)); // mostly random?
vertexArray.push(...this._readCollMesh(buff, 0x1B820, 35)); // a few ground points
vertexArray.push(...this._readCollMesh(buff, 0x89B0, 4)); // look like an arch
vertexArray.push(...this._readCollMesh(buff, 0xB6B0, 1)); // ?? box (very flat)
vertexArray.push(...this._readCollMesh(buff, 0xC190, 1)); // ?? box (cube)
vertexArray.push(...this._readCollMesh(buff, 0xCF40, 1)); // ?? box (flat)
vertexArray.push(...this._readCollMesh(buff, 0xD3D0, 1)); // ?? box (tall)
vertexArray = new Float32Array(vertexArray);
*/
// Half-Float structures
const entrySize = 4;
const offset = 0;
const scale = 1;
const entries = Math.floor((117952 - offset) / entrySize); // 063
//const entries = Math.floor((189696 - offset) / entrySize); // 002
//const entries = 24; // 24;
//const offset = 0x50B0;
//const entries = 330;
//const offset = 0xA210;
//const entries = 2402;
//const offset = 0x26DB0;
let vertexArray = new Float32Array(entries);
let vertexArrayPos = 0;
const dataView = new DataView(buff.buffer, buff.byteOffset + offset);
let dataViewPos = 0;
//let targetVal = 0x1BB0;
let targetVal = 0x1C7A0;
let targetDiff = 4 * 64;
// 0x 898 8A0
for(let i=0; i<entries; ++i)
{
let val = 0.0;
if(entrySize == 1){
val = dataView.getInt8(dataViewPos);
//val = dataView.getUint8(dataViewPos);
}else if(entrySize == 2){
val = this.f16ToF32(dataView.getUint16(dataViewPos)) * 10;
//val = dataView.getInt16(dataViewPos) / 100;
}else if(entrySize == 4){
//val = dataView.getFloat32(dataViewPos);
val = dataView.getUint32(dataViewPos);
if(Math.abs(val - targetVal) < targetDiff || Math.abs(dataViewPos+val - targetVal) < targetDiff)
{
console.log("Target found @ ", dataViewPos.toString(16));
}
//val = dataView.getInt32(dataViewPos) / 2147483648 * 50.0;
}else if(entrySize == 8){
val = dataView.getFloat64(dataViewPos);
}
val *= scale;
vertexArray[vertexArrayPos++] = val;
dataViewPos += entrySize;
}
/*
const vertexArray = new Float32Array([
0, 0, 7,
-1, -64, 0,
0, 0, 0,
-1, -64, 7,
-1, -56, 0,
0, 8, 0,
0, 8, 7,
-1, -56, 7,
]);
console.log(vertexArray);
*/
//let indexArray = null;
//console.log(indexArray);
console.log("===================");
// Dungeon002
const colorArray = null;
// Triangles & Point Cloud
this.meshArray.push(this._createPointMesh(vertexArray, colorArray));
//this.meshArray.push(this._createPolyMesh(vertexArray, null, colorArray));
//this.meshArray.push(this._createPolyMesh(vertexArray, indexArray, colorArray));
}
_readCollMesh(buff, dataOffset, numPoly)
{
const numVert = numPoly * 3;
let vertexArray = new Array(numVert * 3);
let vertexArrayPos = 0;
let indexArray = new Array(numVert * 3);
let indexArrayPos = 0;
const dataView = new DataView(buff.buffer, buff.byteOffset + dataOffset);
let dataViewPos = 0;
for(let p=0; p<numPoly; ++p)
{
for(let i=0; i<3; ++i)
{
for(let e=0; e<3; ++e)
{
let val = dataView.getFloat32(dataViewPos, false);
vertexArray[vertexArrayPos++] = val;
dataViewPos += 4;
}
dataViewPos += 4;
indexArray[indexArrayPos] = indexArrayPos;
++indexArrayPos;
}
dataViewPos += 16 * 3;
}
return vertexArray;
}
_createPointMesh(buffVertex, buffColor)
{
let pointGeometry = new THREE.BufferGeometry();
pointGeometry.addAttribute('position', new THREE.BufferAttribute(buffVertex, 3));
if(buffColor)
pointGeometry.addAttribute('color', new THREE.BufferAttribute(buffColor, 3));
var pointMaterial = new THREE.PointsMaterial({
color: 0xFFFF00,
size: 0.2,
//size: 1.25,
//vertexColors: THREE.VertexColors
});
return new THREE.Points( pointGeometry, pointMaterial );
}
_createPolyMesh(buffVertex, buffIndex, buffColor)
{
let triGeometry = new THREE.BufferGeometry();
triGeometry.addAttribute('position', new THREE.BufferAttribute(buffVertex, 3));
if(buffColor)
triGeometry.addAttribute('color', new THREE.BufferAttribute(buffColor, 3));
if(buffIndex)
triGeometry.setIndex(new THREE.BufferAttribute(buffIndex, 1));
triGeometry.computeFaceNormals();
triGeometry.computeVertexNormals();
var triMaterial = new THREE.MeshNormalMaterial({side: THREE.DoubleSide});
//return new THREE.Mesh( triGeometry, triMaterial );
return new THREE.LineSegments( triGeometry, triMaterial );
}
}
\ No newline at end of file
......@@ -31,7 +31,7 @@ module.exports = class Actor_Cache_Reader
{
jsonData.vertexArray = this._readBuffer(jsonData.vertexArray, "f32");
jsonData.indexArray = this._readBuffer(jsonData.indexArray, "u16");
if(jsonData.color0Array)
jsonData.color0Array = this._readBuffer(jsonData.color0Array, "f32");
......
......@@ -34,6 +34,11 @@ module.exports = class Actor_GUI
this._addCallbacks();
}
_idToHex(id)
{
return id.toString("16").toUpperCase().padStart(8, "0");
}
/**
* updates the ui with the assigned actor
*/
......@@ -42,8 +47,8 @@ module.exports = class Actor_GUI
this.nodeCache.querySelector(".data-actor-name").innerHTML = this.actor.getName();
this.nodeCache.querySelector(".data-actor-type").innerHTML = this.actor.type;
this.nodeCache.querySelector(".data-actor-params-HashId").value = this.actor.params.HashId.value;
this.nodeCache.querySelector(".data-actor-params-SRTHash").value = this.actor.params.SRTHash.value;
this.nodeCache.querySelector(".data-actor-params-HashId").value = this._idToHex(this.actor.params.HashId.value)
this.nodeCache.querySelector(".data-actor-params-SRTHash").value = this._idToHex(this.actor.params.SRTHash.value);
const modelTypeImg = this.actor.isInvisible() ? "with-model.png" : "no-model.png";
this.nodeCache.querySelector("img.actor-model-type").setAttribute("src", "assets/img/icons/actor/" + modelTypeImg);
......