// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. import ( "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" "bytes" ) /** * Quake 1 model format is used to store 3D models completely with * textures and animations used in the game. Quake 1 engine * (retroactively named "idtech2") is a popular 3D engine first used * for Quake game by id Software in 1996. * * Model is constructed traditionally from vertices in 3D space, faces * which connect vertices, textures ("skins", i.e. 2D bitmaps) and * texture UV mapping information. As opposed to more modern, * bones-based animation formats, Quake model was animated by changing * locations of all vertices it included in 3D space, frame by frame. * * File format stores: * * * "Skins" — effectively 2D bitmaps which will be used as a * texture. Every model can have multiple skins — e.g. these can be * switched to depict various levels of damage to the * monsters. Bitmaps are 8-bit-per-pixel, indexed in global Quake * palette, subject to lighting and gamma adjustment when rendering * in the game using colormap technique. * * "Texture coordinates" — UV coordinates, mapping 3D vertices to * skin coordinates. * * "Triangles" — triangular faces connecting 3D vertices. * * "Frames" — locations of vertices in 3D space; can include more * than one frame, thus allowing representation of different frames * for animation purposes. * * Originally, 3D geometry for models for Quake was designed in [Alias * PowerAnimator](https://en.wikipedia.org/wiki/PowerAnimator), * precursor of modern day Autodesk Maya and Autodesk Alias. Therefore, * 3D-related part of Quake model format followed closely Alias TRI * format, and Quake development utilities included a converter from Alias * TRI (`modelgen`). * * Skins (textures) where prepared as LBM bitmaps with the help from * `texmap` utility in the same development utilities toolkit. */ type QuakeMdl struct { Header *QuakeMdl_MdlHeader Skins []*QuakeMdl_MdlSkin TextureCoordinates []*QuakeMdl_MdlTexcoord Triangles []*QuakeMdl_MdlTriangle Frames []*QuakeMdl_MdlFrame _io *kaitai.Stream _root *QuakeMdl _parent interface{} } func NewQuakeMdl() *QuakeMdl { return &QuakeMdl{ } } func (this *QuakeMdl) Read(io *kaitai.Stream, parent interface{}, root *QuakeMdl) (err error) { this._io = io this._parent = parent this._root = root tmp1 := NewQuakeMdl_MdlHeader() err = tmp1.Read(this._io, this, this._root) if err != nil { return err } this.Header = tmp1 for i := 0; i < int(this.Header.NumSkins); i++ { _ = i tmp2 := NewQuakeMdl_MdlSkin() err = tmp2.Read(this._io, this, this._root) if err != nil { return err } this.Skins = append(this.Skins, tmp2) } for i := 0; i < int(this.Header.NumVerts); i++ { _ = i tmp3 := NewQuakeMdl_MdlTexcoord() err = tmp3.Read(this._io, this, this._root) if err != nil { return err } this.TextureCoordinates = append(this.TextureCoordinates, tmp3) } for i := 0; i < int(this.Header.NumTris); i++ { _ = i tmp4 := NewQuakeMdl_MdlTriangle() err = tmp4.Read(this._io, this, this._root) if err != nil { return err } this.Triangles = append(this.Triangles, tmp4) } for i := 0; i < int(this.Header.NumFrames); i++ { _ = i tmp5 := NewQuakeMdl_MdlFrame() err = tmp5.Read(this._io, this, this._root) if err != nil { return err } this.Frames = append(this.Frames, tmp5) } return err } type QuakeMdl_MdlVertex struct { Values []uint8 NormalIndex uint8 _io *kaitai.Stream _root *QuakeMdl _parent interface{} } func NewQuakeMdl_MdlVertex() *QuakeMdl_MdlVertex { return &QuakeMdl_MdlVertex{ } } func (this *QuakeMdl_MdlVertex) Read(io *kaitai.Stream, parent interface{}, root *QuakeMdl) (err error) { this._io = io this._parent = parent this._root = root for i := 0; i < int(3); i++ { _ = i tmp6, err := this._io.ReadU1() if err != nil { return err } this.Values = append(this.Values, tmp6) } tmp7, err := this._io.ReadU1() if err != nil { return err } this.NormalIndex = tmp7 return err } /** * @see Source * @see Source */ type QuakeMdl_MdlTexcoord struct { OnSeam int32 S int32 T int32 _io *kaitai.Stream _root *QuakeMdl _parent *QuakeMdl } func NewQuakeMdl_MdlTexcoord() *QuakeMdl_MdlTexcoord { return &QuakeMdl_MdlTexcoord{ } } func (this *QuakeMdl_MdlTexcoord) Read(io *kaitai.Stream, parent *QuakeMdl, root *QuakeMdl) (err error) { this._io = io this._parent = parent this._root = root tmp8, err := this._io.ReadS4le() if err != nil { return err } this.OnSeam = int32(tmp8) tmp9, err := this._io.ReadS4le() if err != nil { return err } this.S = int32(tmp9) tmp10, err := this._io.ReadS4le() if err != nil { return err } this.T = int32(tmp10) return err } /** * @see Source * @see Source */ type QuakeMdl_MdlHeader struct { Ident []byte Version int32 Scale *QuakeMdl_Vec3 Origin *QuakeMdl_Vec3 Radius float32 EyePosition *QuakeMdl_Vec3 NumSkins int32 SkinWidth int32 SkinHeight int32 NumVerts int32 NumTris int32 NumFrames int32 Synctype int32 Flags int32 Size float32 _io *kaitai.Stream _root *QuakeMdl _parent *QuakeMdl _f_skinSize bool skinSize int } func NewQuakeMdl_MdlHeader() *QuakeMdl_MdlHeader { return &QuakeMdl_MdlHeader{ } } func (this *QuakeMdl_MdlHeader) Read(io *kaitai.Stream, parent *QuakeMdl, root *QuakeMdl) (err error) { this._io = io this._parent = parent this._root = root tmp11, err := this._io.ReadBytes(int(4)) if err != nil { return err } tmp11 = tmp11 this.Ident = tmp11 if !(bytes.Equal(this.Ident, []uint8{73, 68, 80, 79})) { return kaitai.NewValidationNotEqualError([]uint8{73, 68, 80, 79}, this.Ident, this._io, "/types/mdl_header/seq/0") } tmp12, err := this._io.ReadS4le() if err != nil { return err } this.Version = int32(tmp12) if !(this.Version == 6) { return kaitai.NewValidationNotEqualError(6, this.Version, this._io, "/types/mdl_header/seq/1") } tmp13 := NewQuakeMdl_Vec3() err = tmp13.Read(this._io, this, this._root) if err != nil { return err } this.Scale = tmp13 tmp14 := NewQuakeMdl_Vec3() err = tmp14.Read(this._io, this, this._root) if err != nil { return err } this.Origin = tmp14 tmp15, err := this._io.ReadF4le() if err != nil { return err } this.Radius = float32(tmp15) tmp16 := NewQuakeMdl_Vec3() err = tmp16.Read(this._io, this, this._root) if err != nil { return err } this.EyePosition = tmp16 tmp17, err := this._io.ReadS4le() if err != nil { return err } this.NumSkins = int32(tmp17) tmp18, err := this._io.ReadS4le() if err != nil { return err } this.SkinWidth = int32(tmp18) tmp19, err := this._io.ReadS4le() if err != nil { return err } this.SkinHeight = int32(tmp19) tmp20, err := this._io.ReadS4le() if err != nil { return err } this.NumVerts = int32(tmp20) tmp21, err := this._io.ReadS4le() if err != nil { return err } this.NumTris = int32(tmp21) tmp22, err := this._io.ReadS4le() if err != nil { return err } this.NumFrames = int32(tmp22) tmp23, err := this._io.ReadS4le() if err != nil { return err } this.Synctype = int32(tmp23) tmp24, err := this._io.ReadS4le() if err != nil { return err } this.Flags = int32(tmp24) tmp25, err := this._io.ReadF4le() if err != nil { return err } this.Size = float32(tmp25) return err } /** * Skin size in pixels. */ func (this *QuakeMdl_MdlHeader) SkinSize() (v int, err error) { if (this._f_skinSize) { return this.skinSize, nil } this.skinSize = int((this.SkinWidth * this.SkinHeight)) this._f_skinSize = true return this.skinSize, nil } /** * Magic signature bytes that every Quake model must * have. "IDPO" is short for "IDPOLYHEADER". * @see Source */ /** * Global scaling factors in 3 dimensions for whole model. When * represented in 3D world, this model local coordinates will * be multiplied by these factors. */ /** * Number of skins (=texture bitmaps) included in this model. */ /** * Width (U coordinate max) of every skin (=texture) in pixels. */ /** * Height (V coordinate max) of every skin (=texture) in * pixels. */ /** * Number of vertices in this model. Note that this is constant * for all the animation frames and all textures. */ /** * Number of triangles (=triangular faces) in this model. */ /** * Number of animation frames included in this model. */ type QuakeMdl_MdlSkin struct { Group int32 SingleTextureData []byte NumFrames uint32 FrameTimes []float32 GroupTextureData [][]byte _io *kaitai.Stream _root *QuakeMdl _parent *QuakeMdl } func NewQuakeMdl_MdlSkin() *QuakeMdl_MdlSkin { return &QuakeMdl_MdlSkin{ } } func (this *QuakeMdl_MdlSkin) Read(io *kaitai.Stream, parent *QuakeMdl, root *QuakeMdl) (err error) { this._io = io this._parent = parent this._root = root tmp26, err := this._io.ReadS4le() if err != nil { return err } this.Group = int32(tmp26) if (this.Group == 0) { tmp27, err := this._root.Header.SkinSize() if err != nil { return err } tmp28, err := this._io.ReadBytes(int(tmp27)) if err != nil { return err } tmp28 = tmp28 this.SingleTextureData = tmp28 } if (this.Group != 0) { tmp29, err := this._io.ReadU4le() if err != nil { return err } this.NumFrames = uint32(tmp29) } if (this.Group != 0) { for i := 0; i < int(this.NumFrames); i++ { _ = i tmp30, err := this._io.ReadF4le() if err != nil { return err } this.FrameTimes = append(this.FrameTimes, tmp30) } } if (this.Group != 0) { for i := 0; i < int(this.NumFrames); i++ { _ = i tmp31, err := this._root.Header.SkinSize() if err != nil { return err } tmp32, err := this._io.ReadBytes(int(tmp31)) if err != nil { return err } tmp32 = tmp32 this.GroupTextureData = append(this.GroupTextureData, tmp32) } } return err } type QuakeMdl_MdlFrame struct { Type int32 Min *QuakeMdl_MdlVertex Max *QuakeMdl_MdlVertex Time []float32 Frames []*QuakeMdl_MdlSimpleFrame _io *kaitai.Stream _root *QuakeMdl _parent *QuakeMdl _f_numSimpleFrames bool numSimpleFrames int32 } func NewQuakeMdl_MdlFrame() *QuakeMdl_MdlFrame { return &QuakeMdl_MdlFrame{ } } func (this *QuakeMdl_MdlFrame) Read(io *kaitai.Stream, parent *QuakeMdl, root *QuakeMdl) (err error) { this._io = io this._parent = parent this._root = root tmp33, err := this._io.ReadS4le() if err != nil { return err } this.Type = int32(tmp33) if (this.Type != 0) { tmp34 := NewQuakeMdl_MdlVertex() err = tmp34.Read(this._io, this, this._root) if err != nil { return err } this.Min = tmp34 } if (this.Type != 0) { tmp35 := NewQuakeMdl_MdlVertex() err = tmp35.Read(this._io, this, this._root) if err != nil { return err } this.Max = tmp35 } if (this.Type != 0) { for i := 0; i < int(this.Type); i++ { _ = i tmp36, err := this._io.ReadF4le() if err != nil { return err } this.Time = append(this.Time, tmp36) } } tmp37, err := this.NumSimpleFrames() if err != nil { return err } for i := 0; i < int(tmp37); i++ { _ = i tmp38 := NewQuakeMdl_MdlSimpleFrame() err = tmp38.Read(this._io, this, this._root) if err != nil { return err } this.Frames = append(this.Frames, tmp38) } return err } func (this *QuakeMdl_MdlFrame) NumSimpleFrames() (v int32, err error) { if (this._f_numSimpleFrames) { return this.numSimpleFrames, nil } var tmp39 int8; if (this.Type == 0) { tmp39 = 1 } else { tmp39 = this.Type } this.numSimpleFrames = int32(tmp39) this._f_numSimpleFrames = true return this.numSimpleFrames, nil } type QuakeMdl_MdlSimpleFrame struct { BboxMin *QuakeMdl_MdlVertex BboxMax *QuakeMdl_MdlVertex Name string Vertices []*QuakeMdl_MdlVertex _io *kaitai.Stream _root *QuakeMdl _parent *QuakeMdl_MdlFrame } func NewQuakeMdl_MdlSimpleFrame() *QuakeMdl_MdlSimpleFrame { return &QuakeMdl_MdlSimpleFrame{ } } func (this *QuakeMdl_MdlSimpleFrame) Read(io *kaitai.Stream, parent *QuakeMdl_MdlFrame, root *QuakeMdl) (err error) { this._io = io this._parent = parent this._root = root tmp40 := NewQuakeMdl_MdlVertex() err = tmp40.Read(this._io, this, this._root) if err != nil { return err } this.BboxMin = tmp40 tmp41 := NewQuakeMdl_MdlVertex() err = tmp41.Read(this._io, this, this._root) if err != nil { return err } this.BboxMax = tmp41 tmp42, err := this._io.ReadBytes(int(16)) if err != nil { return err } tmp42 = kaitai.BytesTerminate(kaitai.BytesStripRight(tmp42, 0), 0, false) this.Name = string(tmp42) for i := 0; i < int(this._root.Header.NumVerts); i++ { _ = i tmp43 := NewQuakeMdl_MdlVertex() err = tmp43.Read(this._io, this, this._root) if err != nil { return err } this.Vertices = append(this.Vertices, tmp43) } return err } /** * Represents a triangular face, connecting 3 vertices, referenced * by their indexes. * @see Source * @see Source */ type QuakeMdl_MdlTriangle struct { FacesFront int32 Vertices []int32 _io *kaitai.Stream _root *QuakeMdl _parent *QuakeMdl } func NewQuakeMdl_MdlTriangle() *QuakeMdl_MdlTriangle { return &QuakeMdl_MdlTriangle{ } } func (this *QuakeMdl_MdlTriangle) Read(io *kaitai.Stream, parent *QuakeMdl, root *QuakeMdl) (err error) { this._io = io this._parent = parent this._root = root tmp44, err := this._io.ReadS4le() if err != nil { return err } this.FacesFront = int32(tmp44) for i := 0; i < int(3); i++ { _ = i tmp45, err := this._io.ReadS4le() if err != nil { return err } this.Vertices = append(this.Vertices, tmp45) } return err } /** * Basic 3D vector (x, y, z) using single-precision floating point * coordnates. Can be used to specify a point in 3D space, * direction, scaling factor, etc. */ type QuakeMdl_Vec3 struct { X float32 Y float32 Z float32 _io *kaitai.Stream _root *QuakeMdl _parent *QuakeMdl_MdlHeader } func NewQuakeMdl_Vec3() *QuakeMdl_Vec3 { return &QuakeMdl_Vec3{ } } func (this *QuakeMdl_Vec3) Read(io *kaitai.Stream, parent *QuakeMdl_MdlHeader, root *QuakeMdl) (err error) { this._io = io this._parent = parent this._root = root tmp46, err := this._io.ReadF4le() if err != nil { return err } this.X = float32(tmp46) tmp47, err := this._io.ReadF4le() if err != nil { return err } this.Y = float32(tmp47) tmp48, err := this._io.ReadF4le() if err != nil { return err } this.Z = float32(tmp48) return err }