491 lines
11 KiB
Go
491 lines
11 KiB
Go
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
|
||
}
|