Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
YGOMobile
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fallenstardust
YGOMobile
Commits
435c57e2
Commit
435c57e2
authored
Feb 19, 2025
by
fallenstardust
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化scrOPtion的显示
删除无关类
parent
16122411
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
5 additions
and
1700 deletions
+5
-1700
Classes/gframe/CAnimatedMeshHalfLife.cpp
Classes/gframe/CAnimatedMeshHalfLife.cpp
+0
-1695
Classes/gframe/client_field.cpp
Classes/gframe/client_field.cpp
+2
-2
Classes/gframe/game.cpp
Classes/gframe/game.cpp
+3
-3
No files found.
Classes/gframe/CAnimatedMeshHalfLife.cpp
deleted
100644 → 0
View file @
16122411
// Copyright (C) 2002-2012 Nikolaus Gebhardt / Fabio Concas / Thomas Alten
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_
#include "CAnimatedMeshHalfLife.h"
#include "os.h"
#include "CColorConverter.h"
#include "CImage.h"
#include "coreutil.h"
#include "SMeshBuffer.h"
#include "IVideoDriver.h"
#include "IFileSystem.h"
namespace
irr
{
namespace
scene
{
using
namespace
video
;
void
AngleQuaternion
(
const
core
::
vector3df
&
angles
,
vec4_hl
quaternion
)
{
f32
angle
;
f32
sr
,
sp
,
sy
,
cr
,
cp
,
cy
;
// FIXME: rescale the inputs to 1/2 angle
angle
=
angles
.
Z
*
0.5
f
;
sy
=
sin
(
angle
);
cy
=
cos
(
angle
);
angle
=
angles
.
Y
*
0.5
f
;
sp
=
sin
(
angle
);
cp
=
cos
(
angle
);
angle
=
angles
.
X
*
0.5
f
;
sr
=
sin
(
angle
);
cr
=
cos
(
angle
);
quaternion
[
0
]
=
sr
*
cp
*
cy
-
cr
*
sp
*
sy
;
// X
quaternion
[
1
]
=
cr
*
sp
*
cy
+
sr
*
cp
*
sy
;
// Y
quaternion
[
2
]
=
cr
*
cp
*
sy
-
sr
*
sp
*
cy
;
// Z
quaternion
[
3
]
=
cr
*
cp
*
cy
+
sr
*
sp
*
sy
;
// W
}
void
QuaternionMatrix
(
const
vec4_hl
quaternion
,
f32
(
*
matrix
)[
4
]
)
{
matrix
[
0
][
0
]
=
1.
f
-
2.
f
*
quaternion
[
1
]
*
quaternion
[
1
]
-
2.
f
*
quaternion
[
2
]
*
quaternion
[
2
];
matrix
[
1
][
0
]
=
2.
f
*
quaternion
[
0
]
*
quaternion
[
1
]
+
2.
f
*
quaternion
[
3
]
*
quaternion
[
2
];
matrix
[
2
][
0
]
=
2.
f
*
quaternion
[
0
]
*
quaternion
[
2
]
-
2.
f
*
quaternion
[
3
]
*
quaternion
[
1
];
matrix
[
0
][
1
]
=
2.
f
*
quaternion
[
0
]
*
quaternion
[
1
]
-
2.
f
*
quaternion
[
3
]
*
quaternion
[
2
];
matrix
[
1
][
1
]
=
1.
f
-
2.
f
*
quaternion
[
0
]
*
quaternion
[
0
]
-
2.
f
*
quaternion
[
2
]
*
quaternion
[
2
];
matrix
[
2
][
1
]
=
2.
f
*
quaternion
[
1
]
*
quaternion
[
2
]
+
2.
f
*
quaternion
[
3
]
*
quaternion
[
0
];
matrix
[
0
][
2
]
=
2.
f
*
quaternion
[
0
]
*
quaternion
[
2
]
+
2.
f
*
quaternion
[
3
]
*
quaternion
[
1
];
matrix
[
1
][
2
]
=
2.
f
*
quaternion
[
1
]
*
quaternion
[
2
]
-
2.
f
*
quaternion
[
3
]
*
quaternion
[
0
];
matrix
[
2
][
2
]
=
1.
f
-
2.
f
*
quaternion
[
0
]
*
quaternion
[
0
]
-
2.
f
*
quaternion
[
1
]
*
quaternion
[
1
];
}
void
QuaternionSlerp
(
const
vec4_hl
p
,
vec4_hl
q
,
f32
t
,
vec4_hl
qt
)
{
s32
i
;
f32
omega
,
cosom
,
sinom
,
sclp
,
sclq
;
// decide if one of the quaternions is backwards
f32
a
=
0
;
f32
b
=
0
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
a
+=
(
p
[
i
]
-
q
[
i
])
*
(
p
[
i
]
-
q
[
i
]);
b
+=
(
p
[
i
]
+
q
[
i
])
*
(
p
[
i
]
+
q
[
i
]);
}
if
(
a
>
b
)
{
for
(
i
=
0
;
i
<
4
;
i
++
)
{
q
[
i
]
=
-
q
[
i
];
}
}
cosom
=
p
[
0
]
*
q
[
0
]
+
p
[
1
]
*
q
[
1
]
+
p
[
2
]
*
q
[
2
]
+
p
[
3
]
*
q
[
3
];
if
((
1.
f
+
cosom
)
>
0.00000001
)
{
if
((
1.
f
-
cosom
)
>
0.00000001
)
{
omega
=
acos
(
cosom
);
sinom
=
sin
(
omega
);
sclp
=
sin
(
(
1.
f
-
t
)
*
omega
)
/
sinom
;
sclq
=
sin
(
t
*
omega
)
/
sinom
;
}
else
{
sclp
=
1.
f
-
t
;
sclq
=
t
;
}
for
(
i
=
0
;
i
<
4
;
i
++
)
{
qt
[
i
]
=
sclp
*
p
[
i
]
+
sclq
*
q
[
i
];
}
}
else
{
qt
[
0
]
=
-
p
[
1
];
qt
[
1
]
=
p
[
0
];
qt
[
2
]
=
-
p
[
3
];
qt
[
3
]
=
p
[
2
];
sclp
=
sin
(
(
1.
f
-
t
)
*
0.5
f
*
core
::
PI
);
sclq
=
sin
(
t
*
0.5
f
*
core
::
PI
);
for
(
i
=
0
;
i
<
3
;
i
++
)
{
qt
[
i
]
=
sclp
*
p
[
i
]
+
sclq
*
qt
[
i
];
}
}
}
void
R_ConcatTransforms
(
const
f32
in1
[
3
][
4
],
const
f32
in2
[
3
][
4
],
f32
out
[
3
][
4
])
{
out
[
0
][
0
]
=
in1
[
0
][
0
]
*
in2
[
0
][
0
]
+
in1
[
0
][
1
]
*
in2
[
1
][
0
]
+
in1
[
0
][
2
]
*
in2
[
2
][
0
];
out
[
0
][
1
]
=
in1
[
0
][
0
]
*
in2
[
0
][
1
]
+
in1
[
0
][
1
]
*
in2
[
1
][
1
]
+
in1
[
0
][
2
]
*
in2
[
2
][
1
];
out
[
0
][
2
]
=
in1
[
0
][
0
]
*
in2
[
0
][
2
]
+
in1
[
0
][
1
]
*
in2
[
1
][
2
]
+
in1
[
0
][
2
]
*
in2
[
2
][
2
];
out
[
0
][
3
]
=
in1
[
0
][
0
]
*
in2
[
0
][
3
]
+
in1
[
0
][
1
]
*
in2
[
1
][
3
]
+
in1
[
0
][
2
]
*
in2
[
2
][
3
]
+
in1
[
0
][
3
];
out
[
1
][
0
]
=
in1
[
1
][
0
]
*
in2
[
0
][
0
]
+
in1
[
1
][
1
]
*
in2
[
1
][
0
]
+
in1
[
1
][
2
]
*
in2
[
2
][
0
];
out
[
1
][
1
]
=
in1
[
1
][
0
]
*
in2
[
0
][
1
]
+
in1
[
1
][
1
]
*
in2
[
1
][
1
]
+
in1
[
1
][
2
]
*
in2
[
2
][
1
];
out
[
1
][
2
]
=
in1
[
1
][
0
]
*
in2
[
0
][
2
]
+
in1
[
1
][
1
]
*
in2
[
1
][
2
]
+
in1
[
1
][
2
]
*
in2
[
2
][
2
];
out
[
1
][
3
]
=
in1
[
1
][
0
]
*
in2
[
0
][
3
]
+
in1
[
1
][
1
]
*
in2
[
1
][
3
]
+
in1
[
1
][
2
]
*
in2
[
2
][
3
]
+
in1
[
1
][
3
];
out
[
2
][
0
]
=
in1
[
2
][
0
]
*
in2
[
0
][
0
]
+
in1
[
2
][
1
]
*
in2
[
1
][
0
]
+
in1
[
2
][
2
]
*
in2
[
2
][
0
];
out
[
2
][
1
]
=
in1
[
2
][
0
]
*
in2
[
0
][
1
]
+
in1
[
2
][
1
]
*
in2
[
1
][
1
]
+
in1
[
2
][
2
]
*
in2
[
2
][
1
];
out
[
2
][
2
]
=
in1
[
2
][
0
]
*
in2
[
0
][
2
]
+
in1
[
2
][
1
]
*
in2
[
1
][
2
]
+
in1
[
2
][
2
]
*
in2
[
2
][
2
];
out
[
2
][
3
]
=
in1
[
2
][
0
]
*
in2
[
0
][
3
]
+
in1
[
2
][
1
]
*
in2
[
1
][
3
]
+
in1
[
2
][
2
]
*
in2
[
2
][
3
]
+
in1
[
2
][
3
];
}
#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
inline
void
VectorTransform
(
const
vec3_hl
in1
,
const
f32
in2
[
3
][
4
],
core
::
vector3df
&
out
)
{
out
.
X
=
DotProduct
(
in1
,
in2
[
0
])
+
in2
[
0
][
3
];
out
.
Z
=
DotProduct
(
in1
,
in2
[
1
])
+
in2
[
1
][
3
];
out
.
Y
=
DotProduct
(
in1
,
in2
[
2
])
+
in2
[
2
][
3
];
}
static
f32
BoneTransform
[
MAXSTUDIOBONES
][
3
][
4
];
// bone transformation matrix
void
getBoneVector
(
core
::
vector3df
&
out
,
u32
index
)
{
out
.
X
=
BoneTransform
[
index
][
0
][
3
];
out
.
Z
=
BoneTransform
[
index
][
1
][
3
];
out
.
Y
=
BoneTransform
[
index
][
2
][
3
];
}
void
getBoneBox
(
core
::
aabbox3df
&
box
,
u32
index
,
f32
size
=
0.5
f
)
{
box
.
MinEdge
.
X
=
BoneTransform
[
index
][
0
][
3
]
-
size
;
box
.
MinEdge
.
Z
=
BoneTransform
[
index
][
1
][
3
]
-
size
;
box
.
MinEdge
.
Y
=
BoneTransform
[
index
][
2
][
3
]
-
size
;
size
*=
2.
f
;
box
.
MaxEdge
.
X
=
box
.
MinEdge
.
X
+
size
;
box
.
MaxEdge
.
Y
=
box
.
MinEdge
.
Y
+
size
;
box
.
MaxEdge
.
Z
=
box
.
MinEdge
.
Z
+
size
;
}
void
getTransformedBoneVector
(
core
::
vector3df
&
out
,
u32
index
,
const
vec3_hl
in
)
{
out
.
X
=
DotProduct
(
in
,
BoneTransform
[
index
][
0
])
+
BoneTransform
[
index
][
0
][
3
];
out
.
Z
=
DotProduct
(
in
,
BoneTransform
[
index
][
1
])
+
BoneTransform
[
index
][
1
][
3
];
out
.
Y
=
DotProduct
(
in
,
BoneTransform
[
index
][
2
])
+
BoneTransform
[
index
][
2
][
3
];
}
//! Constructor
CHalflifeMDLMeshFileLoader
::
CHalflifeMDLMeshFileLoader
(
scene
::
ISceneManager
*
smgr
)
:
SceneManager
(
smgr
)
{
#ifdef _DEBUG
setDebugName
(
"CHalflifeMDLMeshFileLoader"
);
#endif
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
bool
CHalflifeMDLMeshFileLoader
::
isALoadableFileExtension
(
const
io
::
path
&
filename
)
const
{
return
core
::
hasFileExtension
(
filename
,
"mdl"
);
}
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh
*
CHalflifeMDLMeshFileLoader
::
createMesh
(
io
::
IReadFile
*
file
)
{
CAnimatedMeshHalfLife
*
msh
=
new
CAnimatedMeshHalfLife
();
if
(
msh
)
{
if
(
msh
->
loadModelFile
(
file
,
SceneManager
))
return
msh
;
msh
->
drop
();
}
return
0
;
}
//! Constructor
CAnimatedMeshHalfLife
::
CAnimatedMeshHalfLife
()
:
FrameCount
(
0
),
MeshIPol
(
0
),
SceneManager
(
0
),
Header
(
0
),
TextureHeader
(
0
),
OwnTexModel
(
false
),
SequenceIndex
(
0
),
CurrentFrame
(
0
),
FramesPerSecond
(
25.
f
),
SkinGroupSelection
(
0
)
#ifdef HL_TEXTURE_ATLAS
,
TextureMaster
(
0
)
#endif
{
#ifdef _DEBUG
setDebugName
(
"CAnimatedMeshHalfLife"
);
#endif
initData
();
}
/*!
loads a complete model
*/
bool
CAnimatedMeshHalfLife
::
loadModelFile
(
io
::
IReadFile
*
file
,
ISceneManager
*
smgr
)
{
if
(
!
file
)
return
false
;
SceneManager
=
smgr
;
if
(
loadModel
(
file
,
file
->
getFileName
())
)
{
if
(
postLoadModel
(
file
->
getFileName
()
)
)
{
initModel
();
//dumpModelInfo ( 1 );
return
true
;
}
}
return
false
;
}
//! Destructor
CAnimatedMeshHalfLife
::~
CAnimatedMeshHalfLife
()
{
delete
[]
(
u8
*
)
Header
;
if
(
OwnTexModel
)
delete
[]
(
u8
*
)
TextureHeader
;
for
(
u32
i
=
0
;
i
<
32
;
++
i
)
delete
[]
(
u8
*
)
AnimationHeader
[
i
];
if
(
MeshIPol
)
MeshIPol
->
drop
();
}
//! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
u32
CAnimatedMeshHalfLife
::
getFrameCount
()
const
{
return
FrameCount
;
}
//! set the hardware mapping hint, for driver
void
CAnimatedMeshHalfLife
::
setHardwareMappingHint
(
E_HARDWARE_MAPPING
newMappingHint
,
E_BUFFER_TYPE
buffer
)
{
}
//! flags the meshbuffer as changed, reloads hardware buffers
void
CAnimatedMeshHalfLife
::
setDirty
(
E_BUFFER_TYPE
buffer
)
{
}
static
core
::
vector3df
TransformedVerts
[
MAXSTUDIOVERTS
];
// transformed vertices
//static core::vector3df TransformedNormals[MAXSTUDIOVERTS]; // light surface normals
/*!
*/
void
CAnimatedMeshHalfLife
::
initModel
()
{
// init Sequences to Animation
KeyFrameInterpolation
ipol
;
ipol
.
Name
.
reserve
(
64
);
u32
i
;
AnimList
.
clear
();
FrameCount
=
0
;
SHalflifeSequence
*
seq
=
(
SHalflifeSequence
*
)
((
u8
*
)
Header
+
Header
->
seqindex
);
for
(
i
=
0
;
i
<
Header
->
numseq
;
i
++
)
{
ipol
.
Name
=
seq
[
i
].
label
;
ipol
.
StartFrame
=
FrameCount
;
ipol
.
Frames
=
core
::
max_
(
1
,
seq
[
i
].
numframes
-
1
);
ipol
.
EndFrame
=
ipol
.
StartFrame
+
ipol
.
Frames
-
1
;
ipol
.
FramesPerSecond
=
seq
[
i
].
fps
;
ipol
.
AnimationType
=
seq
[
i
].
flags
&
STUDIO_LOOPING
?
EAMT_LOOPING
:
EAMT_WAYPOINT
;
AnimList
.
push_back
(
ipol
);
FrameCount
+=
ipol
.
Frames
;
}
// initBoneControllers
/*
SHalflifeBoneController *bonecontroller = (SHalflifeBoneController *)((u8*) Header + Header->bonecontrollerindex);
for ( i = 0; i < Header->numbonecontrollers; i++)
{
printf ( "BoneController%d index:%d%s range:%f - %f\n",
i,
bonecontroller[i].index, bonecontroller[i].index == MOUTH_CONTROLLER ? " (Mouth)": "",
bonecontroller[i].start,bonecontroller[i].end
);
}
// initSkins
for (i = 0; i < TextureHeader->numskinfamilies; i++)
{
printf ( "Skin%d\n", i + 1);
}
*/
// initBodyparts
u32
meshBuffer
=
0
;
BodyList
.
clear
();
SHalflifeBody
*
body
=
(
SHalflifeBody
*
)
((
u8
*
)
Header
+
Header
->
bodypartindex
);
for
(
i
=
0
;
i
<
Header
->
numbodyparts
;
++
i
)
{
BodyPart
part
;
part
.
name
=
body
[
i
].
name
;
part
.
defaultModel
=
core
::
max_
(
0
,
(
s32
)
body
[
i
].
base
-
1
);
SHalflifeModel
*
model
=
(
SHalflifeModel
*
)((
u8
*
)
Header
+
body
[
i
].
modelindex
);
for
(
u32
g
=
0
;
g
<
body
[
i
].
nummodels
;
++
g
)
{
SubModel
sub
;
sub
.
name
=
model
[
g
].
name
;
sub
.
startBuffer
=
meshBuffer
;
sub
.
endBuffer
=
sub
.
startBuffer
+
model
[
g
].
nummesh
;
sub
.
state
=
g
==
part
.
defaultModel
;
part
.
model
.
push_back
(
sub
);
meshBuffer
+=
model
[
g
].
nummesh
;
}
BodyList
.
push_back
(
part
);
}
SequenceIndex
=
0
;
CurrentFrame
=
0.
f
;
SetController
(
0
,
0.
f
);
SetController
(
1
,
0.
f
);
SetController
(
2
,
0.
f
);
SetController
(
3
,
0.
f
);
SetController
(
MOUTH_CONTROLLER
,
0.
f
);
SetSkin
(
0
);
// init Meshbuffers
const
SHalflifeTexture
*
tex
=
(
SHalflifeTexture
*
)
((
u8
*
)
TextureHeader
+
TextureHeader
->
textureindex
);
const
u16
*
skinref
=
(
u16
*
)((
u8
*
)
TextureHeader
+
TextureHeader
->
skinindex
);
if
((
SkinGroupSelection
!=
0
)
&&
(
SkinGroupSelection
<
TextureHeader
->
numskinfamilies
))
skinref
+=
(
SkinGroupSelection
*
TextureHeader
->
numskinref
);
core
::
vector2df
tex_scale
;
core
::
vector2di
tex_trans
(
0
,
0
);
#ifdef HL_TEXTURE_ATLAS
TextureAtlas
.
getScale
(
tex_scale
);
#endif
for
(
u32
bodypart
=
0
;
bodypart
<
Header
->
numbodyparts
;
++
bodypart
)
{
const
SHalflifeBody
*
body
=
(
SHalflifeBody
*
)((
u8
*
)
Header
+
Header
->
bodypartindex
)
+
bodypart
;
for
(
u32
modelnr
=
0
;
modelnr
<
body
->
nummodels
;
++
modelnr
)
{
const
SHalflifeModel
*
model
=
(
SHalflifeModel
*
)((
u8
*
)
Header
+
body
->
modelindex
)
+
modelnr
;
#if 0
const vec3_hl *studioverts = (vec3_hl *)((u8*)Header + model->vertindex);
const vec3_hl *studionorms = (vec3_hl *)((u8*)Header + model->normindex);
#endif
for
(
i
=
0
;
i
<
model
->
nummesh
;
++
i
)
{
const
SHalflifeMesh
*
mesh
=
(
SHalflifeMesh
*
)((
u8
*
)
Header
+
model
->
meshindex
)
+
i
;
const
SHalflifeTexture
*
currentex
=
&
tex
[
skinref
[
mesh
->
skinref
]];
#ifdef HL_TEXTURE_ATLAS
TextureAtlas
.
getTranslation
(
currentex
->
name
,
tex_trans
);
#else
tex_scale
.
X
=
1.
f
/
(
f32
)
currentex
->
width
;
tex_scale
.
Y
=
1.
f
/
(
f32
)
currentex
->
height
;
#endif
SMeshBuffer
*
buffer
=
new
SMeshBuffer
();
// count index vertex size indexcount = mesh->numtris * 3
u32
indexCount
=
0
;
u32
vertexCount
=
0
;
const
s16
*
tricmd
=
(
s16
*
)((
u8
*
)
Header
+
mesh
->
triindex
);
s32
c
;
while
(
(
c
=
*
(
tricmd
++
))
)
{
if
(
c
<
0
)
c
=
-
c
;
indexCount
+=
(
c
-
2
)
*
3
;
vertexCount
+=
c
;
tricmd
+=
(
4
*
c
);
}
// indices
buffer
->
Indices
.
set_used
(
indexCount
);
buffer
->
Vertices
.
set_used
(
vertexCount
);
// fill in static indices and vertex
u16
*
index
=
buffer
->
Indices
.
pointer
();
video
::
S3DVertex
*
v
=
buffer
->
Vertices
.
pointer
();
// blow up gl_triangle_fan/gl_triangle_strip to indexed triangle list
E_PRIMITIVE_TYPE
type
;
vertexCount
=
0
;
indexCount
=
0
;
tricmd
=
(
s16
*
)((
u8
*
)
Header
+
mesh
->
triindex
);
while
(
(
c
=
*
(
tricmd
++
))
)
{
if
(
c
<
0
)
{
// triangle fan
c
=
-
c
;
type
=
EPT_TRIANGLE_FAN
;
}
else
{
type
=
EPT_TRIANGLE_STRIP
;
}
for
(
s32
g
=
0
;
g
<
c
;
++
g
,
v
+=
1
,
tricmd
+=
4
)
{
// fill vertex
#if 0
const f32 *av = studioverts[tricmd[0]];
v->Pos.X = av[0];
v->Pos.Z = av[1];
v->Pos.Y = av[2];
av = studionorms[tricmd[1]];
v->Normal.X = av[0];
v->Normal.Z = av[1];
v->Normal.Y = av[2];
#endif
v
->
Normal
.
X
=
0.
f
;
v
->
Normal
.
Z
=
0.
f
;
v
->
Normal
.
Y
=
1.
f
;
v
->
TCoords
.
X
=
(
tex_trans
.
X
+
tricmd
[
2
])
*
tex_scale
.
X
;
v
->
TCoords
.
Y
=
(
tex_trans
.
Y
+
tricmd
[
3
])
*
tex_scale
.
Y
;
v
->
Color
.
color
=
0xFFFFFFFF
;
// fill index
if
(
g
<
c
-
2
)
{
if
(
type
==
EPT_TRIANGLE_FAN
)
{
index
[
indexCount
+
0
]
=
vertexCount
;
index
[
indexCount
+
1
]
=
vertexCount
+
g
+
1
;
index
[
indexCount
+
2
]
=
vertexCount
+
g
+
2
;
}
else
{
if
(
g
&
1
)
{
index
[
indexCount
+
0
]
=
vertexCount
+
g
+
1
;
index
[
indexCount
+
1
]
=
vertexCount
+
g
+
0
;
index
[
indexCount
+
2
]
=
vertexCount
+
g
+
2
;
}
else
{
index
[
indexCount
+
0
]
=
vertexCount
+
g
+
0
;
index
[
indexCount
+
1
]
=
vertexCount
+
g
+
1
;
index
[
indexCount
+
2
]
=
vertexCount
+
g
+
2
;
}
}
indexCount
+=
3
;
}
}
vertexCount
+=
c
;
}
// material
video
::
SMaterial
&
m
=
buffer
->
getMaterial
();
m
.
MaterialType
=
video
::
EMT_SOLID
;
m
.
BackfaceCulling
=
true
;
if
(
currentex
->
flags
&
STUDIO_NF_CHROME
)
{
// don't know what to do with chrome here
}
#ifdef HL_TEXTURE_ATLAS
io
::
path
store
=
TextureBaseName
+
"atlas"
;
#else
io
::
path
fname
;
io
::
path
ext
;
core
::
splitFilename
(
currentex
->
name
,
0
,
&
fname
,
&
ext
);
io
::
path
store
=
TextureBaseName
+
fname
;
#endif
m
.
TextureLayer
[
0
].
Texture
=
SceneManager
->
getVideoDriver
()
->
getTexture
(
store
);
m
.
Lighting
=
false
;
MeshIPol
->
addMeshBuffer
(
buffer
);
buffer
->
recalculateBoundingBox
();
buffer
->
drop
();
}
// mesh
MeshIPol
->
recalculateBoundingBox
();
}
// model
}
// body part
}
/*!
*/
void
CAnimatedMeshHalfLife
::
buildVertices
()
{
/*
const u16 *skinref = (u16 *)((u8*)TextureHeader + TextureHeader->skinindex);
if (SkinGroupSelection != 0 && SkinGroupSelection < TextureHeader->numskinfamilies)
skinref += (SkinGroupSelection * TextureHeader->numskinref);
*/
u32
i
;
s32
c
,
g
;
const
s16
*
tricmd
;
u32
meshBufferNr
=
0
;
for
(
u32
bodypart
=
0
;
bodypart
<
Header
->
numbodyparts
;
++
bodypart
)
{
const
SHalflifeBody
*
body
=
(
SHalflifeBody
*
)((
u8
*
)
Header
+
Header
->
bodypartindex
)
+
bodypart
;
for
(
u32
modelnr
=
0
;
modelnr
<
body
->
nummodels
;
++
modelnr
)
{
const
SHalflifeModel
*
model
=
(
SHalflifeModel
*
)((
u8
*
)
Header
+
body
->
modelindex
)
+
modelnr
;
const
u8
*
vertbone
=
((
u8
*
)
Header
+
model
->
vertinfoindex
);
const
vec3_hl
*
studioverts
=
(
vec3_hl
*
)((
u8
*
)
Header
+
model
->
vertindex
);
for
(
i
=
0
;
i
<
model
->
numverts
;
i
++
)
{
VectorTransform
(
studioverts
[
i
],
BoneTransform
[
vertbone
[
i
]],
TransformedVerts
[
i
]
);
}
/*
const u8 *normbone = ((u8*)Header + model->norminfoindex);
const vec3_hl *studionorms = (vec3_hl *)((u8*)Header + model->normindex);
for ( i = 0; i < model->numnorms; i++)
{
VectorTransform ( studionorms[i], BoneTransform[normbone[i]], TransformedNormals[i] );
}
*/
for
(
i
=
0
;
i
<
model
->
nummesh
;
i
++
)
{
const
SHalflifeMesh
*
mesh
=
(
SHalflifeMesh
*
)((
u8
*
)
Header
+
model
->
meshindex
)
+
i
;
IMeshBuffer
*
buffer
=
MeshIPol
->
getMeshBuffer
(
meshBufferNr
++
);
video
::
S3DVertex
*
v
=
(
video
::
S3DVertex
*
)
buffer
->
getVertices
();
tricmd
=
(
s16
*
)((
u8
*
)
Header
+
mesh
->
triindex
);
while
(
(
c
=
*
(
tricmd
++
))
)
{
if
(
c
<
0
)
c
=
-
c
;
for
(
g
=
0
;
g
<
c
;
++
g
,
v
+=
1
,
tricmd
+=
4
)
{
// fill vertex
const
core
::
vector3df
&
av
=
TransformedVerts
[
tricmd
[
0
]];
v
->
Pos
=
av
;
/*
const core::vector3df& an = TransformedNormals[tricmd[1]];
v->Normal = an;
//v->Normal.normalize();
*/
}
}
// tricmd
}
// nummesh
}
// model
}
// bodypart
}
/*!
render Bones
*/
void
CAnimatedMeshHalfLife
::
renderModel
(
u32
param
,
IVideoDriver
*
driver
,
const
core
::
matrix4
&
absoluteTransformation
)
{
SHalflifeBone
*
bone
=
(
SHalflifeBone
*
)
((
u8
*
)
Header
+
Header
->
boneindex
);
video
::
SColor
blue
(
0xFF000080
);
video
::
SColor
red
(
0xFF800000
);
video
::
SColor
yellow
(
0xFF808000
);
video
::
SColor
cyan
(
0xFF008080
);
core
::
aabbox3df
box
;
u32
i
;
for
(
i
=
0
;
i
<
Header
->
numbones
;
i
++
)
{
if
(
bone
[
i
].
parent
>=
0
)
{
getBoneVector
(
box
.
MinEdge
,
bone
[
i
].
parent
);
getBoneVector
(
box
.
MaxEdge
,
i
);
driver
->
draw3DLine
(
box
.
MinEdge
,
box
.
MaxEdge
,
blue
);
// draw parent bone node
if
(
bone
[
bone
[
i
].
parent
].
parent
>=
0
)
{
getBoneBox
(
box
,
bone
[
i
].
parent
);
driver
->
draw3DBox
(
box
,
blue
);
}
getBoneBox
(
box
,
i
);
driver
->
draw3DBox
(
box
,
blue
);
}
else
{
// draw parent bone node
getBoneBox
(
box
,
i
,
1.
f
);
driver
->
draw3DBox
(
box
,
red
);
}
}
// attachements
SHalflifeAttachment
*
attach
=
(
SHalflifeAttachment
*
)
((
u8
*
)
Header
+
Header
->
attachmentindex
);
core
::
vector3df
v
[
8
];
for
(
i
=
0
;
i
<
Header
->
numattachments
;
i
++
)
{
getTransformedBoneVector
(
v
[
0
],
attach
[
i
].
bone
,
attach
[
i
].
org
);
getTransformedBoneVector
(
v
[
1
],
attach
[
i
].
bone
,
attach
[
i
].
vectors
[
0
]
);
getTransformedBoneVector
(
v
[
2
],
attach
[
i
].
bone
,
attach
[
i
].
vectors
[
1
]
);
getTransformedBoneVector
(
v
[
3
],
attach
[
i
].
bone
,
attach
[
i
].
vectors
[
2
]
);
driver
->
draw3DLine
(
v
[
0
],
v
[
1
],
cyan
);
driver
->
draw3DLine
(
v
[
0
],
v
[
2
],
cyan
);
driver
->
draw3DLine
(
v
[
0
],
v
[
3
],
cyan
);
}
// hit boxes
SHalflifeBBox
*
hitbox
=
(
SHalflifeBBox
*
)
((
u8
*
)
Header
+
Header
->
hitboxindex
);
f32
*
bbmin
,
*
bbmax
;
vec3_hl
v2
[
8
];
for
(
i
=
0
;
i
<
Header
->
numhitboxes
;
i
++
)
{
bbmin
=
hitbox
[
i
].
bbmin
;
bbmax
=
hitbox
[
i
].
bbmax
;
v2
[
0
][
0
]
=
bbmin
[
0
];
v2
[
0
][
1
]
=
bbmax
[
1
];
v2
[
0
][
2
]
=
bbmin
[
2
];
v2
[
1
][
0
]
=
bbmin
[
0
];
v2
[
1
][
1
]
=
bbmin
[
1
];
v2
[
1
][
2
]
=
bbmin
[
2
];
v2
[
2
][
0
]
=
bbmax
[
0
];
v2
[
2
][
1
]
=
bbmax
[
1
];
v2
[
2
][
2
]
=
bbmin
[
2
];
v2
[
3
][
0
]
=
bbmax
[
0
];
v2
[
3
][
1
]
=
bbmin
[
1
];
v2
[
3
][
2
]
=
bbmin
[
2
];
v2
[
4
][
0
]
=
bbmax
[
0
];
v2
[
4
][
1
]
=
bbmax
[
1
];
v2
[
4
][
2
]
=
bbmax
[
2
];
v2
[
5
][
0
]
=
bbmax
[
0
];
v2
[
5
][
1
]
=
bbmin
[
1
];
v2
[
5
][
2
]
=
bbmax
[
2
];
v2
[
6
][
0
]
=
bbmin
[
0
];
v2
[
6
][
1
]
=
bbmax
[
1
];
v2
[
6
][
2
]
=
bbmax
[
2
];
v2
[
7
][
0
]
=
bbmin
[
0
];
v2
[
7
][
1
]
=
bbmin
[
1
];
v2
[
7
][
2
]
=
bbmax
[
2
];
for
(
u32
g
=
0
;
g
<
8
;
++
g
)
getTransformedBoneVector
(
v
[
g
],
hitbox
[
i
].
bone
,
v2
[
g
]
);
driver
->
draw3DLine
(
v
[
0
],
v
[
1
],
yellow
);
driver
->
draw3DLine
(
v
[
1
],
v
[
3
],
yellow
);
driver
->
draw3DLine
(
v
[
3
],
v
[
2
],
yellow
);
driver
->
draw3DLine
(
v
[
2
],
v
[
0
],
yellow
);
driver
->
draw3DLine
(
v
[
4
],
v
[
5
],
yellow
);
driver
->
draw3DLine
(
v
[
5
],
v
[
7
],
yellow
);
driver
->
draw3DLine
(
v
[
7
],
v
[
6
],
yellow
);
driver
->
draw3DLine
(
v
[
6
],
v
[
4
],
yellow
);
driver
->
draw3DLine
(
v
[
0
],
v
[
6
],
yellow
);
driver
->
draw3DLine
(
v
[
1
],
v
[
7
],
yellow
);
driver
->
draw3DLine
(
v
[
3
],
v
[
5
],
yellow
);
driver
->
draw3DLine
(
v
[
2
],
v
[
4
],
yellow
);
}
}
//! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail.
IMesh
*
CAnimatedMeshHalfLife
::
getMesh
(
s32
frameInt
,
s32
detailLevel
,
s32
startFrameLoop
,
s32
endFrameLoop
)
{
f32
frame
=
frameInt
+
(
detailLevel
*
0.001
f
);
u32
frameA
=
core
::
floor32
(
frame
);
// f32 blend = core::fract ( frame );
SHalflifeSequence
*
seq
=
(
SHalflifeSequence
*
)
((
u8
*
)
Header
+
Header
->
seqindex
);
// find SequenceIndex from summed list
u32
frameCount
=
0
;
for
(
u32
i
=
0
;
i
<
Header
->
numseq
;
++
i
)
{
u32
val
=
core
::
max_
(
1
,
seq
[
i
].
numframes
-
1
);
if
(
frameCount
+
val
>
frameA
)
{
SequenceIndex
=
i
;
CurrentFrame
=
frame
-
frameCount
;
break
;
}
frameCount
+=
val
;
}
seq
+=
SequenceIndex
;
//SetBodyPart ( 1, 1 );
setUpBones
();
buildVertices
();
MeshIPol
->
BoundingBox
.
MinEdge
.
X
=
seq
->
bbmin
[
0
];
MeshIPol
->
BoundingBox
.
MinEdge
.
Z
=
seq
->
bbmin
[
1
];
MeshIPol
->
BoundingBox
.
MinEdge
.
Y
=
seq
->
bbmin
[
2
];
MeshIPol
->
BoundingBox
.
MaxEdge
.
X
=
seq
->
bbmax
[
0
];
MeshIPol
->
BoundingBox
.
MaxEdge
.
Z
=
seq
->
bbmax
[
1
];
MeshIPol
->
BoundingBox
.
MaxEdge
.
Y
=
seq
->
bbmax
[
2
];
return
MeshIPol
;
}
/*!
*/
void
CAnimatedMeshHalfLife
::
initData
()
{
u32
i
;
Header
=
0
;
TextureHeader
=
0
;
OwnTexModel
=
false
;
for
(
i
=
0
;
i
<
32
;
++
i
)
AnimationHeader
[
i
]
=
0
;
SequenceIndex
=
0
;
CurrentFrame
=
0.
f
;
for
(
i
=
0
;
i
<
5
;
++
i
)
BoneController
[
i
]
=
0
;
for
(
i
=
0
;
i
<
2
;
++
i
)
Blending
[
i
]
=
0
;
SkinGroupSelection
=
0
;
AnimList
.
clear
();
FrameCount
=
0
;
if
(
!
MeshIPol
)
MeshIPol
=
new
SMesh
();
MeshIPol
->
clear
();
#ifdef HL_TEXTURE_ATLAS
TextureAtlas
.
release
();
#endif
}
/*!
*/
void
STextureAtlas
::
release
()
{
for
(
u32
i
=
0
;
i
<
atlas
.
size
();
i
++
)
{
if
(
atlas
[
i
].
image
)
{
atlas
[
i
].
image
->
drop
();
atlas
[
i
].
image
=
0
;
}
}
Master
=
0
;
}
/*!
*/
void
STextureAtlas
::
addSource
(
const
c8
*
name
,
video
::
IImage
*
image
)
{
TextureAtlasEntry
entry
;
entry
.
name
=
name
;
entry
.
image
=
image
;
entry
.
width
=
image
->
getDimension
().
Width
;
entry
.
height
=
image
->
getDimension
().
Height
;
entry
.
pos
.
X
=
0
;
entry
.
pos
.
Y
=
0
;
atlas
.
push_back
(
entry
);
}
/*!
*/
void
STextureAtlas
::
getScale
(
core
::
vector2df
&
scale
)
{
for
(
s32
i
=
static_cast
<
s32
>
(
atlas
.
size
())
-
1
;
i
>=
0
;
--
i
)
{
if
(
atlas
[
i
].
name
==
"_merged_"
)
{
scale
.
X
=
1.
f
/
atlas
[
i
].
width
;
scale
.
Y
=
1.
f
/
atlas
[
i
].
height
;
return
;
}
}
scale
.
X
=
1.
f
;
scale
.
Y
=
1.
f
;
}
/*!
*/
void
STextureAtlas
::
getTranslation
(
const
c8
*
name
,
core
::
vector2di
&
pos
)
{
for
(
u32
i
=
0
;
i
<
atlas
.
size
();
++
i
)
{
if
(
atlas
[
i
].
name
==
name
)
{
pos
=
atlas
[
i
].
pos
;
return
;
}
}
}
/*!
*/
void
STextureAtlas
::
create
(
u32
border
,
E_TEXTURE_CLAMP
texmode
)
{
u32
i
=
0
;
u32
w
=
0
;
u32
w2
;
u32
h2
;
u32
h
;
u32
wsum
;
u32
hsum
=
0
;
ECOLOR_FORMAT
format
=
ECF_R8G8B8
;
const
s32
frame
=
core
::
s32_max
(
0
,
(
border
-
1
)
/
2
);
// sort for biggest coming first
atlas
.
sort
();
// split size
wsum
=
frame
;
for
(
i
=
0
;
i
<
atlas
.
size
();
i
++
)
{
// make space
w2
=
atlas
[
i
].
width
+
border
;
// align
w2
=
(
w2
+
1
)
&
~
1
;
wsum
+=
w2
;
}
u32
splitsize
=
256
;
if
(
wsum
>
512
)
splitsize
=
512
;
wsum
=
frame
;
hsum
=
frame
;
w
=
frame
;
h
=
0
;
for
(
i
=
0
;
i
<
atlas
.
size
();
i
++
)
{
if
(
atlas
[
i
].
image
->
getColorFormat
()
==
ECF_A8R8G8B8
)
{
format
=
ECF_A8R8G8B8
;
}
// make space
w2
=
atlas
[
i
].
width
+
border
;
h2
=
atlas
[
i
].
height
+
border
;
// align
w2
=
(
w2
+
1
)
&
~
1
;
h2
=
(
h2
+
1
)
&
~
1
;
h
=
core
::
s32_max
(
h
,
h2
);
if
(
w
+
w2
>=
splitsize
)
{
hsum
+=
h
;
wsum
=
core
::
s32_max
(
wsum
,
w
);
h
=
h2
;
w
=
frame
;
}
atlas
[
i
].
pos
.
X
=
w
;
atlas
[
i
].
pos
.
Y
=
hsum
;
w
+=
w2
;
}
hsum
+=
h
;
wsum
=
core
::
s32_max
(
wsum
,
w
);
// build image
core
::
dimension2d
<
u32
>
dim
=
core
::
dimension2d
<
u32
>
(
wsum
,
hsum
).
getOptimalSize
();
IImage
*
master
=
new
CImage
(
format
,
dim
);
master
->
fill
(
0
);
video
::
SColor
col
[
2
];
static
const
u8
wrap
[][
4
]
=
{
{
1
,
0
},
// ETC_REPEAT
{
0
,
1
},
// ETC_CLAMP
{
0
,
1
},
// ETC_CLAMP_TO_EDGE
{
0
,
1
}
// ETC_MIRROR
};
s32
a
,
b
;
for
(
i
=
0
;
i
<
atlas
.
size
();
i
++
)
{
atlas
[
i
].
image
->
copyTo
(
master
,
atlas
[
i
].
pos
);
// clamp/wrap ( copy edges, filtering needs it )
for
(
b
=
0
;
b
<
frame
;
++
b
)
{
for
(
a
=
0
-
b
;
a
<=
(
s32
)
atlas
[
i
].
width
+
b
;
++
a
)
{
col
[
0
]
=
atlas
[
i
].
image
->
getPixel
(
core
::
s32_clamp
(
a
,
0
,
atlas
[
i
].
width
-
1
),
0
);
col
[
1
]
=
atlas
[
i
].
image
->
getPixel
(
core
::
s32_clamp
(
a
,
0
,
atlas
[
i
].
width
-
1
),
atlas
[
i
].
height
-
1
);
master
->
setPixel
(
atlas
[
i
].
pos
.
X
+
a
,
atlas
[
i
].
pos
.
Y
+
(
b
+
1
)
*
-
1
,
col
[
wrap
[
texmode
][
0
]]
);
master
->
setPixel
(
atlas
[
i
].
pos
.
X
+
a
,
atlas
[
i
].
pos
.
Y
+
atlas
[
i
].
height
-
1
+
(
b
+
1
)
*
1
,
col
[
wrap
[
texmode
][
1
]]
);
}
for
(
a
=
-
1
-
b
;
a
<=
(
s32
)
atlas
[
i
].
height
+
b
;
++
a
)
{
col
[
0
]
=
atlas
[
i
].
image
->
getPixel
(
0
,
core
::
s32_clamp
(
a
,
0
,
atlas
[
i
].
height
-
1
)
);
col
[
1
]
=
atlas
[
i
].
image
->
getPixel
(
atlas
[
i
].
width
-
1
,
core
::
s32_clamp
(
a
,
0
,
atlas
[
i
].
height
-
1
)
);
master
->
setPixel
(
atlas
[
i
].
pos
.
X
+
(
b
+
1
)
*
-
1
,
atlas
[
i
].
pos
.
Y
+
a
,
col
[
wrap
[
texmode
][
0
]]
);
master
->
setPixel
(
atlas
[
i
].
pos
.
X
+
atlas
[
i
].
width
+
b
,
atlas
[
i
].
pos
.
Y
+
a
,
col
[
wrap
[
texmode
][
1
]]
);
}
}
}
addSource
(
"_merged_"
,
master
);
Master
=
master
;
}
/*!
*/
SHalflifeHeader
*
CAnimatedMeshHalfLife
::
loadModel
(
io
::
IReadFile
*
file
,
const
io
::
path
&
filename
)
{
bool
closefile
=
false
;
// if secondary files are needed, open here and mark for closing
if
(
0
==
file
)
{
file
=
SceneManager
->
getFileSystem
()
->
createAndOpenFile
(
filename
);
closefile
=
true
;
}
if
(
0
==
file
)
return
0
;
// read into memory
u8
*
pin
=
new
u8
[
file
->
getSize
()];
file
->
read
(
pin
,
file
->
getSize
());
SHalflifeHeader
*
header
=
(
SHalflifeHeader
*
)
pin
;
const
bool
idst
=
(
0
==
strncmp
(
header
->
id
,
"IDST"
,
4
));
const
bool
idsq
=
(
0
==
strncmp
(
header
->
id
,
"IDSQ"
,
4
));
if
(
(
!
idst
&&
!
idsq
)
||
(
idsq
&&
!
Header
)
)
{
os
::
Printer
::
log
(
"MDL Halflife Loader: Wrong file header"
,
file
->
getFileName
(),
ELL_WARNING
);
if
(
closefile
)
{
file
->
drop
();
file
=
0
;
}
delete
[]
pin
;
return
0
;
}
// don't know the real header.. idsg might be different
if
(
header
->
textureindex
&&
idst
)
{
io
::
path
path
;
io
::
path
fname
;
io
::
path
ext
;
core
::
splitFilename
(
file
->
getFileName
(),
&
path
,
&
fname
,
&
ext
);
TextureBaseName
=
path
+
fname
+
"_"
;
SHalflifeTexture
*
tex
=
(
SHalflifeTexture
*
)(
pin
+
header
->
textureindex
);
u32
*
palette
=
new
u32
[
256
];
for
(
u32
i
=
0
;
i
<
header
->
numtextures
;
++
i
)
{
const
u8
*
src
=
pin
+
tex
[
i
].
index
;
// convert rgb to argb palette
{
const
u8
*
pal
=
src
+
tex
[
i
].
width
*
tex
[
i
].
height
;
for
(
u32
g
=
0
;
g
<
256
;
++
g
)
{
palette
[
g
]
=
0xFF000000
|
pal
[
0
]
<<
16
|
pal
[
1
]
<<
8
|
pal
[
2
];
pal
+=
3
;
}
}
IImage
*
image
=
SceneManager
->
getVideoDriver
()
->
createImage
(
ECF_R8G8B8
,
core
::
dimension2d
<
u32
>
(
tex
[
i
].
width
,
tex
[
i
].
height
));
CColorConverter
::
convert8BitTo24Bit
(
src
,
(
u8
*
)
image
->
lock
(),
tex
[
i
].
width
,
tex
[
i
].
height
,
(
u8
*
)
palette
,
0
,
false
);
image
->
unlock
();
#ifdef HL_TEXTURE_ATLAS
TextureAtlas
.
addSource
(
tex
[
i
].
name
,
image
);
#else
core
::
splitFilename
(
tex
[
i
].
name
,
0
,
&
fname
,
&
ext
);
SceneManager
->
getVideoDriver
()
->
addTexture
(
TextureBaseName
+
fname
,
image
);
image
->
drop
();
#endif
}
delete
[]
palette
;
#ifdef HL_TEXTURE_ATLAS
TextureAtlas
.
create
(
2
*
2
+
1
,
ETC_CLAMP
);
SceneManager
->
getVideoDriver
()
->
addTexture
(
TextureBaseName
+
"atlas"
,
TextureAtlas
.
Master
);
TextureAtlas
.
release
();
#endif
}
if
(
!
Header
)
Header
=
header
;
if
(
closefile
)
{
file
->
drop
();
file
=
0
;
}
return
header
;
}
/*!
*/
f32
CAnimatedMeshHalfLife
::
SetController
(
s32
controllerIndex
,
f32
value
)
{
if
(
!
Header
)
return
0.
f
;
SHalflifeBoneController
*
bonecontroller
=
(
SHalflifeBoneController
*
)((
u8
*
)
Header
+
Header
->
bonecontrollerindex
);
// find first controller that matches the index
u32
i
;
for
(
i
=
0
;
i
<
Header
->
numbonecontrollers
;
i
++
,
bonecontroller
++
)
{
if
(
bonecontroller
->
index
==
controllerIndex
)
break
;
}
if
(
i
>=
Header
->
numbonecontrollers
)
return
value
;
// wrap 0..360 if it's a rotational controller
if
(
bonecontroller
->
type
&
(
STUDIO_XR
|
STUDIO_YR
|
STUDIO_ZR
))
{
// ugly hack, invert value if end < start
if
(
bonecontroller
->
end
<
bonecontroller
->
start
)
value
=
-
value
;
// does the controller not wrap?
if
(
bonecontroller
->
start
+
359.
f
>=
bonecontroller
->
end
)
{
if
(
value
>
((
bonecontroller
->
start
+
bonecontroller
->
end
)
/
2.
f
)
+
180.
f
)
value
=
value
-
360.
f
;
if
(
value
<
((
bonecontroller
->
start
+
bonecontroller
->
end
)
/
2.
f
)
-
180.
f
)
value
=
value
+
360.
f
;
}
else
{
if
(
value
>
360.
f
)
value
=
value
-
(
s32
)(
value
/
360.
f
)
*
360.
f
;
else
if
(
value
<
0.
f
)
value
=
value
+
(
s32
)((
value
/
-
360.
f
)
+
1
)
*
360.
f
;
}
}
s32
range
=
controllerIndex
==
MOUTH_CONTROLLER
?
64
:
255
;
s32
setting
=
(
s32
)
(
(
f32
)
range
*
(
value
-
bonecontroller
->
start
)
/
(
bonecontroller
->
end
-
bonecontroller
->
start
));
if
(
setting
<
0
)
setting
=
0
;
if
(
setting
>
range
)
setting
=
range
;
BoneController
[
controllerIndex
]
=
setting
;
return
setting
*
(
1.
f
/
(
f32
)
range
)
*
(
bonecontroller
->
end
-
bonecontroller
->
start
)
+
bonecontroller
->
start
;
}
/*!
*/
u32
CAnimatedMeshHalfLife
::
SetSkin
(
u32
value
)
{
if
(
value
<
Header
->
numskinfamilies
)
SkinGroupSelection
=
value
;
return
SkinGroupSelection
;
}
/*!
*/
bool
CAnimatedMeshHalfLife
::
postLoadModel
(
const
io
::
path
&
filename
)
{
io
::
path
path
;
io
::
path
texname
;
io
::
path
submodel
;
core
::
splitFilename
(
filename
,
&
path
,
&
texname
,
0
);
// preload textures
// if no textures are stored in main file, use texfile
if
(
Header
->
numtextures
==
0
)
{
submodel
=
path
+
texname
+
"T.mdl"
;
TextureHeader
=
loadModel
(
0
,
submodel
);
if
(
!
TextureHeader
)
return
false
;
OwnTexModel
=
true
;
}
else
{
TextureHeader
=
Header
;
OwnTexModel
=
false
;
}
// preload animations
if
(
Header
->
numseqgroups
>
1
)
{
c8
seq
[
8
];
for
(
u32
i
=
1
;
i
<
Header
->
numseqgroups
;
i
++
)
{
snprintf
(
seq
,
8
,
"%02d.mdl"
,
i
);
submodel
=
path
+
texname
+
seq
;
AnimationHeader
[
i
]
=
loadModel
(
0
,
submodel
);
if
(
!
AnimationHeader
[
i
])
return
false
;
}
}
return
true
;
}
/*!
*/
void
CAnimatedMeshHalfLife
::
dumpModelInfo
(
u32
level
)
const
{
const
u8
*
phdr
=
(
const
u8
*
)
Header
;
const
SHalflifeHeader
*
hdr
=
Header
;
u32
i
;
if
(
level
==
0
)
{
printf
(
"Bones: %d
\n
"
"Bone Controllers: %d
\n
"
"Hit Boxes: %d
\n
"
"Sequences: %d
\n
"
"Sequence Groups: %d
\n
"
,
hdr
->
numbones
,
hdr
->
numbonecontrollers
,
hdr
->
numhitboxes
,
hdr
->
numseq
,
hdr
->
numseqgroups
);
printf
(
"Textures: %d
\n
"
"Skin Families: %d
\n
"
"Bodyparts: %d
\n
"
"Attachments: %d
\n
"
"Transitions: %d
\n
"
,
hdr
->
numtextures
,
hdr
->
numskinfamilies
,
hdr
->
numbodyparts
,
hdr
->
numattachments
,
hdr
->
numtransitions
);
return
;
}
printf
(
"id: %c%c%c%c
\n
"
,
phdr
[
0
],
phdr
[
1
],
phdr
[
2
],
phdr
[
3
]);
printf
(
"version: %d
\n
"
,
hdr
->
version
);
printf
(
"name:
\"
%s
\"\n
"
,
hdr
->
name
);
printf
(
"length: %d
\n\n
"
,
hdr
->
length
);
printf
(
"eyeposition: %f %f %f
\n
"
,
hdr
->
eyeposition
[
0
],
hdr
->
eyeposition
[
1
],
hdr
->
eyeposition
[
2
]);
printf
(
"min: %f %f %f
\n
"
,
hdr
->
min
[
0
],
hdr
->
min
[
1
],
hdr
->
min
[
2
]);
printf
(
"max: %f %f %f
\n
"
,
hdr
->
max
[
0
],
hdr
->
max
[
1
],
hdr
->
max
[
2
]);
printf
(
"bbmin: %f %f %f
\n
"
,
hdr
->
bbmin
[
0
],
hdr
->
bbmin
[
1
],
hdr
->
bbmin
[
2
]);
printf
(
"bbmax: %f %f %f
\n
"
,
hdr
->
bbmax
[
0
],
hdr
->
bbmax
[
1
],
hdr
->
bbmax
[
2
]);
printf
(
"flags: %d
\n\n
"
,
hdr
->
flags
);
printf
(
"numbones: %d
\n
"
,
hdr
->
numbones
);
for
(
i
=
0
;
i
<
hdr
->
numbones
;
i
++
)
{
const
SHalflifeBone
*
bone
=
(
const
SHalflifeBone
*
)
(
phdr
+
hdr
->
boneindex
);
printf
(
"bone %d.name:
\"
%s
\"\n
"
,
i
+
1
,
bone
[
i
].
name
);
printf
(
"bone %d.parent: %d
\n
"
,
i
+
1
,
bone
[
i
].
parent
);
printf
(
"bone %d.flags: %d
\n
"
,
i
+
1
,
bone
[
i
].
flags
);
printf
(
"bone %d.bonecontroller: %d %d %d %d %d %d
\n
"
,
i
+
1
,
bone
[
i
].
bonecontroller
[
0
],
bone
[
i
].
bonecontroller
[
1
],
bone
[
i
].
bonecontroller
[
2
],
bone
[
i
].
bonecontroller
[
3
],
bone
[
i
].
bonecontroller
[
4
],
bone
[
i
].
bonecontroller
[
5
]);
printf
(
"bone %d.value: %f %f %f %f %f %f
\n
"
,
i
+
1
,
bone
[
i
].
value
[
0
],
bone
[
i
].
value
[
1
],
bone
[
i
].
value
[
2
],
bone
[
i
].
value
[
3
],
bone
[
i
].
value
[
4
],
bone
[
i
].
value
[
5
]);
printf
(
"bone %d.scale: %f %f %f %f %f %f
\n
"
,
i
+
1
,
bone
[
i
].
scale
[
0
],
bone
[
i
].
scale
[
1
],
bone
[
i
].
scale
[
2
],
bone
[
i
].
scale
[
3
],
bone
[
i
].
scale
[
4
],
bone
[
i
].
scale
[
5
]);
}
printf
(
"
\n
numbonecontrollers: %d
\n
"
,
hdr
->
numbonecontrollers
);
const
SHalflifeBoneController
*
bonecontrollers
=
(
const
SHalflifeBoneController
*
)
(
phdr
+
hdr
->
bonecontrollerindex
);
for
(
i
=
0
;
i
<
hdr
->
numbonecontrollers
;
i
++
)
{
printf
(
"bonecontroller %d.bone: %d
\n
"
,
i
+
1
,
bonecontrollers
[
i
].
bone
);
printf
(
"bonecontroller %d.type: %d
\n
"
,
i
+
1
,
bonecontrollers
[
i
].
type
);
printf
(
"bonecontroller %d.start: %f
\n
"
,
i
+
1
,
bonecontrollers
[
i
].
start
);
printf
(
"bonecontroller %d.end: %f
\n
"
,
i
+
1
,
bonecontrollers
[
i
].
end
);
printf
(
"bonecontroller %d.rest: %d
\n
"
,
i
+
1
,
bonecontrollers
[
i
].
rest
);
printf
(
"bonecontroller %d.index: %d
\n
"
,
i
+
1
,
bonecontrollers
[
i
].
index
);
}
printf
(
"
\n
numhitboxes: %d
\n
"
,
hdr
->
numhitboxes
);
const
SHalflifeBBox
*
box
=
(
const
SHalflifeBBox
*
)
(
phdr
+
hdr
->
hitboxindex
);
for
(
i
=
0
;
i
<
hdr
->
numhitboxes
;
i
++
)
{
printf
(
"hitbox %d.bone: %d
\n
"
,
i
+
1
,
box
[
i
].
bone
);
printf
(
"hitbox %d.group: %d
\n
"
,
i
+
1
,
box
[
i
].
group
);
printf
(
"hitbox %d.bbmin: %f %f %f
\n
"
,
i
+
1
,
box
[
i
].
bbmin
[
0
],
box
[
i
].
bbmin
[
1
],
box
[
i
].
bbmin
[
2
]);
printf
(
"hitbox %d.bbmax: %f %f %f
\n
"
,
i
+
1
,
box
[
i
].
bbmax
[
0
],
box
[
i
].
bbmax
[
1
],
box
[
i
].
bbmax
[
2
]);
}
printf
(
"
\n
numseq: %d
\n
"
,
hdr
->
numseq
);
const
SHalflifeSequence
*
seq
=
(
const
SHalflifeSequence
*
)
(
phdr
+
hdr
->
seqindex
);
for
(
i
=
0
;
i
<
hdr
->
numseq
;
i
++
)
{
printf
(
"seqdesc %d.label:
\"
%s
\"\n
"
,
i
+
1
,
seq
[
i
].
label
);
printf
(
"seqdesc %d.fps: %f
\n
"
,
i
+
1
,
seq
[
i
].
fps
);
printf
(
"seqdesc %d.flags: %d
\n
"
,
i
+
1
,
seq
[
i
].
flags
);
printf
(
"<...>
\n
"
);
}
printf
(
"
\n
numseqgroups: %d
\n
"
,
hdr
->
numseqgroups
);
for
(
i
=
0
;
i
<
hdr
->
numseqgroups
;
i
++
)
{
const
SHalflifeSequenceGroup
*
group
=
(
const
SHalflifeSequenceGroup
*
)
(
phdr
+
hdr
->
seqgroupindex
);
printf
(
"
\n
seqgroup %d.label:
\"
%s
\"\n
"
,
i
+
1
,
group
[
i
].
label
);
printf
(
"
\n
seqgroup %d.namel:
\"
%s
\"\n
"
,
i
+
1
,
group
[
i
].
name
);
printf
(
"
\n
seqgroup %d.data: %d
\n
"
,
i
+
1
,
group
[
i
].
data
);
}
printf
(
"
\n
numskinref: %d
\n
"
,
hdr
->
numskinref
);
printf
(
"numskinfamilies: %d
\n
"
,
hdr
->
numskinfamilies
);
printf
(
"
\n
numbodyparts: %d
\n
"
,
hdr
->
numbodyparts
);
const
SHalflifeBody
*
pbodyparts
=
(
const
SHalflifeBody
*
)
((
const
u8
*
)
hdr
+
hdr
->
bodypartindex
);
for
(
i
=
0
;
i
<
hdr
->
numbodyparts
;
i
++
)
{
printf
(
"bodypart %d.name:
\"
%s
\"\n
"
,
i
+
1
,
pbodyparts
[
i
].
name
);
printf
(
"bodypart %d.nummodels: %d
\n
"
,
i
+
1
,
pbodyparts
[
i
].
nummodels
);
printf
(
"bodypart %d.base: %d
\n
"
,
i
+
1
,
pbodyparts
[
i
].
base
);
printf
(
"bodypart %d.modelindex: %d
\n
"
,
i
+
1
,
pbodyparts
[
i
].
modelindex
);
}
printf
(
"
\n
numattachments: %d
\n
"
,
hdr
->
numattachments
);
for
(
i
=
0
;
i
<
hdr
->
numattachments
;
i
++
)
{
const
SHalflifeAttachment
*
attach
=
(
const
SHalflifeAttachment
*
)
((
const
u8
*
)
hdr
+
hdr
->
attachmentindex
);
printf
(
"attachment %d.name:
\"
%s
\"\n
"
,
i
+
1
,
attach
[
i
].
name
);
}
hdr
=
TextureHeader
;
printf
(
"
\n
numtextures: %d
\n
"
,
hdr
->
numtextures
);
printf
(
"textureindex: %d
\n
"
,
hdr
->
textureindex
);
printf
(
"texturedataindex: %d
\n
"
,
hdr
->
texturedataindex
);
const
SHalflifeTexture
*
ptextures
=
(
const
SHalflifeTexture
*
)
((
const
u8
*
)
hdr
+
hdr
->
textureindex
);
for
(
i
=
0
;
i
<
hdr
->
numtextures
;
i
++
)
{
printf
(
"texture %d.name:
\"
%s
\"\n
"
,
i
+
1
,
ptextures
[
i
].
name
);
printf
(
"texture %d.flags: %d
\n
"
,
i
+
1
,
ptextures
[
i
].
flags
);
printf
(
"texture %d.width: %d
\n
"
,
i
+
1
,
ptextures
[
i
].
width
);
printf
(
"texture %d.height: %d
\n
"
,
i
+
1
,
ptextures
[
i
].
height
);
printf
(
"texture %d.index: %d
\n
"
,
i
+
1
,
ptextures
[
i
].
index
);
}
}
/*!
*/
void
CAnimatedMeshHalfLife
::
ExtractBbox
(
s32
sequence
,
core
::
aabbox3df
&
box
)
const
{
const
SHalflifeSequence
*
seq
=
(
const
SHalflifeSequence
*
)((
const
u8
*
)
Header
+
Header
->
seqindex
)
+
sequence
;
box
.
MinEdge
.
X
=
seq
[
0
].
bbmin
[
0
];
box
.
MinEdge
.
Y
=
seq
[
0
].
bbmin
[
1
];
box
.
MinEdge
.
Z
=
seq
[
0
].
bbmin
[
2
];
box
.
MaxEdge
.
X
=
seq
[
0
].
bbmax
[
0
];
box
.
MaxEdge
.
Y
=
seq
[
0
].
bbmax
[
1
];
box
.
MaxEdge
.
Z
=
seq
[
0
].
bbmax
[
2
];
}
/*!
*/
void
CAnimatedMeshHalfLife
::
calcBoneAdj
()
{
const
SHalflifeBoneController
*
bonecontroller
=
(
const
SHalflifeBoneController
*
)((
const
u8
*
)
Header
+
Header
->
bonecontrollerindex
);
for
(
u32
j
=
0
;
j
<
Header
->
numbonecontrollers
;
j
++
)
{
const
s32
i
=
bonecontroller
[
j
].
index
;
// check for 360% wrapping
f32
value
;
if
(
bonecontroller
[
j
].
type
&
STUDIO_RLOOP
)
{
value
=
BoneController
[
i
]
*
(
360.
f
/
256.
f
)
+
bonecontroller
[
j
].
start
;
}
else
{
const
f32
range
=
i
<=
3
?
255.
f
:
64.
f
;
value
=
core
::
clamp
(
BoneController
[
i
]
/
range
,
0.
f
,
1.
f
);
value
=
(
1.
f
-
value
)
*
bonecontroller
[
j
].
start
+
value
*
bonecontroller
[
j
].
end
;
}
switch
(
bonecontroller
[
j
].
type
&
STUDIO_TYPES
)
{
case
STUDIO_XR
:
case
STUDIO_YR
:
case
STUDIO_ZR
:
BoneAdj
[
j
]
=
value
*
core
::
DEGTORAD
;
break
;
case
STUDIO_X
:
case
STUDIO_Y
:
case
STUDIO_Z
:
BoneAdj
[
j
]
=
value
;
break
;
}
}
}
/*!
*/
void
CAnimatedMeshHalfLife
::
calcBoneQuaternion
(
const
s32
frame
,
const
SHalflifeBone
*
const
bone
,
SHalflifeAnimOffset
*
anim
,
const
u32
j
,
f32
&
angle1
,
f32
&
angle2
)
const
{
// three vector components
if
(
anim
->
offset
[
j
+
3
]
==
0
)
{
angle2
=
angle1
=
bone
->
value
[
j
+
3
];
// default
}
else
{
SHalflifeAnimationFrame
*
animvalue
=
(
SHalflifeAnimationFrame
*
)((
u8
*
)
anim
+
anim
->
offset
[
j
+
3
]);
s32
k
=
frame
;
while
(
animvalue
->
num
.
total
<=
k
)
{
k
-=
animvalue
->
num
.
total
;
animvalue
+=
animvalue
->
num
.
valid
+
1
;
}
// Bah, missing blend!
if
(
animvalue
->
num
.
valid
>
k
)
{
angle1
=
animvalue
[
k
+
1
].
value
;
if
(
animvalue
->
num
.
valid
>
k
+
1
)
{
angle2
=
animvalue
[
k
+
2
].
value
;
}
else
{
if
(
animvalue
->
num
.
total
>
k
+
1
)
angle2
=
angle1
;
else
angle2
=
animvalue
[
animvalue
->
num
.
valid
+
2
].
value
;
}
}
else
{
angle1
=
animvalue
[
animvalue
->
num
.
valid
].
value
;
if
(
animvalue
->
num
.
total
>
k
+
1
)
{
angle2
=
angle1
;
}
else
{
angle2
=
animvalue
[
animvalue
->
num
.
valid
+
2
].
value
;
}
}
angle1
=
bone
->
value
[
j
+
3
]
+
angle1
*
bone
->
scale
[
j
+
3
];
angle2
=
bone
->
value
[
j
+
3
]
+
angle2
*
bone
->
scale
[
j
+
3
];
}
if
(
bone
->
bonecontroller
[
j
+
3
]
!=
-
1
)
{
angle1
+=
BoneAdj
[
bone
->
bonecontroller
[
j
+
3
]];
angle2
+=
BoneAdj
[
bone
->
bonecontroller
[
j
+
3
]];
}
}
/*!
*/
void
CAnimatedMeshHalfLife
::
calcBonePosition
(
const
s32
frame
,
f32
s
,
const
SHalflifeBone
*
const
bone
,
SHalflifeAnimOffset
*
anim
,
f32
*
pos
)
const
{
for
(
s32
j
=
0
;
j
<
3
;
++
j
)
{
pos
[
j
]
=
bone
->
value
[
j
];
// default;
if
(
anim
->
offset
[
j
]
!=
0
)
{
SHalflifeAnimationFrame
*
animvalue
=
(
SHalflifeAnimationFrame
*
)((
u8
*
)
anim
+
anim
->
offset
[
j
]);
s32
k
=
frame
;
// find span of values that includes the frame we want
while
(
animvalue
->
num
.
total
<=
k
)
{
k
-=
animvalue
->
num
.
total
;
animvalue
+=
animvalue
->
num
.
valid
+
1
;
}
// if we're inside the span
if
(
animvalue
->
num
.
valid
>
k
)
{
// and there's more data in the span
if
(
animvalue
->
num
.
valid
>
k
+
1
)
{
pos
[
j
]
+=
(
animvalue
[
k
+
1
].
value
*
(
1.
f
-
s
)
+
s
*
animvalue
[
k
+
2
].
value
)
*
bone
->
scale
[
j
];
}
else
{
pos
[
j
]
+=
animvalue
[
k
+
1
].
value
*
bone
->
scale
[
j
];
}
}
else
{
// are we at the end of the repeating values section and there's another section with data?
if
(
animvalue
->
num
.
total
<=
k
+
1
)
{
pos
[
j
]
+=
(
animvalue
[
animvalue
->
num
.
valid
].
value
*
(
1.
f
-
s
)
+
s
*
animvalue
[
animvalue
->
num
.
valid
+
2
].
value
)
*
bone
->
scale
[
j
];
}
else
{
pos
[
j
]
+=
animvalue
[
animvalue
->
num
.
valid
].
value
*
bone
->
scale
[
j
];
}
}
}
if
(
bone
->
bonecontroller
[
j
]
!=
-
1
)
{
pos
[
j
]
+=
BoneAdj
[
bone
->
bonecontroller
[
j
]];
}
}
}
/*!
*/
void
CAnimatedMeshHalfLife
::
calcRotations
(
vec3_hl
*
pos
,
vec4_hl
*
q
,
SHalflifeSequence
*
seq
,
SHalflifeAnimOffset
*
anim
,
f32
f
)
{
s32
frame
=
(
s32
)
f
;
f32
s
=
(
f
-
frame
);
// add in programatic controllers
calcBoneAdj
();
SHalflifeBone
*
bone
=
(
SHalflifeBone
*
)((
u8
*
)
Header
+
Header
->
boneindex
);
for
(
u32
i
=
0
;
i
<
Header
->
numbones
;
i
++
,
bone
++
,
anim
++
)
{
core
::
vector3df
angle1
,
angle2
;
calcBoneQuaternion
(
frame
,
bone
,
anim
,
0
,
angle1
.
X
,
angle2
.
X
);
calcBoneQuaternion
(
frame
,
bone
,
anim
,
1
,
angle1
.
Y
,
angle2
.
Y
);
calcBoneQuaternion
(
frame
,
bone
,
anim
,
2
,
angle1
.
Z
,
angle2
.
Z
);
if
(
!
angle1
.
equals
(
angle2
))
{
vec4_hl
q1
,
q2
;
AngleQuaternion
(
angle1
,
q1
);
AngleQuaternion
(
angle2
,
q2
);
QuaternionSlerp
(
q1
,
q2
,
s
,
q
[
i
]
);
}
else
{
AngleQuaternion
(
angle1
,
q
[
i
]
);
}
calcBonePosition
(
frame
,
s
,
bone
,
anim
,
pos
[
i
]);
}
if
(
seq
->
motiontype
&
STUDIO_X
)
pos
[
seq
->
motionbone
][
0
]
=
0.
f
;
if
(
seq
->
motiontype
&
STUDIO_Y
)
pos
[
seq
->
motionbone
][
1
]
=
0.
f
;
if
(
seq
->
motiontype
&
STUDIO_Z
)
pos
[
seq
->
motionbone
][
2
]
=
0.
f
;
}
/*!
*/
SHalflifeAnimOffset
*
CAnimatedMeshHalfLife
::
getAnim
(
SHalflifeSequence
*
seq
)
{
SHalflifeSequenceGroup
*
seqgroup
=
(
SHalflifeSequenceGroup
*
)((
u8
*
)
Header
+
Header
->
seqgroupindex
)
+
seq
->
seqgroup
;
if
(
seq
->
seqgroup
==
0
)
{
return
(
SHalflifeAnimOffset
*
)((
u8
*
)
Header
+
seqgroup
->
data
+
seq
->
animindex
);
}
return
(
SHalflifeAnimOffset
*
)((
u8
*
)
AnimationHeader
[
seq
->
seqgroup
]
+
seq
->
animindex
);
}
/*!
*/
void
CAnimatedMeshHalfLife
::
slerpBones
(
vec4_hl
q1
[],
vec3_hl
pos1
[],
vec4_hl
q2
[],
vec3_hl
pos2
[],
f32
s
)
{
if
(
s
<
0
)
s
=
0
;
else
if
(
s
>
1.
f
)
s
=
1.
f
;
f32
s1
=
1.
f
-
s
;
for
(
u32
i
=
0
;
i
<
Header
->
numbones
;
i
++
)
{
vec4_hl
q3
;
QuaternionSlerp
(
q1
[
i
],
q2
[
i
],
s
,
q3
);
q1
[
i
][
0
]
=
q3
[
0
];
q1
[
i
][
1
]
=
q3
[
1
];
q1
[
i
][
2
]
=
q3
[
2
];
q1
[
i
][
3
]
=
q3
[
3
];
pos1
[
i
][
0
]
=
pos1
[
i
][
0
]
*
s1
+
pos2
[
i
][
0
]
*
s
;
pos1
[
i
][
1
]
=
pos1
[
i
][
1
]
*
s1
+
pos2
[
i
][
1
]
*
s
;
pos1
[
i
][
2
]
=
pos1
[
i
][
2
]
*
s1
+
pos2
[
i
][
2
]
*
s
;
}
}
/*!
*/
void
CAnimatedMeshHalfLife
::
setUpBones
()
{
static
vec3_hl
pos
[
MAXSTUDIOBONES
];
f32
bonematrix
[
3
][
4
];
static
vec4_hl
q
[
MAXSTUDIOBONES
];
static
vec3_hl
pos2
[
MAXSTUDIOBONES
];
static
vec4_hl
q2
[
MAXSTUDIOBONES
];
static
vec3_hl
pos3
[
MAXSTUDIOBONES
];
static
vec4_hl
q3
[
MAXSTUDIOBONES
];
static
vec3_hl
pos4
[
MAXSTUDIOBONES
];
static
vec4_hl
q4
[
MAXSTUDIOBONES
];
if
(
SequenceIndex
>=
Header
->
numseq
)
SequenceIndex
=
0
;
SHalflifeSequence
*
seq
=
(
SHalflifeSequence
*
)((
u8
*
)
Header
+
Header
->
seqindex
)
+
SequenceIndex
;
SHalflifeAnimOffset
*
anim
=
getAnim
(
seq
);
calcRotations
(
pos
,
q
,
seq
,
anim
,
CurrentFrame
);
if
(
seq
->
numblends
>
1
)
{
anim
+=
Header
->
numbones
;
calcRotations
(
pos2
,
q2
,
seq
,
anim
,
CurrentFrame
);
f32
s
=
Blending
[
0
]
/
255.
f
;
slerpBones
(
q
,
pos
,
q2
,
pos2
,
s
);
if
(
seq
->
numblends
==
4
)
{
anim
+=
Header
->
numbones
;
calcRotations
(
pos3
,
q3
,
seq
,
anim
,
CurrentFrame
);
anim
+=
Header
->
numbones
;
calcRotations
(
pos4
,
q4
,
seq
,
anim
,
CurrentFrame
);
s
=
Blending
[
0
]
/
255.
f
;
slerpBones
(
q3
,
pos3
,
q4
,
pos4
,
s
);
s
=
Blending
[
1
]
/
255.
f
;
slerpBones
(
q
,
pos
,
q3
,
pos3
,
s
);
}
}
SHalflifeBone
*
bone
=
(
SHalflifeBone
*
)((
u8
*
)
Header
+
Header
->
boneindex
);
for
(
u32
i
=
0
;
i
<
Header
->
numbones
;
i
++
)
{
QuaternionMatrix
(
q
[
i
],
bonematrix
);
bonematrix
[
0
][
3
]
=
pos
[
i
][
0
];
bonematrix
[
1
][
3
]
=
pos
[
i
][
1
];
bonematrix
[
2
][
3
]
=
pos
[
i
][
2
];
if
(
bone
[
i
].
parent
==
-
1
)
{
memcpy
(
BoneTransform
[
i
],
bonematrix
,
sizeof
(
f32
)
*
12
);
}
else
{
R_ConcatTransforms
(
BoneTransform
[
bone
[
i
].
parent
],
bonematrix
,
BoneTransform
[
i
]);
}
}
}
//! Returns an axis aligned bounding box
const
core
::
aabbox3d
<
f32
>&
CAnimatedMeshHalfLife
::
getBoundingBox
()
const
{
return
MeshIPol
->
BoundingBox
;
}
//! Returns the type of the animated mesh.
E_ANIMATED_MESH_TYPE
CAnimatedMeshHalfLife
::
getMeshType
()
const
{
return
EAMT_MDL_HALFLIFE
;
}
//! returns amount of mesh buffers.
u32
CAnimatedMeshHalfLife
::
getMeshBufferCount
()
const
{
return
MeshIPol
->
getMeshBufferCount
();
}
//! returns pointer to a mesh buffer
IMeshBuffer
*
CAnimatedMeshHalfLife
::
getMeshBuffer
(
u32
nr
)
const
{
return
MeshIPol
->
getMeshBuffer
(
nr
);
}
//! Returns pointer to a mesh buffer which fits a material
/** \param material: material to search for
\return Returns the pointer to the mesh buffer or
NULL if there is no such mesh buffer. */
IMeshBuffer
*
CAnimatedMeshHalfLife
::
getMeshBuffer
(
const
video
::
SMaterial
&
material
)
const
{
return
MeshIPol
->
getMeshBuffer
(
material
);
}
void
CAnimatedMeshHalfLife
::
setMaterialFlag
(
video
::
E_MATERIAL_FLAG
flag
,
bool
newvalue
)
{
MeshIPol
->
setMaterialFlag
(
flag
,
newvalue
);
}
//! set user axis aligned bounding box
void
CAnimatedMeshHalfLife
::
setBoundingBox
(
const
core
::
aabbox3df
&
box
)
{
MeshIPol
->
setBoundingBox
(
box
);
}
}
// end namespace scene
}
// end namespace irr
#endif // _IRR_COMPILE_WITH_MD3_LOADER_
Classes/gframe/client_field.cpp
View file @
435c57e2
...
@@ -698,10 +698,10 @@ void ClientField::ShowSelectOption(int select_hint) {
...
@@ -698,10 +698,10 @@ void ClientField::ShowSelectOption(int select_hint) {
int
newheight
=
50
+
60
*
(
scrollbar
?
5
:
count
)
*
mainGame
->
yScale
;
int
newheight
=
50
+
60
*
(
scrollbar
?
5
:
count
)
*
mainGame
->
yScale
;
int
oldheight
=
pos
.
LowerRightCorner
.
Y
-
pos
.
UpperLeftCorner
.
Y
;
int
oldheight
=
pos
.
LowerRightCorner
.
Y
-
pos
.
UpperLeftCorner
.
Y
;
pos
.
UpperLeftCorner
.
Y
=
pos
.
UpperLeftCorner
.
Y
+
(
oldheight
-
newheight
)
/
2
;
pos
.
UpperLeftCorner
.
Y
=
pos
.
UpperLeftCorner
.
Y
+
(
oldheight
-
newheight
)
/
2
;
pos
.
LowerRightCorner
.
X
=
pos
.
UpperLeftCorner
.
X
+
(
scrollbar
?
4
0
5
:
390
)
*
mainGame
->
xScale
;
pos
.
LowerRightCorner
.
X
=
pos
.
UpperLeftCorner
.
X
+
(
scrollbar
?
4
2
5
:
390
)
*
mainGame
->
xScale
;
pos
.
LowerRightCorner
.
Y
=
pos
.
UpperLeftCorner
.
Y
+
newheight
;
pos
.
LowerRightCorner
.
Y
=
pos
.
UpperLeftCorner
.
Y
+
newheight
;
mainGame
->
wOptions
->
setRelativePosition
(
pos
);
mainGame
->
wOptions
->
setRelativePosition
(
pos
);
mainGame
->
bgOptions
->
setRelativePosition
(
rect
<
s32
>
(
0
,
0
,
(
scrollbar
?
4
0
5
:
390
)
*
mainGame
->
xScale
,
pos
.
LowerRightCorner
.
Y
-
pos
.
UpperLeftCorner
.
Y
));
mainGame
->
bgOptions
->
setRelativePosition
(
rect
<
s32
>
(
0
,
0
,
(
scrollbar
?
4
2
5
:
390
)
*
mainGame
->
xScale
,
pos
.
LowerRightCorner
.
Y
-
pos
.
UpperLeftCorner
.
Y
));
}
else
{
}
else
{
mainGame
->
SetStaticText
(
mainGame
->
stOptions
,
350
*
mainGame
->
xScale
,
mainGame
->
guiFont
,
dataManager
.
GetDesc
(
select_options
[
0
]));
mainGame
->
SetStaticText
(
mainGame
->
stOptions
,
350
*
mainGame
->
xScale
,
mainGame
->
guiFont
,
dataManager
.
GetDesc
(
select_options
[
0
]));
mainGame
->
stOptions
->
setVisible
(
true
);
mainGame
->
stOptions
->
setVisible
(
true
);
...
...
Classes/gframe/game.cpp
View file @
435c57e2
...
@@ -734,7 +734,7 @@ bool Game::Initialize(ANDROID_APP app, android::InitOptions *options) {
...
@@ -734,7 +734,7 @@ bool Game::Initialize(ANDROID_APP app, android::InitOptions *options) {
btnSurrenderNo
=
env
->
addButton
(
Resize
(
200
,
120
,
310
,
170
),
wSurrender
,
BUTTON_SURRENDER_NO
,
dataManager
.
GetSysString
(
1214
));
btnSurrenderNo
=
env
->
addButton
(
Resize
(
200
,
120
,
310
,
170
),
wSurrender
,
BUTTON_SURRENDER_NO
,
dataManager
.
GetSysString
(
1214
));
ChangeToIGUIImageButton
(
btnSurrenderNo
,
imageManager
.
tButton_S
,
imageManager
.
tButton_S_pressed
);
ChangeToIGUIImageButton
(
btnSurrenderNo
,
imageManager
.
tButton_S
,
imageManager
.
tButton_S_pressed
);
//options (350)
//options (350)
wOptions
=
env
->
addWindow
(
Resize
(
470
,
180
,
860
,
3
6
0
),
false
,
L""
);
wOptions
=
env
->
addWindow
(
Resize
(
470
,
180
,
860
,
3
9
0
),
false
,
L""
);
wOptions
->
getCloseButton
()
->
setVisible
(
false
);
wOptions
->
getCloseButton
()
->
setVisible
(
false
);
wOptions
->
setVisible
(
false
);
wOptions
->
setVisible
(
false
);
wOptions
->
setDrawBackground
(
false
);
wOptions
->
setDrawBackground
(
false
);
...
@@ -753,12 +753,12 @@ bool Game::Initialize(ANDROID_APP app, android::InitOptions *options) {
...
@@ -753,12 +753,12 @@ bool Game::Initialize(ANDROID_APP app, android::InitOptions *options) {
btnOption
[
i
]
=
env
->
addButton
(
Resize
(
20
,
20
+
60
*
i
,
370
,
70
+
60
*
i
),
wOptions
,
BUTTON_OPTION_0
+
i
,
L""
);
btnOption
[
i
]
=
env
->
addButton
(
Resize
(
20
,
20
+
60
*
i
,
370
,
70
+
60
*
i
),
wOptions
,
BUTTON_OPTION_0
+
i
,
L""
);
ChangeToIGUIImageButton
(
btnOption
[
i
],
imageManager
.
tButton_L
,
imageManager
.
tButton_L_pressed
);
ChangeToIGUIImageButton
(
btnOption
[
i
],
imageManager
.
tButton_L
,
imageManager
.
tButton_L_pressed
);
}
}
scrOption
=
env
->
addScrollBar
(
false
,
Resize
(
0
,
0
,
0
,
0
),
wOptions
,
SCROLL_OPTION_SELECT
);
scrOption
=
env
->
addScrollBar
(
false
,
Resize
(
380
,
20
,
410
,
31
0
),
wOptions
,
SCROLL_OPTION_SELECT
);
scrOption
->
setLargeStep
(
1
);
scrOption
->
setLargeStep
(
1
);
scrOption
->
setSmallStep
(
1
);
scrOption
->
setSmallStep
(
1
);
scrOption
->
setMin
(
0
);
scrOption
->
setMin
(
0
);
#endif
#endif
//pos
//pos
select
wPosSelect
=
env
->
addWindow
(
recti
(
660
*
xScale
-
223
*
yScale
,
160
*
yScale
,
660
*
xScale
+
223
*
yScale
,
(
160
+
228
)
*
yScale
),
false
,
dataManager
.
GetSysString
(
561
));
wPosSelect
=
env
->
addWindow
(
recti
(
660
*
xScale
-
223
*
yScale
,
160
*
yScale
,
660
*
xScale
+
223
*
yScale
,
(
160
+
228
)
*
yScale
),
false
,
dataManager
.
GetSysString
(
561
));
wPosSelect
->
getCloseButton
()
->
setVisible
(
false
);
wPosSelect
->
getCloseButton
()
->
setVisible
(
false
);
wPosSelect
->
setVisible
(
false
);
wPosSelect
->
setVisible
(
false
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment