DigglesTool/pkg/threedb/decoder.go
2024-07-19 10:21:26 +03:00

491 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package threedb
import (
"encoding/binary"
"errors"
"io"
"log"
)
type Decoder struct {
reader io.ReadSeeker
}
func NewDecoder(reader io.ReadSeeker) *Decoder {
return &Decoder{reader: reader}
}
func (dec *Decoder) Decode(model *Model) error {
if model == nil {
return errors.New("model is nil")
}
var err error
if model.DBVersion, err = dec.readString(); err != nil {
return err
}
if model.Name, err = dec.readString(); err != nil {
return err
}
if err = dec.readMaterials(model); err != nil {
return err
}
if err = dec.readMeshes(model); err != nil {
return err
}
if err = dec.readObjects(model); err != nil {
return err
}
if err = dec.readAnimations(model); err != nil {
return err
}
if err = dec.readShadows(model); err != nil {
return err
}
if err = dec.readCubeMaps(model); err != nil {
return err
}
if err = dec.readData(model); err != nil {
return err
}
return nil
}
func (dec *Decoder) seek(offset int64) (err error) {
_, err = dec.reader.Seek(offset, io.SeekCurrent)
return
}
func (dec *Decoder) read(dst any) error {
return binary.Read(dec.reader, binary.LittleEndian, dst)
}
func (dec *Decoder) readUInt8() (result uint8, err error) {
err = dec.read(&result)
return
}
func (dec *Decoder) readUInt16() (result uint16, err error) {
err = dec.read(&result)
return
}
func (dec *Decoder) readUInt32() (result uint32, err error) {
err = dec.read(&result)
return
}
func (dec *Decoder) readFloat32() (result float32, err error) {
err = dec.read(&result)
return
}
func (dec *Decoder) readString() (string, error) {
length, err := dec.readUInt32()
if err != nil {
return "", err
}
buf := make([]byte, length)
if err = dec.read(&buf); err != nil {
return "", err
}
return string(buf), nil
}
func (dec *Decoder) readVector() (*Vector, error) {
var vec Vector
var err error
if vec[0], err = dec.readFloat32(); err != nil {
return nil, err
}
if vec[1], err = dec.readFloat32(); err != nil {
return nil, err
}
if vec[2], err = dec.readFloat32(); err != nil {
return nil, err
}
return &vec, nil
}
func (dec *Decoder) readMaterials(model *Model) error {
materialCount, err := dec.readUInt16()
if err != nil {
return err
}
count := int(materialCount)
for i := 0; i < count; i++ {
material := Material{}
if material.Name, err = dec.readString(); err != nil {
return err
}
if material.Path, err = dec.readString(); err != nil {
return err
}
if material.Unknown, err = dec.readUInt32(); err != nil {
return err
}
model.Materials = append(model.Materials, material)
}
return nil
}
func (dec *Decoder) readMeshes(model *Model) error {
meshCount, err := dec.readUInt32()
if err != nil {
return err
}
count := int(meshCount)
for i := 0; i < count; i++ {
mesh := Mesh{}
if err = dec.readMeshLink(&mesh); err != nil {
return err
}
if mesh.Vector1, err = dec.readVector(); err != nil {
return err
}
if mesh.Vector2, err = dec.readVector(); err != nil {
return err
}
_ = dec.seek(0x80)
if mesh.Shadow, err = dec.readUInt16(); err != nil {
return err
} // Mesh Shadow Index ?
_ = dec.seek(0x30)
if mesh.CMap, err = dec.readUInt16(); err != nil {
return err
} // Mesh CMap Index ?
model.Meshes = append(model.Meshes, mesh)
}
return nil
}
func (dec *Decoder) readMeshLink(mesh *Mesh) error {
meshLinkCount, err := dec.readUInt16()
if err != nil {
return err
}
count := int(meshLinkCount)
for i := 0; i < count; i++ {
meshLink := MeshLink{}
if meshLink.Material, err = dec.readUInt16(); err != nil {
return err
}
if meshLink.Unknown, err = dec.readUInt16(); err != nil {
return err
}
if meshLink.Triangles, err = dec.readUInt16(); err != nil {
return err
}
if meshLink.TextureCoordinates, err = dec.readUInt16(); err != nil {
return err
}
if meshLink.Points, err = dec.readUInt16(); err != nil {
return err
}
if meshLink.Brightness, err = dec.readUInt16(); err != nil {
return err
}
mesh.Links = append(mesh.Links, meshLink)
}
return nil
}
func (dec *Decoder) readObjects(model *Model) error {
keyValuePairCount, err := dec.readUInt16()
if err != nil {
return err
}
count := int(keyValuePairCount)
if count > 0 && model.Objects == nil {
model.Objects = make(map[string][]uint32)
}
for i := 0; i < count; i++ {
var key string
if key, err = dec.readString(); err != nil {
return err
}
var objectCount uint16
if objectCount, err = dec.readUInt16(); err != nil {
return err
}
model.Objects[key] = make([]uint32, objectCount)
for j := 0; j < int(objectCount); j++ {
var n uint32
if n, err = dec.readUInt32(); err != nil {
return err
}
model.Objects[key] = append(model.Objects[key], n)
}
}
return nil
}
func (dec *Decoder) readAnimations(model *Model) error {
animationCount, err := dec.readUInt16()
if err != nil {
return err
}
count := int(animationCount)
for i := 0; i < count; i++ {
animation := Animation{}
if animation.Name, err = dec.readString(); err != nil {
return err
}
var meshIndexesCount uint16
if meshIndexesCount, err = dec.readUInt16(); err != nil {
return err
}
animation.MeshIndexes = make([]uint32, meshIndexesCount)
for j := 0; j < int(meshIndexesCount); j++ {
var n uint32
if n, err = dec.readUInt32(); err != nil {
return err
}
animation.MeshIndexes[j] = n
}
if animation.Unknown, err = dec.readUInt16(); err != nil {
return err
}
if animation.Unknown1, err = dec.readUInt16(); err != nil {
return err
}
if animation.Unknown2, err = dec.readUInt16(); err != nil {
return err
}
//if animation.Unknown1, err = dec.readFloat32(); err != nil {
// return err
//}
if animation.Unknown3, err = dec.readString(); err != nil {
return err
}
if animation.MoveVector, err = dec.readVector(); err != nil {
return err
}
if animation.RotationVector, err = dec.readVector(); err != nil {
return err
}
model.Animations = append(model.Animations, animation)
}
return nil
}
func (dec *Decoder) readShadows(_ *Model) error {
shadowCount, err := dec.readUInt16()
if err != nil {
return err
}
count := int(shadowCount)
for i := 0; i < count; i++ {
// Skip // TODO: возможно это картинка 32х32
_ = dec.seek(32 * 32)
}
return nil
}
func (dec *Decoder) readCubeMaps(_ *Model) error {
cubeMapCount, err := dec.readUInt16()
if err != nil {
return err
}
count := int(cubeMapCount)
for i := 0; i < count; i++ {
var width, height uint16
if width, err = dec.readUInt16(); err != nil {
return err
}
if height, err = dec.readUInt16(); err != nil {
return err
}
_, _ = dec.readUInt16()
_, _ = dec.readUInt16()
// Skip pixel data
_ = dec.seek(int64(width * height))
}
return nil
}
func (dec *Decoder) readData(model *Model) error {
var (
triangleCount uint16
trianglesCounts []uint16
textureCoordCount uint16
textureCoordCounts []uint16
pointCount uint16
pointCounts []uint16
brightnessCount uint16
brightnessCounts []uint16
unknownCount uint32
cnt uint16
err error
)
if triangleCount, err = dec.readUInt16(); err != nil {
return err
}
if textureCoordCount, err = dec.readUInt16(); err != nil {
return err
}
if pointCount, err = dec.readUInt16(); err != nil {
return err
}
if brightnessCount, err = dec.readUInt16(); err != nil {
return err
}
if unknownCount, err = dec.readUInt32(); err != nil {
return err
}
log.Println("unknownCount:", unknownCount)
for i := 0; i < int(triangleCount); i++ {
if cnt, err = dec.readUInt16(); err != nil {
return err
}
trianglesCounts = append(trianglesCounts, cnt)
}
for i := 0; i < int(textureCoordCount); i++ {
if cnt, err = dec.readUInt16(); err != nil {
return err
}
textureCoordCounts = append(textureCoordCounts, cnt)
}
for i := 0; i < int(pointCount); i++ {
if cnt, err = dec.readUInt16(); err != nil {
return err
}
pointCounts = append(pointCounts, cnt)
}
for i := 0; i < int(brightnessCount); i++ {
if cnt, err = dec.readUInt16(); err != nil {
return err
}
brightnessCounts = append(brightnessCounts, cnt)
}
for i := 0; i < int(unknownCount); i++ {
//x, err := dec.readFloat32()
//if err != nil {
// return err
//}
//y, err := dec.readFloat32()
//if err != nil {
// return err
//}
//vec, err := dec.readVector()
//if err != nil {
// return err
//}
//log.Println(Coordinate{x, y}, vec)
//if cnt, err = dec.readUInt16(); err != nil {
// return err
//}
//log.Println("cnt", cnt)
//buff := make([]byte, 20)
//err = dec.read(&buff)
//if err != nil {
// return err
//}
//log.Println(buff)
//vec, err := dec.readVector()
//if err != nil {
// return err
//}
//log.Println(vec)
_ = dec.seek(20)
}
if err = dec.readTriangles(model, int(triangleCount), trianglesCounts); err != nil {
return err
}
if err = dec.readTextureCoordinates(model, int(textureCoordCount), textureCoordCounts); err != nil {
return err
}
if err = dec.readPoint(model, int(pointCount), pointCounts); err != nil {
return err
}
if err = dec.readBrightness(model, int(brightnessCount), brightnessCounts); err != nil {
return err
}
return nil
}
func (dec *Decoder) readTriangles(model *Model, count int, counts []uint16) error {
for i := 0; i < count; i++ {
cnt := int(counts[i])
var triangles []uint16
for j := 0; j < cnt; j++ {
n, err := dec.readUInt16()
if err != nil {
return err
}
triangles = append(triangles, n)
}
model.Triangles = append(model.Triangles, triangles)
}
return nil
}
func (dec *Decoder) readTextureCoordinates(model *Model, count int, counts []uint16) error {
for i := 0; i < count; i++ {
cnt := int(counts[i])
var cords []Coordinate
for j := 0; j < cnt; j++ {
cord := Coordinate{}
u, err := dec.readFloat32()
if err != nil {
return err
}
v, err := dec.readFloat32()
if err != nil {
return err
}
cord.Set(u, v)
cords = append(cords, cord)
}
model.TextureCoordinates = append(model.TextureCoordinates, cords)
}
return nil
}
func (dec *Decoder) readPoint(model *Model, count int, counts []uint16) error {
for i := 0; i < count; i++ {
cnt := int(counts[i])
var vectors []Vector
for j := 0; j < cnt; j++ {
vec := Vector{}
ux, err := dec.readUInt16()
if err != nil {
return err
}
uy, err := dec.readUInt16()
if err != nil {
return err
}
uz, err := dec.readUInt16()
if err != nil {
return err
}
vec.Set(float32(ux)/float32(0xffff), float32(uy)/float32(0xffff), float32(uz)/float32(0xffff))
vectors = append(vectors, vec)
}
model.Points = append(model.Points, vectors)
}
return nil
}
func (dec *Decoder) readBrightness(model *Model, count int, counts []uint16) error {
for i := 0; i < count; i++ {
cnt := int(counts[i])
var brightness []byte
for j := 0; j < cnt; j++ {
b, err := dec.readUInt8()
if err != nil {
return err
}
brightness = append(brightness, b)
}
model.Brightness = append(model.Brightness, brightness)
}
return nil
}