Recolove Model Importer (Noesis)

Skeletons, animations, shaders, texturing, converting, fixing and anything else related to read game models
kana4567
Posts: 7
Joined: Fri Jun 08, 2018 11:37 am

Recolove Model Importer (Noesis)

Post by kana4567 »

Here is Recolove Model Importer for Noesis.
It loads mesh data (vertex, face, normals and UVs) from a *.fed model.

fmt_recolove_fed.py:

Code: Select all

# v2: Fixed face direction and UV
import math
from inc_noesis import *


def registerNoesisTypes():
    """ register plugin
    """
    handle = noesis.register("Recolove Model", ".fed")
    noesis.setHandlerTypeCheck(handle, fedCheckType)
    noesis.setHandlerLoadModel(handle, fedLoadModel)

    # noesis.logPopup()  # show console
    return 1


def fedCheckType(data):
    """ check header
    """
    FED_HEADER = 0x43415046  # FPAC
    bs = NoeBitStream(data)
    bs.seek(0)
    if bs.readInt() != FED_HEADER:
        return 0
    return 1


def fedLoadModel(data, mdlList):
    """ load model (mesh and UV)
    """
    bs = NoeBitStream(data)
    meshes = []
    myMeshes = []

    # find face sets. eg. (0, 1, 2)
    bs.seek(0)
    while not bs.checkEOF():
        firstFace = (bs.readUShort(), bs.readUShort(), bs.readUShort())
        tailVals = (bs.readUShort(), bs.readUShort(), bs.readUShort(),
                    bs.readUShort(), bs.readUShort())
        if (firstFace == (0, 1, 2) and sum(tailVals) < 30):
            myMeshes.append({"faceOffset": bs.tell() - 16})
    if len(myMeshes) == 0:
        print("no face sets.")
        return 0

    # find face counts
    for myMesh in myMeshes:
        isFound = False
        ofs = myMesh["faceOffset"]
        while True:
            ofs -= 16  # go up
            if isFound:
                break
            if ofs < 0:
                print("face count not found.")
                return 0
            bs.seek(ofs)
            numFaceX3 = bs.readUShort()
            bs.readUShort()  # unknown
            magic1C = bs.readInt()
            magicZero1 = bs.readInt64()
            numVert = bs.readInt()
            magicZero2 = bs.readInt()
            magicZero3 = bs.readInt64()
            if (numFaceX3 % 3 == 0 and magic1C == 0x1C and magicZero1 == 0 and magicZero2 == 0 and magicZero3 == 0):
                isFound = True
                myMesh["numFace"] = numFaceX3 // 3
                myMesh["numVert"] = numVert
                myMesh["vertOffset"] = bs.tell()

    for myMesh in myMeshes:
        print(myMesh)

        verts = []
        bs.seek(myMesh["vertOffset"])
        for i in range(myMesh["numVert"]):
            x = _getFloat(bs)
            y = _getFloat(bs)
            z = _getFloat(bs)
            verts.append(NoeVec3((x, y, z)))
        _padding(bs)

        normals = []
        for i in range(myMesh["numVert"]):
            x = _getFloat(bs)
            y = _getFloat(bs)
            z = _getFloat(bs)
            normals.append(NoeVec3((x, y, z)))
        _padding(bs)

        if bs.readBytes(4)[3] == 0xFF:  # Skip, may be weights
            bs.seek(-4, NOESEEK_REL)
            bs.readBytes(myMesh["numVert"] * 4)
            _padding(bs)

        uvs = []
        for i in range(myMesh["numVert"]):
            u = _getFloat(bs)
            v = _getFloat(bs) + 1.0
            uvs.append(NoeVec3((u, v, 0.0)))
        _padding(bs)

        if bs.tell() != myMesh["faceOffset"]:
            print("  SKIP: UV exceeds faceOffset: %d" % bs.tell())
            continue

        idxList = []
        for i in range(myMesh["numFace"]):
            indices = (bs.readUShort(), bs.readUShort(), bs.readUShort())
            idxList.append(indices[2])
            idxList.append(indices[1])
            idxList.append(indices[0])
        _padding(bs)

        meshName = "mesh_%08X" % myMesh["vertOffset"]
        mesh = NoeMesh(idxList, verts, meshName)
        mesh.setNormals(normals)
        mesh.setUVs(uvs)
        meshes.append(mesh)

    mdlList.append(NoeModel(meshes))
    return 1


def _getFloat(bs: NoeBitStream):
    """ get float value, skipping NaN
    """
    val = bs.readFloat()
    if not math.isnan(val):
        return val
    else:
        return bs.readFloat()


def _padding(bs: NoeBitStream):
    """ padding by 16 bytes
    """
    mod = bs.tell() % 16
    if mod != 0:
        bs.readBytes(16 - mod)


You will also need to use the following tools.

1. CPK Unpacker (to obtain fed files):
https://github.com/esperknight/CriPakTo ... ster/Build

2. QuickBMS and this script (to extract *.tex files):
http://aluigi.altervista.org/bms/fpactex.bms

3. Texture Unpacker (to convert textures):
https://github.com/xdanieldzd/GXTConvert/releases
Last edited by kana4567 on Fri Jun 22, 2018 7:32 am, edited 3 times in total.
beargood
Posts: 2
Joined: Sat Jun 16, 2018 12:31 pm

Re: Recolove Model Importer (Noesis)

Post by beargood »

I got recolove dumped data.
When I tried to expand. cpk with cripaktools, I could not extract it by saying cannnot find ALL.
https://imgur.com/a/uiwQ6pB
Is it necessary to decrypt it?
This is the .cpk file i got.
https://mega.nz/#!kIFDSIQI!x-CBWFLmHYyu ... QZDmAJC5JY
kana4567
Posts: 7
Joined: Fri Jun 08, 2018 11:37 am

Re: Recolove Model Importer (Noesis)

Post by kana4567 »

Yes, you have to decrypt game files by using a tool like this:
https://github.com/motoharu-gosuto/psvpfstools/releases
Tsuna__
Posts: 7
Joined: Wed Jun 20, 2018 1:18 pm

Re: Recolove Model Importer (Noesis)

Post by Tsuna__ »

It doesn't work.

i get this

"Successfully decompressed zRIF from provided license string.
failed to find unicv.db file or icv.db in folder"
kana4567
Posts: 7
Joined: Fri Jun 08, 2018 11:37 am

Re: Recolove Model Importer (Noesis)

Post by kana4567 »

Make sure that you are using the latest dump tool.
https://github.com/TheOfficialFloW/NoNpDrm

I'm not a professional of decryption,
but Reddit or gbatemp forums may help you.
kana4567
Posts: 7
Joined: Fri Jun 08, 2018 11:37 am

Re: Recolove Model Importer (Noesis)

Post by kana4567 »

Here is a little guide to decrypt files. A retail game is needed.

Install h-encore on PS Vita 3.68.
https://github.com/TheOfficialFloW/h-encore

Install AntiBlacklist (in case of VitaTV).
https://vitadb.rinnegatamante.it/#/info/11

Install NoNpDrm and reboot device.
https://github.com/TheOfficialFloW/NoNpDrm#installation
https://github.com/TheOfficialFloW/NoNp ... ke-license

When you first launch the game, a file "6488b73b912a753a492e2714e9b38bc7.rif" will be created.
Open it by hex editor and you will see the license key at 0x50.

Copy "gro0:app/TITLE_ID" folder to your PC via FTP, then decrypt files using psvpfsparser.
Note that the license key corresponds "--klicensee" parameter.
https://github.com/motoharu-gosuto/psvpfstools/releases
Last edited by kana4567 on Fri Jul 06, 2018 2:45 pm, edited 2 times in total.
beargood
Posts: 2
Joined: Sat Jun 16, 2018 12:31 pm

Re: Recolove Model Importer (Noesis)

Post by beargood »

kana4567,Thank you!
I appreciate your help.
I was able to obtain it.
https://imgur.com/a/Y868rsA
However, it seems that some files are not expanded correctly.
https://imgur.com/a/Meg0sBK
Are you planning to solve this problem?
kana4567
Posts: 7
Joined: Fri Jun 08, 2018 11:37 am

Re: Recolove Model Importer (Noesis)

Post by kana4567 »

beargood, congrats!

> it seems that some files are not expanded correctly

You don't have to worry about that.
Some head models contains strange triangle meshes between the face (top) and hairs (bottom).
Please delete those meshes at the middle, after exporting.

One more thing, the original filenames (*.fed, *.tex) are listed in the following files:
- TITLE_ID/media/afs/CharaModel.als
- TITLE_ID/media/afs/CharaTex.als
Last edited by kana4567 on Thu Jun 28, 2018 2:24 pm, edited 1 time in total.
Tsuna__
Posts: 7
Joined: Wed Jun 20, 2018 1:18 pm

Re: Recolove Model Importer (Noesis)

Post by Tsuna__ »

Ah, thats cool i hope it will work for me too once i get my 3.60 vita

thank you for the tutorial, finger crossed, as they say
Tsuna__
Posts: 7
Joined: Wed Jun 20, 2018 1:18 pm

Re: Recolove Model Importer (Noesis)

Post by Tsuna__ »

Edit:
Well i did it, tho all the models seem to miss the ears, do you know by any chance where they are ?
kana4567
Posts: 7
Joined: Fri Jun 08, 2018 11:37 am

Re: Recolove Model Importer (Noesis)

Post by kana4567 »

> all the models seem to miss the ears

Wow, I never realized it, as most girls in this game have hairs which covers ears!
Unfortunately, my script can't load (find) those sub-meshes.

But I guess ears should exist in the same *.fed file, because the file has string like "EAR" or "EARShape".
Tsuna__
Posts: 7
Joined: Wed Jun 20, 2018 1:18 pm

Re: Recolove Model Importer (Noesis)

Post by Tsuna__ »

Yeah also some of them miss some hair accessories like bows
kana4567
Posts: 7
Joined: Fri Jun 08, 2018 11:37 am

Re: Recolove Model Importer (Noesis)

Post by kana4567 »

Sorry but I don't have enough time and information (about file format) to fix that.
For now, I recommend you to create your own sub-meshes if there were some missing parts.

All I did is just finding chunks of floating-point numbers, by viewing file in Hex Workshop like this:
bit-image-fed.png


Anyway, If anyone knows similar 3D model format (by CRIWARE), please let me know!
I believe that *.fed files also contain bones, weights and blendshapes.