Move classes into separate files
FossilOrigin-Name: 14861826d4c1f561aca909afe773366a46b57b20cf41fd668092dfb98d960d80
This commit is contained in:
parent
3661ce9a40
commit
623076a034
17 changed files with 366 additions and 322 deletions
16
meson.build
16
meson.build
|
@ -1,12 +1,14 @@
|
||||||
project('Cube', ['c', 'objcpp'],
|
project('Cube', ['c', 'objc', 'objcpp'],
|
||||||
meson_version: '>=1.5.0')
|
meson_version: '>=1.5.0')
|
||||||
|
|
||||||
add_global_arguments(
|
foreach lang : ['objc', 'objcpp']
|
||||||
[
|
add_global_arguments(
|
||||||
'-fobjc-arc',
|
[
|
||||||
'-fobjc-arc-exceptions'
|
'-fobjc-arc',
|
||||||
],
|
'-fobjc-arc-exceptions'
|
||||||
language: 'objcpp')
|
],
|
||||||
|
language: lang)
|
||||||
|
endforeach
|
||||||
|
|
||||||
objfw_dep = dependency('objfw')
|
objfw_dep = dependency('objfw')
|
||||||
sdl_dep = dependency('SDL2')
|
sdl_dep = dependency('SDL2')
|
||||||
|
|
18
src/Ident.h
Normal file
18
src/Ident.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#import <ObjFW/ObjFW.h>
|
||||||
|
|
||||||
|
OF_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
enum IdentType { ID_VAR, ID_COMMAND, ID_ALIAS };
|
||||||
|
|
||||||
|
@interface Ident : OFObject
|
||||||
|
@property (nonatomic) enum IdentType type;
|
||||||
|
@property (copy, nonatomic) OFString *name;
|
||||||
|
@property (nonatomic) int min, max; // ID_VAR
|
||||||
|
@property (nonatomic) int *storage; // ID_VAR
|
||||||
|
@property (nonatomic) void (*fun)(); // ID_VAR, ID_COMMAND
|
||||||
|
@property (nonatomic) int narg; // ID_VAR, ID_COMMAND
|
||||||
|
@property (copy, nonatomic) OFString *action; // ID_ALIAS
|
||||||
|
@property (nonatomic) bool persist;
|
||||||
|
@end
|
||||||
|
|
||||||
|
OF_ASSUME_NONNULL_END
|
4
src/Ident.m
Normal file
4
src/Ident.m
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#import "Ident.h"
|
||||||
|
|
||||||
|
@implementation Ident
|
||||||
|
@end
|
13
src/KeyMapping.h
Normal file
13
src/KeyMapping.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#import <ObjFW/ObjFW.h>
|
||||||
|
|
||||||
|
OF_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface KeyMapping : OFObject
|
||||||
|
@property (readonly) int code;
|
||||||
|
@property (readonly, nonatomic) OFString *name;
|
||||||
|
@property (copy, nonatomic) OFString *action;
|
||||||
|
|
||||||
|
- (instancetype)initWithCode:(int)code name:(OFString *)name;
|
||||||
|
@end
|
||||||
|
|
||||||
|
OF_ASSUME_NONNULL_END
|
13
src/KeyMapping.m
Normal file
13
src/KeyMapping.m
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#import "KeyMapping.h"
|
||||||
|
|
||||||
|
@implementation KeyMapping
|
||||||
|
- (instancetype)initWithCode:(int)code name:(OFString *)name
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
_code = code;
|
||||||
|
_name = [name copy];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
@end
|
29
src/MD2.h
Normal file
29
src/MD2.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#import <ObjFW/ObjFW.h>
|
||||||
|
|
||||||
|
OF_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@class MapModelInfo;
|
||||||
|
|
||||||
|
@interface MD2 : OFObject
|
||||||
|
@property (nonatomic) MapModelInfo *mmi;
|
||||||
|
@property (copy, nonatomic) OFString *loadname;
|
||||||
|
@property (nonatomic) int mdlnum;
|
||||||
|
@property (nonatomic) bool loaded;
|
||||||
|
|
||||||
|
- (bool)loadWithIRI:(OFIRI *)IRI;
|
||||||
|
- (void)renderWithLight:(OFVector3D &)light
|
||||||
|
frame:(int)frame
|
||||||
|
range:(int)range
|
||||||
|
x:(float)x
|
||||||
|
y:(float)y
|
||||||
|
z:(float)z
|
||||||
|
yaw:(float)yaw
|
||||||
|
pitch:(float)pitch
|
||||||
|
scale:(float)scale
|
||||||
|
speed:(float)speed
|
||||||
|
snap:(int)snap
|
||||||
|
basetime:(int)basetime;
|
||||||
|
- (void)scaleWithFrame:(int)frame scale:(float)scale snap:(int)snap;
|
||||||
|
@end
|
||||||
|
|
||||||
|
OF_ASSUME_NONNULL_END
|
207
src/MD2.mm
Normal file
207
src/MD2.mm
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
#import "MD2.h"
|
||||||
|
|
||||||
|
#include "cube.h"
|
||||||
|
|
||||||
|
struct md2_header {
|
||||||
|
int magic;
|
||||||
|
int version;
|
||||||
|
int skinWidth, skinHeight;
|
||||||
|
int frameSize;
|
||||||
|
int numSkins, numVertices, numTexcoords;
|
||||||
|
int numTriangles, numGlCommands, numFrames;
|
||||||
|
int offsetSkins, offsetTexcoords, offsetTriangles;
|
||||||
|
int offsetFrames, offsetGlCommands, offsetEnd;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct md2_vertex {
|
||||||
|
uchar vertex[3], lightNormalIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct md2_frame {
|
||||||
|
float scale[3];
|
||||||
|
float translate[3];
|
||||||
|
char name[16];
|
||||||
|
md2_vertex vertices[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
@implementation MD2 {
|
||||||
|
int _numGlCommands;
|
||||||
|
int *_glCommands;
|
||||||
|
int _numTriangles;
|
||||||
|
int _frameSize;
|
||||||
|
int _numFrames;
|
||||||
|
int _numVerts;
|
||||||
|
char *_frames;
|
||||||
|
OFVector3D **_mverts;
|
||||||
|
int _displaylist;
|
||||||
|
int _displaylistverts;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
if (_glCommands)
|
||||||
|
delete[] _glCommands;
|
||||||
|
if (_frames)
|
||||||
|
delete[] _frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (bool)loadWithIRI:(OFIRI *)IRI
|
||||||
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
OFSeekableStream *stream;
|
||||||
|
@try {
|
||||||
|
stream = (OFSeekableStream *)[[OFIRIHandler
|
||||||
|
handlerForIRI:IRI] openItemAtIRI:IRI mode:@"r"];
|
||||||
|
} @catch (id e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![stream isKindOfClass:[OFSeekableStream class]])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
md2_header header;
|
||||||
|
[stream readIntoBuffer:&header exactLength:sizeof(md2_header)];
|
||||||
|
endianswap(
|
||||||
|
&header, sizeof(int), sizeof(md2_header) / sizeof(int));
|
||||||
|
|
||||||
|
if (header.magic != 844121161 || header.version != 8)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_frames = new char[header.frameSize * header.numFrames];
|
||||||
|
if (_frames == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
[stream seekToOffset:header.offsetFrames whence:OFSeekSet];
|
||||||
|
[stream readIntoBuffer:_frames
|
||||||
|
exactLength:header.frameSize * header.numFrames];
|
||||||
|
|
||||||
|
for (int i = 0; i < header.numFrames; ++i)
|
||||||
|
endianswap(
|
||||||
|
_frames + i * header.frameSize, sizeof(float), 6);
|
||||||
|
|
||||||
|
_glCommands = new int[header.numGlCommands];
|
||||||
|
if (_glCommands == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
[stream seekToOffset:header.offsetGlCommands whence:OFSeekSet];
|
||||||
|
[stream readIntoBuffer:_glCommands
|
||||||
|
exactLength:header.numGlCommands * sizeof(int)];
|
||||||
|
endianswap(_glCommands, sizeof(int), header.numGlCommands);
|
||||||
|
|
||||||
|
_numFrames = header.numFrames;
|
||||||
|
_numGlCommands = header.numGlCommands;
|
||||||
|
_frameSize = header.frameSize;
|
||||||
|
_numTriangles = header.numTriangles;
|
||||||
|
_numVerts = header.numVertices;
|
||||||
|
|
||||||
|
[stream close];
|
||||||
|
|
||||||
|
_mverts = new OFVector3D *[_numFrames];
|
||||||
|
loopj(_numFrames) _mverts[j] = NULL;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
snap(int sn, float f)
|
||||||
|
{
|
||||||
|
return sn ? (float)(((int)(f + sn * 0.5f)) & (~(sn - 1))) : f;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)scaleWithFrame:(int)frame scale:(float)scale snap:(int)sn
|
||||||
|
{
|
||||||
|
_mverts[frame] = new OFVector3D[_numVerts];
|
||||||
|
md2_frame *cf = (md2_frame *)((char *)_frames + _frameSize * frame);
|
||||||
|
float sc = 16.0f / scale;
|
||||||
|
loop(vi, _numVerts)
|
||||||
|
{
|
||||||
|
uchar *cv = (uchar *)&cf->vertices[vi].vertex;
|
||||||
|
OFVector3D *v = &(_mverts[frame])[vi];
|
||||||
|
v->x = (snap(sn, cv[0] * cf->scale[0]) + cf->translate[0]) / sc;
|
||||||
|
v->y =
|
||||||
|
-(snap(sn, cv[1] * cf->scale[1]) + cf->translate[1]) / sc;
|
||||||
|
v->z = (snap(sn, cv[2] * cf->scale[2]) + cf->translate[2]) / sc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)renderWithLight:(OFVector3D &)light
|
||||||
|
frame:(int)frame
|
||||||
|
range:(int)range
|
||||||
|
x:(float)x
|
||||||
|
y:(float)y
|
||||||
|
z:(float)z
|
||||||
|
yaw:(float)yaw
|
||||||
|
pitch:(float)pitch
|
||||||
|
scale:(float)sc
|
||||||
|
speed:(float)speed
|
||||||
|
snap:(int)sn
|
||||||
|
basetime:(int)basetime
|
||||||
|
{
|
||||||
|
loopi(range) if (!_mverts[frame + i])[self scaleWithFrame:frame + i
|
||||||
|
scale:sc
|
||||||
|
snap:sn];
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(x, y, z);
|
||||||
|
glRotatef(yaw + 180, 0, -1, 0);
|
||||||
|
glRotatef(pitch, 0, 0, 1);
|
||||||
|
|
||||||
|
glColor3fv((float *)&light);
|
||||||
|
|
||||||
|
if (_displaylist && frame == 0 && range == 1) {
|
||||||
|
glCallList(_displaylist);
|
||||||
|
xtraverts += _displaylistverts;
|
||||||
|
} else {
|
||||||
|
if (frame == 0 && range == 1) {
|
||||||
|
static int displaylistn = 10;
|
||||||
|
glNewList(_displaylist = displaylistn++, GL_COMPILE);
|
||||||
|
_displaylistverts = xtraverts;
|
||||||
|
}
|
||||||
|
|
||||||
|
int time = lastmillis - basetime;
|
||||||
|
int fr1 = (int)(time / speed);
|
||||||
|
float frac1 = (time - fr1 * speed) / speed;
|
||||||
|
float frac2 = 1 - frac1;
|
||||||
|
fr1 = fr1 % range + frame;
|
||||||
|
int fr2 = fr1 + 1;
|
||||||
|
if (fr2 >= frame + range)
|
||||||
|
fr2 = frame;
|
||||||
|
OFVector3D *verts1 = _mverts[fr1];
|
||||||
|
OFVector3D *verts2 = _mverts[fr2];
|
||||||
|
|
||||||
|
for (int *command = _glCommands; (*command) != 0;) {
|
||||||
|
int numVertex = *command++;
|
||||||
|
if (numVertex > 0) {
|
||||||
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
|
} else {
|
||||||
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
|
numVertex = -numVertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
loopi(numVertex)
|
||||||
|
{
|
||||||
|
float tu = *((float *)command++);
|
||||||
|
float tv = *((float *)command++);
|
||||||
|
glTexCoord2f(tu, tv);
|
||||||
|
int vn = *command++;
|
||||||
|
OFVector3D &v1 = verts1[vn];
|
||||||
|
OFVector3D &v2 = verts2[vn];
|
||||||
|
#define ip(c) v1.c *frac2 + v2.c *frac1
|
||||||
|
glVertex3f(ip(x), ip(z), ip(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
xtraverts += numVertex;
|
||||||
|
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_displaylist) {
|
||||||
|
glEndList();
|
||||||
|
_displaylistverts = xtraverts - _displaylistverts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
@end
|
16
src/MapModelInfo.h
Normal file
16
src/MapModelInfo.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#import <ObjFW/ObjFW.h>
|
||||||
|
|
||||||
|
OF_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface MapModelInfo : OFObject
|
||||||
|
@property (nonatomic) int rad, h, zoff, snap;
|
||||||
|
@property (copy, nonatomic) OFString *name;
|
||||||
|
|
||||||
|
- (instancetype)initWithRad:(int)rad
|
||||||
|
h:(int)h
|
||||||
|
zoff:(int)zoff
|
||||||
|
snap:(int)snap
|
||||||
|
name:(OFString *)name;
|
||||||
|
@end
|
||||||
|
|
||||||
|
OF_ASSUME_NONNULL_END
|
20
src/MapModelInfo.m
Normal file
20
src/MapModelInfo.m
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#import "MapModelInfo.h"
|
||||||
|
|
||||||
|
@implementation MapModelInfo
|
||||||
|
- (instancetype)initWithRad:(int)rad
|
||||||
|
h:(int)h
|
||||||
|
zoff:(int)zoff
|
||||||
|
snap:(int)snap
|
||||||
|
name:(OFString *)name
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
_rad = rad;
|
||||||
|
_h = h;
|
||||||
|
_zoff = zoff;
|
||||||
|
_snap = snap;
|
||||||
|
_name = [name copy];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
@end
|
|
@ -5,21 +5,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
enum { ID_VAR, ID_COMMAND, ID_ALIAS };
|
#import "Ident.h"
|
||||||
|
|
||||||
@interface Ident : OFObject
|
|
||||||
@property (nonatomic) int type; // one of ID_* above
|
|
||||||
@property (copy, nonatomic) OFString *name;
|
|
||||||
@property (nonatomic) int min, max; // ID_VAR
|
|
||||||
@property (nonatomic) int *storage; // ID_VAR
|
|
||||||
@property (nonatomic) void (*fun)(); // ID_VAR, ID_COMMAND
|
|
||||||
@property (nonatomic) int narg; // ID_VAR, ID_COMMAND
|
|
||||||
@property (copy, nonatomic) OFString *action; // ID_ALIAS
|
|
||||||
@property (nonatomic) bool persist;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation Ident
|
|
||||||
@end
|
|
||||||
|
|
||||||
void
|
void
|
||||||
itoa(char *s, int i)
|
itoa(char *s, int i)
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#import "KeyMapping.h"
|
||||||
|
|
||||||
struct cline {
|
struct cline {
|
||||||
char *cref;
|
char *cref;
|
||||||
int outtime;
|
int outtime;
|
||||||
|
@ -93,26 +95,6 @@ renderconsole() // render buffer taking into account time & scrolling
|
||||||
|
|
||||||
// keymap is defined externally in keymap.cfg
|
// keymap is defined externally in keymap.cfg
|
||||||
|
|
||||||
@interface KeyMapping : OFObject
|
|
||||||
@property (readonly) int code;
|
|
||||||
@property (readonly, nonatomic) OFString *name;
|
|
||||||
@property (copy, nonatomic) OFString *action;
|
|
||||||
|
|
||||||
- (instancetype)initWithCode:(int)code name:(OFString *)name;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation KeyMapping
|
|
||||||
- (instancetype)initWithCode:(int)code name:(OFString *)name
|
|
||||||
{
|
|
||||||
self = [super init];
|
|
||||||
|
|
||||||
_code = code;
|
|
||||||
_name = [name copy];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
static OFMutableArray<KeyMapping *> *keyMappings = nil;
|
static OFMutableArray<KeyMapping *> *keyMappings = nil;
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
11
src/cube.h
11
src/cube.h
|
@ -115,17 +115,6 @@ struct block {
|
||||||
int x, y, xs, ys;
|
int x, y, xs, ys;
|
||||||
};
|
};
|
||||||
|
|
||||||
@interface MapModelInfo : OFObject
|
|
||||||
@property (nonatomic) int rad, h, zoff, snap;
|
|
||||||
@property (copy, nonatomic) OFString *name;
|
|
||||||
|
|
||||||
- (instancetype)initWithRad:(int)rad
|
|
||||||
h:(int)h
|
|
||||||
zoff:(int)zoff
|
|
||||||
snap:(int)snap
|
|
||||||
name:(OFString *)name;
|
|
||||||
@end
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
GUN_FIST = 0,
|
GUN_FIST = 0,
|
||||||
GUN_SG,
|
GUN_SG,
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
|
#import "MapModelInfo.h"
|
||||||
|
|
||||||
vector<entity> ents;
|
vector<entity> ents;
|
||||||
|
|
||||||
static OFString *entmdlnames[] = {
|
static OFString *entmdlnames[] = {
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
executable('client',
|
executable('client',
|
||||||
[
|
[
|
||||||
'Cube.mm',
|
'Cube.mm',
|
||||||
|
'Ident.m',
|
||||||
|
'KeyMapping.m',
|
||||||
|
'MD2.mm',
|
||||||
|
'MapModelInfo.m',
|
||||||
'client.mm',
|
'client.mm',
|
||||||
'clientextras.mm',
|
'clientextras.mm',
|
||||||
'clientgame.mm',
|
'clientgame.mm',
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
|
#import "MapModelInfo.h"
|
||||||
|
|
||||||
bool
|
bool
|
||||||
plcollide(dynent *d, dynent *o, float &headspace, float &hi,
|
plcollide(dynent *d, dynent *o, float &headspace, float &hi,
|
||||||
float &lo) // collide with player or monster
|
float &lo) // collide with player or monster
|
||||||
|
|
|
@ -210,6 +210,7 @@ extern void cleansound();
|
||||||
extern void rendermodel(OFString *mdl, int frame, int range, int tex, float rad,
|
extern void rendermodel(OFString *mdl, int frame, int range, int tex, float rad,
|
||||||
float x, float y, float z, float yaw, float pitch, bool teammate,
|
float x, float y, float z, float yaw, float pitch, bool teammate,
|
||||||
float scale, float speed, int snap = 0, int basetime = 0);
|
float scale, float speed, int snap = 0, int basetime = 0);
|
||||||
|
@class MapModelInfo;
|
||||||
extern MapModelInfo *getmminfo(int i);
|
extern MapModelInfo *getmminfo(int i);
|
||||||
|
|
||||||
// server
|
// server
|
||||||
|
|
294
src/rendermd2.mm
294
src/rendermd2.mm
|
@ -2,244 +2,13 @@
|
||||||
|
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
struct md2_header {
|
#import "MD2.h"
|
||||||
int magic;
|
#import "MapModelInfo.h"
|
||||||
int version;
|
|
||||||
int skinWidth, skinHeight;
|
|
||||||
int frameSize;
|
|
||||||
int numSkins, numVertices, numTexcoords;
|
|
||||||
int numTriangles, numGlCommands, numFrames;
|
|
||||||
int offsetSkins, offsetTexcoords, offsetTriangles;
|
|
||||||
int offsetFrames, offsetGlCommands, offsetEnd;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct md2_vertex {
|
|
||||||
uchar vertex[3], lightNormalIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct md2_frame {
|
|
||||||
float scale[3];
|
|
||||||
float translate[3];
|
|
||||||
char name[16];
|
|
||||||
md2_vertex vertices[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
@interface MD2 : OFObject {
|
|
||||||
int _numGlCommands;
|
|
||||||
int *_glCommands;
|
|
||||||
int _numTriangles;
|
|
||||||
int _frameSize;
|
|
||||||
int _numFrames;
|
|
||||||
int _numVerts;
|
|
||||||
char *_frames;
|
|
||||||
OFVector3D **_mverts;
|
|
||||||
int _displaylist;
|
|
||||||
int _displaylistverts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property (nonatomic) MapModelInfo *mmi;
|
|
||||||
@property (copy, nonatomic) OFString *loadname;
|
|
||||||
@property (nonatomic) int mdlnum;
|
|
||||||
@property (nonatomic) bool loaded;
|
|
||||||
|
|
||||||
- (bool)loadWithIRI:(OFIRI *)IRI;
|
|
||||||
- (void)renderWithLight:(OFVector3D &)light
|
|
||||||
frame:(int)frame
|
|
||||||
range:(int)range
|
|
||||||
x:(float)x
|
|
||||||
y:(float)y
|
|
||||||
z:(float)z
|
|
||||||
yaw:(float)yaw
|
|
||||||
pitch:(float)pitch
|
|
||||||
scale:(float)scale
|
|
||||||
speed:(float)speed
|
|
||||||
snap:(int)snap
|
|
||||||
basetime:(int)basetime;
|
|
||||||
- (void)scaleWithFrame:(int)frame scale:(float)scale snap:(int)snap;
|
|
||||||
@end
|
|
||||||
|
|
||||||
static OFMutableDictionary<OFString *, MD2 *> *mdllookup = nil;
|
static OFMutableDictionary<OFString *, MD2 *> *mdllookup = nil;
|
||||||
static OFMutableArray<MD2 *> *mapmodels = nil;
|
static OFMutableArray<MD2 *> *mapmodels = nil;
|
||||||
|
|
||||||
@implementation MD2
|
static const int FIRSTMDL = 20;
|
||||||
+ (void)initialize
|
|
||||||
{
|
|
||||||
if (self != [MD2 class])
|
|
||||||
return;
|
|
||||||
|
|
||||||
mdllookup = [[OFMutableDictionary alloc] init];
|
|
||||||
mapmodels = [[OFMutableArray alloc] init];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc
|
|
||||||
{
|
|
||||||
if (_glCommands)
|
|
||||||
delete[] _glCommands;
|
|
||||||
if (_frames)
|
|
||||||
delete[] _frames;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (bool)loadWithIRI:(OFIRI *)IRI
|
|
||||||
{
|
|
||||||
@autoreleasepool {
|
|
||||||
OFSeekableStream *stream;
|
|
||||||
@try {
|
|
||||||
stream = (OFSeekableStream *)[[OFIRIHandler
|
|
||||||
handlerForIRI:IRI] openItemAtIRI:IRI mode:@"r"];
|
|
||||||
} @catch (id e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (![stream isKindOfClass:[OFSeekableStream class]])
|
|
||||||
return false;
|
|
||||||
|
|
||||||
md2_header header;
|
|
||||||
[stream readIntoBuffer:&header exactLength:sizeof(md2_header)];
|
|
||||||
endianswap(
|
|
||||||
&header, sizeof(int), sizeof(md2_header) / sizeof(int));
|
|
||||||
|
|
||||||
if (header.magic != 844121161 || header.version != 8)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_frames = new char[header.frameSize * header.numFrames];
|
|
||||||
if (_frames == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
[stream seekToOffset:header.offsetFrames whence:OFSeekSet];
|
|
||||||
[stream readIntoBuffer:_frames
|
|
||||||
exactLength:header.frameSize * header.numFrames];
|
|
||||||
|
|
||||||
for (int i = 0; i < header.numFrames; ++i)
|
|
||||||
endianswap(
|
|
||||||
_frames + i * header.frameSize, sizeof(float), 6);
|
|
||||||
|
|
||||||
_glCommands = new int[header.numGlCommands];
|
|
||||||
if (_glCommands == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
[stream seekToOffset:header.offsetGlCommands whence:OFSeekSet];
|
|
||||||
[stream readIntoBuffer:_glCommands
|
|
||||||
exactLength:header.numGlCommands * sizeof(int)];
|
|
||||||
endianswap(_glCommands, sizeof(int), header.numGlCommands);
|
|
||||||
|
|
||||||
_numFrames = header.numFrames;
|
|
||||||
_numGlCommands = header.numGlCommands;
|
|
||||||
_frameSize = header.frameSize;
|
|
||||||
_numTriangles = header.numTriangles;
|
|
||||||
_numVerts = header.numVertices;
|
|
||||||
|
|
||||||
[stream close];
|
|
||||||
|
|
||||||
_mverts = new OFVector3D *[_numFrames];
|
|
||||||
loopj(_numFrames) _mverts[j] = NULL;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
|
||||||
snap(int sn, float f)
|
|
||||||
{
|
|
||||||
return sn ? (float)(((int)(f + sn * 0.5f)) & (~(sn - 1))) : f;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)scaleWithFrame:(int)frame scale:(float)scale snap:(int)sn
|
|
||||||
{
|
|
||||||
_mverts[frame] = new OFVector3D[_numVerts];
|
|
||||||
md2_frame *cf = (md2_frame *)((char *)_frames + _frameSize * frame);
|
|
||||||
float sc = 16.0f / scale;
|
|
||||||
loop(vi, _numVerts)
|
|
||||||
{
|
|
||||||
uchar *cv = (uchar *)&cf->vertices[vi].vertex;
|
|
||||||
OFVector3D *v = &(_mverts[frame])[vi];
|
|
||||||
v->x = (snap(sn, cv[0] * cf->scale[0]) + cf->translate[0]) / sc;
|
|
||||||
v->y =
|
|
||||||
-(snap(sn, cv[1] * cf->scale[1]) + cf->translate[1]) / sc;
|
|
||||||
v->z = (snap(sn, cv[2] * cf->scale[2]) + cf->translate[2]) / sc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)renderWithLight:(OFVector3D &)light
|
|
||||||
frame:(int)frame
|
|
||||||
range:(int)range
|
|
||||||
x:(float)x
|
|
||||||
y:(float)y
|
|
||||||
z:(float)z
|
|
||||||
yaw:(float)yaw
|
|
||||||
pitch:(float)pitch
|
|
||||||
scale:(float)sc
|
|
||||||
speed:(float)speed
|
|
||||||
snap:(int)sn
|
|
||||||
basetime:(int)basetime
|
|
||||||
{
|
|
||||||
loopi(range) if (!_mverts[frame + i])[self scaleWithFrame:frame + i
|
|
||||||
scale:sc
|
|
||||||
snap:sn];
|
|
||||||
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(x, y, z);
|
|
||||||
glRotatef(yaw + 180, 0, -1, 0);
|
|
||||||
glRotatef(pitch, 0, 0, 1);
|
|
||||||
|
|
||||||
glColor3fv((float *)&light);
|
|
||||||
|
|
||||||
if (_displaylist && frame == 0 && range == 1) {
|
|
||||||
glCallList(_displaylist);
|
|
||||||
xtraverts += _displaylistverts;
|
|
||||||
} else {
|
|
||||||
if (frame == 0 && range == 1) {
|
|
||||||
static int displaylistn = 10;
|
|
||||||
glNewList(_displaylist = displaylistn++, GL_COMPILE);
|
|
||||||
_displaylistverts = xtraverts;
|
|
||||||
}
|
|
||||||
|
|
||||||
int time = lastmillis - basetime;
|
|
||||||
int fr1 = (int)(time / speed);
|
|
||||||
float frac1 = (time - fr1 * speed) / speed;
|
|
||||||
float frac2 = 1 - frac1;
|
|
||||||
fr1 = fr1 % range + frame;
|
|
||||||
int fr2 = fr1 + 1;
|
|
||||||
if (fr2 >= frame + range)
|
|
||||||
fr2 = frame;
|
|
||||||
OFVector3D *verts1 = _mverts[fr1];
|
|
||||||
OFVector3D *verts2 = _mverts[fr2];
|
|
||||||
|
|
||||||
for (int *command = _glCommands; (*command) != 0;) {
|
|
||||||
int numVertex = *command++;
|
|
||||||
if (numVertex > 0) {
|
|
||||||
glBegin(GL_TRIANGLE_STRIP);
|
|
||||||
} else {
|
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
|
||||||
numVertex = -numVertex;
|
|
||||||
}
|
|
||||||
|
|
||||||
loopi(numVertex)
|
|
||||||
{
|
|
||||||
float tu = *((float *)command++);
|
|
||||||
float tv = *((float *)command++);
|
|
||||||
glTexCoord2f(tu, tv);
|
|
||||||
int vn = *command++;
|
|
||||||
OFVector3D &v1 = verts1[vn];
|
|
||||||
OFVector3D &v2 = verts2[vn];
|
|
||||||
#define ip(c) v1.c *frac2 + v2.c *frac1
|
|
||||||
glVertex3f(ip(x), ip(z), ip(y));
|
|
||||||
}
|
|
||||||
|
|
||||||
xtraverts += numVertex;
|
|
||||||
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_displaylist) {
|
|
||||||
glEndList();
|
|
||||||
_displaylistverts = xtraverts - _displaylistverts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glPopMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
const int FIRSTMDL = 20;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
delayedload(MD2 *m)
|
delayedload(MD2 *m)
|
||||||
|
@ -265,25 +34,30 @@ delayedload(MD2 *m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int modelnum = 0;
|
|
||||||
|
|
||||||
MD2 *
|
MD2 *
|
||||||
loadmodel(OFString *name)
|
loadmodel(OFString *name)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
static int modelnum = 0;
|
||||||
|
|
||||||
MD2 *m = mdllookup[name];
|
MD2 *m = mdllookup[name];
|
||||||
if (m != nil)
|
if (m != nil)
|
||||||
return m;
|
return m;
|
||||||
|
|
||||||
m = [[MD2 alloc] init];
|
m = [[MD2 alloc] init];
|
||||||
m.mdlnum = modelnum++;
|
m.mdlnum = modelnum++;
|
||||||
MapModelInfo *mmi = [[MapModelInfo alloc] initWithRad:2
|
m.mmi = [[MapModelInfo alloc] initWithRad:2
|
||||||
h:2
|
h:2
|
||||||
zoff:0
|
zoff:0
|
||||||
snap:0
|
snap:0
|
||||||
name:@""];
|
name:@""];
|
||||||
m.mmi = mmi;
|
|
||||||
m.loadname = name;
|
m.loadname = name;
|
||||||
|
|
||||||
|
if (mdllookup == nil)
|
||||||
|
mdllookup = [[OFMutableDictionary alloc] init];
|
||||||
|
|
||||||
mdllookup[name] = m;
|
mdllookup[name] = m;
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,13 +67,15 @@ mapmodel(
|
||||||
OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name)
|
OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name)
|
||||||
{
|
{
|
||||||
MD2 *m = loadmodel(name);
|
MD2 *m = loadmodel(name);
|
||||||
MapModelInfo *mmi =
|
m.mmi = [[MapModelInfo alloc] initWithRad:(int)rad.longLongValue
|
||||||
[[MapModelInfo alloc] initWithRad:(int)rad.longLongValue
|
h:(int)h.longLongValue
|
||||||
h:(int)h.longLongValue
|
zoff:(int)zoff.longLongValue
|
||||||
zoff:(int)zoff.longLongValue
|
snap:(int)snap.longLongValue
|
||||||
snap:(int)snap.longLongValue
|
name:m.loadname];
|
||||||
name:m.loadname];
|
|
||||||
m.mmi = mmi;
|
if (mapmodels == nil)
|
||||||
|
mapmodels = [[OFMutableArray alloc] init];
|
||||||
|
|
||||||
[mapmodels addObject:m];
|
[mapmodels addObject:m];
|
||||||
}
|
}
|
||||||
COMMAND(mapmodel, ARG_5STR)
|
COMMAND(mapmodel, ARG_5STR)
|
||||||
|
@ -365,23 +141,3 @@ rendermodel(OFString *mdl, int frame, int range, int tex, float rad, float x,
|
||||||
snap:snap
|
snap:snap
|
||||||
basetime:basetime];
|
basetime:basetime];
|
||||||
}
|
}
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation MapModelInfo
|
|
||||||
- (instancetype)initWithRad:(int)rad
|
|
||||||
h:(int)h
|
|
||||||
zoff:(int)zoff
|
|
||||||
snap:(int)snap
|
|
||||||
name:(OFString *)name
|
|
||||||
{
|
|
||||||
self = [super init];
|
|
||||||
|
|
||||||
_rad = rad;
|
|
||||||
_h = h;
|
|
||||||
_zoff = zoff;
|
|
||||||
_snap = snap;
|
|
||||||
_name = [name copy];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue