merged in rich's demo
This was SVN commit r236.
This commit is contained in:
parent
fb8ea69062
commit
fbba2e463d
@ -96,13 +96,14 @@ static int mk_native_path(const char* const path, char* const n_path)
|
||||
}
|
||||
|
||||
|
||||
// rationale for data dir being root:
|
||||
// xxxxxxxx yyyyyyyyy zzzzzzzzzz sandbox; vfs users (untrusted scripts) can't overwrite critical game files
|
||||
// rationale for data dir being root: untrusted scripts must not be allowed
|
||||
// to overwrite critical game (or worse, OS) files. the VFS prevents any
|
||||
// accesses to files above this directory.
|
||||
int file_set_root_dir(const char* argv0, const char* root_dir)
|
||||
{
|
||||
// security check: only allow attempting to set root dir once
|
||||
// (prevents malicious scripts from overwriting important files
|
||||
// above the intended VFS root)
|
||||
// (this is called early at startup, so any subsequent
|
||||
// call is most likely malicious).
|
||||
static bool already_attempted;
|
||||
if(already_attempted)
|
||||
{
|
||||
@ -131,10 +132,10 @@ int file_set_root_dir(const char* argv0, const char* root_dir)
|
||||
if(chdir(path) < 0)
|
||||
return -errno;
|
||||
|
||||
char* native_root = path; // reuse path[] (no longer needed)
|
||||
CHECK_ERR(mk_native_path(root_dir, native_root));
|
||||
char* n_root = path; // reuse path[] (no longer needed)
|
||||
CHECK_ERR(mk_native_path(root_dir, n_root));
|
||||
|
||||
if(chdir(native_root) < 0)
|
||||
if(chdir(n_root) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
@ -148,25 +149,26 @@ int file_set_root_dir(const char* argv0, const char* root_dir)
|
||||
// need to store entries returned by readdir so they can be sorted.
|
||||
struct DirEnt
|
||||
{
|
||||
std::string name;
|
||||
uint flags;
|
||||
ssize_t size;
|
||||
const std::string name;
|
||||
const uint flags;
|
||||
const ssize_t size;
|
||||
|
||||
DirEnt(const char* _name, uint _flags, ssize_t _size)
|
||||
DirEnt(const char* const _name, const uint _flags, const ssize_t _size)
|
||||
: name(_name), flags(_flags), size(_size) {}
|
||||
};
|
||||
|
||||
typedef std::vector<DirEnt> DirEnts;
|
||||
typedef DirEnts::iterator DirEntsIt;
|
||||
typedef std::vector<const DirEnt*> DirEnts;
|
||||
typedef DirEnts::const_iterator DirEntIt;
|
||||
|
||||
static bool dirent_less(DirEnt& d1, DirEnt& d2)
|
||||
{ return d1.name.compare(d2.name) < 0; }
|
||||
static bool dirent_less(const DirEnt* const d1, const DirEnt* const d2)
|
||||
{ return d1->name.compare(d2->name) < 0; }
|
||||
|
||||
// rationale: we pass the directory entry name only to the callback -
|
||||
// not the absolute path, nor <dir> prepended. some users don't need it,
|
||||
// and would need to strip it. this routine generates the absolute path,
|
||||
// but in native form - can't use that.
|
||||
int file_enum(const char* dir, FileCB cb, uintptr_t user)
|
||||
// we give the callback the directory-entry-name only - not the
|
||||
// absolute path, nor <dir> prepended. rationale: some users don't need it,
|
||||
// and would need to strip it. there are not enough users requiring it to
|
||||
// justify that. this routine does actually generate the absolute path
|
||||
// for use with stat, but in native form - can't use that.
|
||||
int file_enum(const char* const dir, const FileCB cb, const uintptr_t user)
|
||||
{
|
||||
char n_path[PATH_MAX+1];
|
||||
n_path[PATH_MAX] = '\0';
|
||||
@ -174,14 +176,15 @@ int file_enum(const char* dir, FileCB cb, uintptr_t user)
|
||||
// 0-terminate simplifies filename strncpy below.
|
||||
CHECK_ERR(mk_native_path(dir, n_path));
|
||||
|
||||
// all entries are enumerated (adding to list), sorted, then passed to cb
|
||||
// all entries are enumerated (adding to this container),
|
||||
// std::sort-ed, then all passed to cb.
|
||||
DirEnts dirents;
|
||||
|
||||
int stat_err = 0;
|
||||
int cb_err = 0;
|
||||
int ret;
|
||||
|
||||
DIR* os_dir = opendir(n_path);
|
||||
DIR* const os_dir = opendir(n_path);
|
||||
if(!os_dir)
|
||||
return -1;
|
||||
|
||||
@ -190,15 +193,19 @@ int file_enum(const char* dir, FileCB cb, uintptr_t user)
|
||||
char* fn_start = n_path + n_path_len;
|
||||
*fn_start++ = DIR_SEP;
|
||||
|
||||
struct dirent* ent;
|
||||
while((ent = readdir(os_dir)))
|
||||
struct dirent* os_ent;
|
||||
while((os_ent = readdir(os_dir)))
|
||||
{
|
||||
const char* fn = ent->d_name;
|
||||
const char* fn = os_ent->d_name;
|
||||
|
||||
strncpy(fn_start, fn, PATH_MAX-n_path_len);
|
||||
// stat needs the relative path. this is easier than changing
|
||||
// stat needs the full path. this is easier than changing
|
||||
// directory every time, and should be fast enough.
|
||||
// BTW, direct strcpy is faster than path_append -
|
||||
// we save a strlen every iteration.
|
||||
|
||||
// no need to go through file_stat -
|
||||
// we already have the native path.
|
||||
struct stat s;
|
||||
ret = stat(n_path, &s);
|
||||
if(ret < 0)
|
||||
@ -225,23 +232,29 @@ int file_enum(const char* dir, FileCB cb, uintptr_t user)
|
||||
else if(!(s.st_mode & S_IFREG))
|
||||
continue;
|
||||
|
||||
dirents.push_back(DirEnt(fn, flags, size));
|
||||
const DirEnt* const ent = new DirEnt(fn, flags, size);
|
||||
dirents.push_back(ent);
|
||||
}
|
||||
closedir(os_dir);
|
||||
|
||||
std::sort(dirents.begin(), dirents.end(), dirent_less);
|
||||
|
||||
for(DirEntsIt it = dirents.begin(); it != dirents.end(); ++it)
|
||||
DirEntIt it;
|
||||
for(it = dirents.begin(); it != dirents.end(); ++it)
|
||||
{
|
||||
const char* name_c = it->name.c_str();
|
||||
const uint flags = it->flags;
|
||||
const ssize_t size = it->size;
|
||||
const DirEnt* const ent = *it;
|
||||
const char* name_c = ent->name.c_str();
|
||||
const uint flags = ent->flags;
|
||||
const ssize_t size = ent->size;
|
||||
ret = cb(name_c, flags, size, user);
|
||||
if(ret < 0)
|
||||
if(cb_err == 0)
|
||||
cb_err = ret;
|
||||
}
|
||||
|
||||
for(it = dirents.begin(); it != dirents.end(); ++it)
|
||||
delete *it;
|
||||
|
||||
if(cb_err < 0)
|
||||
return cb_err;
|
||||
return stat_err;
|
||||
@ -832,7 +845,7 @@ Handle file_start_io(File* f, size_t user_ofs, size_t user_size, void* user_p)
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t bytes_left = f->size - user_ofs; // > 0
|
||||
const size_t bytes_left = f->size - user_ofs; // > 0
|
||||
int op = (f->flags & FILE_WRITE)? LIO_WRITE : LIO_READ;
|
||||
|
||||
// don't read beyond EOF
|
||||
@ -841,6 +854,7 @@ Handle file_start_io(File* f, size_t user_ofs, size_t user_size, void* user_p)
|
||||
|
||||
|
||||
u64 block_id = block_make_id(f->fn_hash, user_ofs);
|
||||
// reset to 0 if transferring more than 1 block.
|
||||
|
||||
// allocate IO slot
|
||||
Handle hio = io_alloc();
|
||||
@ -852,8 +866,9 @@ Handle file_start_io(File* f, size_t user_ofs, size_t user_size, void* user_p)
|
||||
// notes: io->cached, io->pending and io->block are already zeroed;
|
||||
// cb will receive the actual IO request (aligned offset and size).
|
||||
|
||||
|
||||
#ifdef PARANOIA
|
||||
debug_out("file_start_io hio=%I64x ofs=%d size=%d\n", hio, user_ofs, user_size);
|
||||
#endif
|
||||
|
||||
// aio already safely handles unaligned buffers or offsets.
|
||||
// when reading zip files, we don't want to repeat a read
|
||||
@ -875,7 +890,9 @@ debug_out("file_start_io hio=%I64x ofs=%d size=%d\n", hio, user_ofs, user_size);
|
||||
// if already cached, we're done
|
||||
if(size == BLOCK_SIZE && block_retrieve(block_id, io->block) == 0)
|
||||
{
|
||||
debug_out("file_start_io: cached! block # = %d\n", block_id & 0xffffffff);
|
||||
#ifdef PARANOIA
|
||||
debug_out("file_start_io: cached! block # = %d\n", block_id & 0xffffffff);
|
||||
#endif
|
||||
io->cached = 1;
|
||||
return hio;
|
||||
}
|
||||
@ -922,7 +939,9 @@ fail:
|
||||
|
||||
int file_wait_io(const Handle hio, void*& p, size_t& size)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
debug_out("file_wait_io: hio=%I64x\n", hio);
|
||||
#endif
|
||||
|
||||
int ret = 0;
|
||||
|
||||
@ -1003,7 +1022,9 @@ int file_discard_io(Handle& hio)
|
||||
ssize_t file_io(File* const f, const size_t raw_ofs, size_t raw_size, void** const p,
|
||||
const FILE_IO_CB cb, const uintptr_t ctx) // optional
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs);
|
||||
#endif
|
||||
|
||||
CHECK_FILE(f)
|
||||
|
||||
@ -1100,8 +1121,6 @@ debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs);
|
||||
const int MAX_IOS = 2;
|
||||
Handle ios[MAX_IOS] = { 0 };
|
||||
|
||||
if(ios[0] || ios[1])abort();
|
||||
|
||||
int head = 0;
|
||||
int tail = 0;
|
||||
int pending_ios = 0;
|
||||
@ -1119,11 +1138,6 @@ if(ios[0] || ios[1])abort();
|
||||
ssize_t err = +1; // loop terminates if <= 0
|
||||
|
||||
|
||||
static int seq;
|
||||
seq++;
|
||||
if(seq == 4)
|
||||
seq=4;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// queue not full, data remaining to transfer, and no error:
|
||||
|
@ -883,21 +883,30 @@ Handle vfs_open(const char* fn, uint flags /* = 0 */)
|
||||
Handle h = h_alloc(H_VFile, fn, 0, flags);
|
||||
// pass file flags to init
|
||||
|
||||
#ifdef PARANOIA
|
||||
debug_out("vfs_open fn=%s %I64x\n", fn, h);
|
||||
return h;
|
||||
#endif
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
inline int vfs_close(Handle& h)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
debug_out("vfs_close %I64x\n", h);
|
||||
#endif
|
||||
|
||||
return h_free(h, H_VFile);
|
||||
}
|
||||
|
||||
|
||||
ssize_t vfs_io(Handle hf, size_t ofs, size_t size, void*& p)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
debug_out("vfs_io ofs=%d size=%d\n", ofs, size);
|
||||
#endif
|
||||
|
||||
H_DEREF(hf, VFile, vf);
|
||||
|
||||
// (vfs_open makes sure it's not opened for writing if zip)
|
||||
@ -913,7 +922,10 @@ debug_out("vfs_io ofs=%d size=%d\n", ofs, size);
|
||||
|
||||
Handle vfs_load(const char* fn, void*& p, size_t& size)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
debug_out("vfs_load fn=%s\n", fn);
|
||||
#endif
|
||||
|
||||
p = 0; // vfs_io needs initial 0 value
|
||||
size = 0; // in case open or deref fails
|
||||
|
||||
|
@ -164,9 +164,9 @@ static inline void pre_main_init()
|
||||
|
||||
atexit(at_exit);
|
||||
|
||||
// real SDL will do this as well. no matter.
|
||||
// ignore BoundsChecker warning here.
|
||||
freopen("stdout.txt", "wt", stdout);
|
||||
// no point redirecting stdout yet - the current directory
|
||||
// may be incorrect (file_set_root not yet called).
|
||||
// (w)sdl will take care of it anyway.
|
||||
}
|
||||
|
||||
|
||||
|
@ -366,6 +366,16 @@ int SDL_GL_SetAttribute(SDL_GLattr attr, int value)
|
||||
}
|
||||
|
||||
|
||||
int SDL_Init(Uint32 flags)
|
||||
{
|
||||
FILE* const ret = freopen("stdout.txt", "w", stdout);
|
||||
if(!ret)
|
||||
debug_warn("SDL_Init freopen failed");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set video mode wxh:bpp if necessary.
|
||||
* w = h = bpp = 0 => no change.
|
||||
|
@ -14,12 +14,17 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define Uint32 u32
|
||||
|
||||
/* SDL_Init flags */
|
||||
#define SDL_INIT_VIDEO 0
|
||||
#define SDL_INIT_AUDIO 0
|
||||
#define SDL_INIT_TIMER 0
|
||||
#define SDL_INIT_NOPARACHUTE 0
|
||||
|
||||
extern int SDL_Init(Uint32 flags);
|
||||
|
||||
extern void SDL_Quit();
|
||||
|
||||
|
||||
@ -86,8 +91,6 @@ extern int __stdcall SDL_WarpMouse(int, int);
|
||||
|
||||
/* macros */
|
||||
|
||||
#define SDL_Init
|
||||
|
||||
#define SDL_GRAB_ON 0
|
||||
#define SDL_WM_GrabInput(a)
|
||||
#define SDL_GetError() ""
|
||||
|
@ -47,45 +47,54 @@ extern void terr_init();
|
||||
extern void terr_update(float time);
|
||||
extern bool terr_handler(const SDL_Event& ev);
|
||||
|
||||
extern int allow_reload();
|
||||
extern int dir_add_watch(const char* const dir, bool watch_subdirs);
|
||||
|
||||
static void write_sys_info()
|
||||
|
||||
|
||||
static int write_sys_info()
|
||||
{
|
||||
get_gfx_info();
|
||||
|
||||
struct utsname un;
|
||||
uname(&un);
|
||||
freopen("stdout.txt", "w", stdout);
|
||||
|
||||
FILE* const f = fopen("../system/system_info.txt", "w");
|
||||
if(!f)
|
||||
return -1;
|
||||
|
||||
// .. OS
|
||||
printf("%s %s (%s)\n", un.sysname, un.release, un.version);
|
||||
fprintf(f, "%s %s (%s)\n", un.sysname, un.release, un.version);
|
||||
// .. CPU
|
||||
printf("%s, %s", un.machine, cpu_type);
|
||||
fprintf(f, "%s, %s", un.machine, cpu_type);
|
||||
if(cpu_freq != 0.0f)
|
||||
{
|
||||
if(cpu_freq < 1e9)
|
||||
printf(", %.2f MHz\n", cpu_freq*1e-6);
|
||||
fprintf(f, ", %.2f MHz\n", cpu_freq*1e-6);
|
||||
else
|
||||
printf(", %.2f GHz\n", cpu_freq*1e-9);
|
||||
fprintf(f, ", %.2f GHz\n", cpu_freq*1e-9);
|
||||
}
|
||||
else
|
||||
printf("\n");
|
||||
fprintf(f, "\n");
|
||||
// .. memory
|
||||
printf("%lu MB RAM; %lu MB free\n", tot_mem/MB, avl_mem/MB);
|
||||
fprintf(f, "%lu MB RAM; %lu MB free\n", tot_mem/MB, avl_mem/MB);
|
||||
// .. graphics card
|
||||
printf("%s\n", gfx_card);
|
||||
printf("%s\n", gfx_drv);
|
||||
fprintf(f, "%s\n", gfx_card);
|
||||
fprintf(f, "%s\n", gfx_drv);
|
||||
// .. network name / ips
|
||||
char hostname[100]; // possibly nodename != hostname
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
printf("%s\n", hostname);
|
||||
fprintf(f, "%s\n", hostname);
|
||||
hostent* h = gethostbyname(hostname);
|
||||
if(h)
|
||||
{
|
||||
struct in_addr** ips = (struct in_addr**)h->h_addr_list;
|
||||
for(int i = 0; ips && ips[i]; i++)
|
||||
printf("%s ", inet_ntoa(*ips[i]));
|
||||
printf("\n");
|
||||
fprintf(f, "%s ", inet_ntoa(*ips[i]));
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
@ -149,12 +158,6 @@ static bool handler(const SDL_Event& ev)
|
||||
case SDLK_ESCAPE:
|
||||
quit = true;
|
||||
break;
|
||||
|
||||
|
||||
case '1':
|
||||
case SDLK_F1:
|
||||
res_reload("art/textures/terrain/types/grass/Base1.tga");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -348,8 +351,13 @@ void ParseArgs(int argc, char* argv[])
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
ParseArgs(argc,argv);
|
||||
file_set_root_dir(argv[0], "../data");
|
||||
|
||||
argc=2;
|
||||
argv[1] = "-m=test01.pmp";
|
||||
|
||||
ParseArgs(argc,argv);
|
||||
/*
|
||||
chdir("\\games\\bf\\ScreenShots");
|
||||
int a,b;
|
||||
char fn[100];
|
||||
@ -395,12 +403,14 @@ sprintf(fn, "ScreenShot%d.jpg", i);
|
||||
if(access(fn, F_OK) < 0)
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
__asm cpuid __asm rdtsc __asm mov b, eax
|
||||
int c = b-a;
|
||||
|
||||
*/
|
||||
|
||||
lib_init();
|
||||
|
||||
// set 24 bit (float) FPU precision for faster divides / sqrts
|
||||
@ -451,8 +461,8 @@ int c = b-a;
|
||||
|
||||
new CConfig;
|
||||
|
||||
file_set_root_dir(argv[0], "../data");
|
||||
vfs_mount("", "mods/official/", 0);
|
||||
dir_add_watch("mods\\official", false);
|
||||
|
||||
#ifndef NO_GUI
|
||||
// GUI uses VFS, so this must come after VFS init.
|
||||
@ -507,6 +517,9 @@ in_add_handler(terr_handler);
|
||||
{
|
||||
g_Config.Update();
|
||||
|
||||
allow_reload();
|
||||
|
||||
|
||||
// TODO: limiter in case simulation can't keep up?
|
||||
#if 0
|
||||
double time1 = get_time();
|
||||
|
@ -1,201 +1,201 @@
|
||||
#include "TextureManager.h"
|
||||
#include "lib.h"
|
||||
#include "ogl.h"
|
||||
#include "res/tex.h"
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
|
||||
const char* SupportedTextureFormats[] = { "png", "dds", "tga", "bmp" };
|
||||
|
||||
|
||||
CTextureManager g_TexMan;
|
||||
|
||||
|
||||
CTextureManager::CTextureManager()
|
||||
{
|
||||
m_TerrainTextures.reserve(32);
|
||||
}
|
||||
|
||||
void CTextureManager::AddTextureType(const char* name)
|
||||
{
|
||||
m_TerrainTextures.resize(m_TerrainTextures.size()+1);
|
||||
STextureType& ttype=m_TerrainTextures.back();
|
||||
ttype.m_Name=name;
|
||||
ttype.m_Index=m_TerrainTextures.size()-1;
|
||||
}
|
||||
|
||||
CTextureEntry* CTextureManager::FindTexture(const char* filename)
|
||||
{
|
||||
// check if file already loaded
|
||||
for (uint k=0;k<m_TerrainTextures.size();k++) {
|
||||
STextureType& ttype=m_TerrainTextures[k];
|
||||
for (uint i=0;i<ttype.m_Textures.size();i++) {
|
||||
if (strcmp((const char*) ttype.m_Textures[i]->m_Name,filename)==0) {
|
||||
return ttype.m_Textures[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CTextureEntry* CTextureManager::FindTexture(Handle handle)
|
||||
{
|
||||
for (uint k=0;k<m_TerrainTextures.size();k++) {
|
||||
STextureType& ttype=m_TerrainTextures[k];
|
||||
for (uint i=0;i<ttype.m_Textures.size();i++) {
|
||||
if (handle==ttype.m_Textures[i]->m_Handle) {
|
||||
return ttype.m_Textures[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CTextureEntry* CTextureManager::AddTexture(const char* filename,int type)
|
||||
{
|
||||
assert((uint)type<m_TerrainTextures.size());
|
||||
|
||||
CStr pathname("art/textures/terrain/types/");
|
||||
pathname+=m_TerrainTextures[type].m_Name;
|
||||
pathname+='/';
|
||||
pathname+=filename;
|
||||
|
||||
Handle h=tex_load((const char*) pathname);
|
||||
if (!h) {
|
||||
return 0;
|
||||
} else {
|
||||
int tw;
|
||||
int th;
|
||||
|
||||
tex_info(h, &tw, &th, NULL, NULL, NULL);
|
||||
|
||||
tw &= (tw-1);
|
||||
th &= (th-1);
|
||||
if (tw || th) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// create new texture entry
|
||||
CTextureEntry* texentry=new CTextureEntry;
|
||||
texentry->m_Name=filename;
|
||||
texentry->m_Handle=h;
|
||||
texentry->m_Type=type;
|
||||
|
||||
// upload texture for future GL use
|
||||
tex_upload(h,GL_LINEAR_MIPMAP_LINEAR);
|
||||
|
||||
// setup texture to repeat
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
// get root color for coloring minimap by querying root level of the texture
|
||||
// (this should decompress any compressed textures for us),
|
||||
// then scaling it down to a 1x1 size
|
||||
// - an alternative approach of just grabbing the top level of the mipmap tree fails
|
||||
// (or gives an incorrect colour) in some cases:
|
||||
// - suspect bug on Radeon cards when SGIS_generate_mipmap is used
|
||||
// - any textures without mipmaps
|
||||
// we'll just take the basic approach here:
|
||||
int width,height;
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&width);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height);
|
||||
|
||||
unsigned char* buf=new unsigned char[width*height*4];
|
||||
glGetTexImage(GL_TEXTURE_2D,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,buf);
|
||||
gluScaleImage(GL_BGRA_EXT,width,height,GL_UNSIGNED_BYTE,buf,
|
||||
1,1,GL_UNSIGNED_BYTE,&texentry->m_BaseColor);
|
||||
delete[] buf;
|
||||
|
||||
// add entry to list ..
|
||||
m_TerrainTextures[type].m_Textures.push_back(texentry);
|
||||
|
||||
// .. and return it
|
||||
return texentry;
|
||||
}
|
||||
|
||||
void CTextureManager::DeleteTexture(CTextureEntry* entry)
|
||||
{
|
||||
// find entry in list
|
||||
std::vector<CTextureEntry*>& textures=m_TerrainTextures[entry->m_Type].m_Textures;
|
||||
|
||||
typedef std::vector<CTextureEntry*>::iterator Iter;
|
||||
Iter i=std::find(textures.begin(),textures.end(),entry);
|
||||
if (i!=textures.end()) {
|
||||
textures.erase(i);
|
||||
}
|
||||
delete entry;
|
||||
}
|
||||
|
||||
void CTextureManager::LoadTerrainTextures(int terraintype,const char* fileext)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
struct _finddata_t file;
|
||||
long handle;
|
||||
|
||||
// build pathname
|
||||
CStr pathname("mods\\official\\art\\textures\\terrain\\types\\");
|
||||
pathname+=m_TerrainTextures[terraintype].m_Name;
|
||||
pathname+="\\";
|
||||
|
||||
CStr findname(pathname);
|
||||
findname+="*.";
|
||||
findname+=fileext;
|
||||
|
||||
// Find first matching file in directory for this terrain type
|
||||
if ((handle=_findfirst((const char*) findname,&file))!=-1) {
|
||||
|
||||
AddTexture(file.name,terraintype);
|
||||
|
||||
// Find the rest of the matching files
|
||||
while( _findnext(handle,&file)==0) {
|
||||
AddTexture((const char*) file.name,terraintype);
|
||||
}
|
||||
|
||||
_findclose(handle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CTextureManager::BuildTerrainTypes()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
struct _finddata_t file;
|
||||
long handle;
|
||||
|
||||
// Find first matching directory in terrain\textures
|
||||
if ((handle=_findfirst("mods\\official\\art\\textures\\terrain\\types\\*",&file))!=-1) {
|
||||
|
||||
if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') {
|
||||
AddTextureType(file.name);
|
||||
}
|
||||
|
||||
// Find the rest of the matching files
|
||||
while( _findnext(handle,&file)==0) {
|
||||
if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') {
|
||||
AddTextureType(file.name);
|
||||
}
|
||||
}
|
||||
|
||||
_findclose(handle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CTextureManager::LoadTerrainTextures()
|
||||
{
|
||||
// find all the terrain types by directory name
|
||||
BuildTerrainTypes();
|
||||
|
||||
// now iterate through terrain types loading all textures of that type
|
||||
for (uint i=0;i<m_TerrainTextures.size();i++) {
|
||||
for (uint j=0;j<sizeof(SupportedTextureFormats)/sizeof(const char*);j++) {
|
||||
LoadTerrainTextures(i,SupportedTextureFormats[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "TextureManager.h"
|
||||
#include "lib.h"
|
||||
#include "ogl.h"
|
||||
#include "res/tex.h"
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
|
||||
const char* SupportedTextureFormats[] = { "png", "dds", "tga", "bmp" };
|
||||
|
||||
|
||||
CTextureManager g_TexMan;
|
||||
|
||||
|
||||
CTextureManager::CTextureManager()
|
||||
{
|
||||
m_TerrainTextures.reserve(32);
|
||||
}
|
||||
|
||||
void CTextureManager::AddTextureType(const char* name)
|
||||
{
|
||||
m_TerrainTextures.resize(m_TerrainTextures.size()+1);
|
||||
STextureType& ttype=m_TerrainTextures.back();
|
||||
ttype.m_Name=name;
|
||||
ttype.m_Index=m_TerrainTextures.size()-1;
|
||||
}
|
||||
|
||||
CTextureEntry* CTextureManager::FindTexture(const char* filename)
|
||||
{
|
||||
// check if file already loaded
|
||||
for (uint k=0;k<m_TerrainTextures.size();k++) {
|
||||
STextureType& ttype=m_TerrainTextures[k];
|
||||
for (uint i=0;i<ttype.m_Textures.size();i++) {
|
||||
if (strcmp((const char*) ttype.m_Textures[i]->m_Name,filename)==0) {
|
||||
return ttype.m_Textures[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CTextureEntry* CTextureManager::FindTexture(Handle handle)
|
||||
{
|
||||
for (uint k=0;k<m_TerrainTextures.size();k++) {
|
||||
STextureType& ttype=m_TerrainTextures[k];
|
||||
for (uint i=0;i<ttype.m_Textures.size();i++) {
|
||||
if (handle==ttype.m_Textures[i]->m_Handle) {
|
||||
return ttype.m_Textures[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CTextureEntry* CTextureManager::AddTexture(const char* filename,int type)
|
||||
{
|
||||
assert((uint)type<m_TerrainTextures.size());
|
||||
|
||||
CStr pathname("art/textures/terrain/types/");
|
||||
pathname+=m_TerrainTextures[type].m_Name;
|
||||
pathname+='/';
|
||||
pathname+=filename;
|
||||
|
||||
Handle h=tex_load((const char*) pathname);
|
||||
if (!h) {
|
||||
return 0;
|
||||
} else {
|
||||
int tw;
|
||||
int th;
|
||||
|
||||
tex_info(h, &tw, &th, NULL, NULL, NULL);
|
||||
|
||||
tw &= (tw-1);
|
||||
th &= (th-1);
|
||||
if (tw || th) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// create new texture entry
|
||||
CTextureEntry* texentry=new CTextureEntry;
|
||||
texentry->m_Name=filename;
|
||||
texentry->m_Handle=h;
|
||||
texentry->m_Type=type;
|
||||
|
||||
// upload texture for future GL use
|
||||
tex_upload(h,GL_LINEAR_MIPMAP_LINEAR);
|
||||
|
||||
// setup texture to repeat
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
// get root color for coloring minimap by querying root level of the texture
|
||||
// (this should decompress any compressed textures for us),
|
||||
// then scaling it down to a 1x1 size
|
||||
// - an alternative approach of just grabbing the top level of the mipmap tree fails
|
||||
// (or gives an incorrect colour) in some cases:
|
||||
// - suspect bug on Radeon cards when SGIS_generate_mipmap is used
|
||||
// - any textures without mipmaps
|
||||
// we'll just take the basic approach here:
|
||||
int width,height;
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&width);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height);
|
||||
|
||||
unsigned char* buf=new unsigned char[width*height*4];
|
||||
glGetTexImage(GL_TEXTURE_2D,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,buf);
|
||||
gluScaleImage(GL_BGRA_EXT,width,height,GL_UNSIGNED_BYTE,buf,
|
||||
1,1,GL_UNSIGNED_BYTE,&texentry->m_BaseColor);
|
||||
delete[] buf;
|
||||
|
||||
// add entry to list ..
|
||||
m_TerrainTextures[type].m_Textures.push_back(texentry);
|
||||
|
||||
// .. and return it
|
||||
return texentry;
|
||||
}
|
||||
|
||||
void CTextureManager::DeleteTexture(CTextureEntry* entry)
|
||||
{
|
||||
// find entry in list
|
||||
std::vector<CTextureEntry*>& textures=m_TerrainTextures[entry->m_Type].m_Textures;
|
||||
|
||||
typedef std::vector<CTextureEntry*>::iterator Iter;
|
||||
Iter i=std::find(textures.begin(),textures.end(),entry);
|
||||
if (i!=textures.end()) {
|
||||
textures.erase(i);
|
||||
}
|
||||
delete entry;
|
||||
}
|
||||
|
||||
void CTextureManager::LoadTerrainTextures(int terraintype,const char* fileext)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
struct _finddata_t file;
|
||||
long handle;
|
||||
|
||||
// build pathname
|
||||
CStr pathname("mods\\official\\art\\textures\\terrain\\types\\");
|
||||
pathname+=m_TerrainTextures[terraintype].m_Name;
|
||||
pathname+="\\";
|
||||
|
||||
CStr findname(pathname);
|
||||
findname+="*.";
|
||||
findname+=fileext;
|
||||
|
||||
// Find first matching file in directory for this terrain type
|
||||
if ((handle=_findfirst((const char*) findname,&file))!=-1) {
|
||||
|
||||
AddTexture(file.name,terraintype);
|
||||
|
||||
// Find the rest of the matching files
|
||||
while( _findnext(handle,&file)==0) {
|
||||
AddTexture((const char*) file.name,terraintype);
|
||||
}
|
||||
|
||||
_findclose(handle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CTextureManager::BuildTerrainTypes()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
struct _finddata_t file;
|
||||
long handle;
|
||||
|
||||
// Find first matching directory in terrain\textures
|
||||
if ((handle=_findfirst("mods\\official\\art\\textures\\terrain\\types\\*",&file))!=-1) {
|
||||
|
||||
if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') {
|
||||
AddTextureType(file.name);
|
||||
}
|
||||
|
||||
// Find the rest of the matching files
|
||||
while( _findnext(handle,&file)==0) {
|
||||
if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') {
|
||||
AddTextureType(file.name);
|
||||
}
|
||||
}
|
||||
|
||||
_findclose(handle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CTextureManager::LoadTerrainTextures()
|
||||
{
|
||||
// find all the terrain types by directory name
|
||||
BuildTerrainTypes();
|
||||
|
||||
// now iterate through terrain types loading all textures of that type
|
||||
for (uint i=0;i<m_TerrainTextures.size();i++) {
|
||||
for (uint j=0;j<sizeof(SupportedTextureFormats)/sizeof(const char*);j++) {
|
||||
LoadTerrainTextures(i,SupportedTextureFormats[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,327 +1,325 @@
|
||||
#include "Matrix3D.h"
|
||||
#include "Renderer.h"
|
||||
#include "Terrain.h"
|
||||
#include "LightEnv.h"
|
||||
#include "TextureManager.h"
|
||||
#include "ObjectManager.h"
|
||||
#include "Prometheus.h"
|
||||
|
||||
#include "time.h"
|
||||
#include "sdl.h"
|
||||
#include "res/tex.h"
|
||||
#include "detect.h"
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
// TODO: fix scrolling hack - framerate independent, use SDL
|
||||
//#include "win.h" // REMOVEME
|
||||
|
||||
void InitScene ();
|
||||
void InitResources ();
|
||||
void RenderScene ();
|
||||
|
||||
extern bool keys[512]; // SDL also defines non-ascii keys; 512 should be enough
|
||||
|
||||
|
||||
CMatrix3D g_WorldMat;
|
||||
CRenderer g_Renderer;
|
||||
CTerrain g_Terrain;
|
||||
CCamera g_Camera;
|
||||
CLightEnv g_LightEnv;
|
||||
|
||||
int SelPX, SelPY, SelTX, SelTY;
|
||||
int g_BaseTexCounter = 0;
|
||||
int g_SecTexCounter = 1;
|
||||
int g_TransTexCounter = 0;
|
||||
|
||||
int g_TickCounter = 0;
|
||||
double g_LastTime;
|
||||
|
||||
|
||||
const int NUM_ALPHA_MAPS = 13;
|
||||
|
||||
int mouse_x=50, mouse_y=50;
|
||||
|
||||
void terr_init()
|
||||
{
|
||||
int xres,yres;
|
||||
get_cur_resolution(xres,yres);
|
||||
g_Renderer.Open(xres,yres,32);
|
||||
|
||||
SViewPort vp;
|
||||
vp.m_X=0;
|
||||
vp.m_Y=0;
|
||||
vp.m_Width=xres;
|
||||
vp.m_Height=yres;
|
||||
g_Camera.SetViewPort(&vp);
|
||||
|
||||
InitResources ();
|
||||
InitScene ();
|
||||
}
|
||||
|
||||
void terr_update(float time)
|
||||
{
|
||||
CVector3D right(time*60,0,time*60);
|
||||
CVector3D up(time*60,0,-time*60);
|
||||
|
||||
if (mouse_x >= g_xres-2)
|
||||
g_Camera.m_Orientation.Translate(right);
|
||||
if (mouse_x <= 3)
|
||||
g_Camera.m_Orientation.Translate(right*-1);
|
||||
|
||||
if (mouse_y >= g_yres-2)
|
||||
g_Camera.m_Orientation.Translate(up);
|
||||
if (mouse_y <= 3)
|
||||
g_Camera.m_Orientation.Translate(up*-1);
|
||||
|
||||
|
||||
|
||||
float fov = g_Camera.GetFOV();
|
||||
float d = DEGTORAD(0.4f);
|
||||
if(keys[SDLK_KP_MINUS])
|
||||
if (fov+d < DEGTORAD(90))
|
||||
g_Camera.SetProjection(1, 1000, fov + d);
|
||||
if(keys[SDLK_KP_PLUS])
|
||||
if (fov-d > DEGTORAD(20))
|
||||
g_Camera.SetProjection(1, 1000, fov - d);
|
||||
|
||||
g_Camera.UpdateFrustum ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool terr_handler(const SDL_Event& ev)
|
||||
{
|
||||
switch(ev.type)
|
||||
{
|
||||
case SDL_MOUSEMOTION:
|
||||
mouse_x = ev.motion.x;
|
||||
mouse_y = ev.motion.y;
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
switch(ev.key.keysym.sym)
|
||||
{
|
||||
case 'W':
|
||||
if (g_Renderer.GetTerrainRenderMode()==WIREFRAME) {
|
||||
g_Renderer.SetTerrainRenderMode(SOLID);
|
||||
} else {
|
||||
g_Renderer.SetTerrainRenderMode(WIREFRAME);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
// quick hack to return camera home, for screenshots (after alt+tabbing)
|
||||
g_Camera.SetProjection (1, 1000, DEGTORAD(20));
|
||||
g_Camera.m_Orientation.SetXRotation(DEGTORAD(30));
|
||||
g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
|
||||
g_Camera.m_Orientation.Translate (100, 150, -100);
|
||||
break;
|
||||
|
||||
/* case 'L':
|
||||
g_HillShading = !g_HillShading;
|
||||
break;*/
|
||||
|
||||
// tile selection
|
||||
case SDLK_DOWN:
|
||||
if(++SelTX > 15)
|
||||
if(SelPX == g_Terrain.GetPatchesPerSide()-1)
|
||||
SelTX = 15;
|
||||
else
|
||||
SelTX = 0, SelPX++;
|
||||
break;
|
||||
|
||||
case SDLK_UP:
|
||||
if(--SelTX < 0)
|
||||
if(SelPX == 0)
|
||||
SelTX = 0;
|
||||
else
|
||||
SelTX = 15, SelPX--;
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
if(++SelTY > 15)
|
||||
if(SelPY == g_Terrain.GetPatchesPerSide()-1)
|
||||
SelTY = 15;
|
||||
else
|
||||
SelTY = 0, SelPY++;
|
||||
break;
|
||||
|
||||
case SDLK_LEFT:
|
||||
if(--SelTY < 0)
|
||||
if(SelPY == 0)
|
||||
SelTY = 0;
|
||||
else
|
||||
SelTY = 15, SelPY--;
|
||||
break;
|
||||
|
||||
|
||||
case SDLK_KP0:
|
||||
{
|
||||
CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX];
|
||||
/*if (!MPatch->Tex2)
|
||||
{
|
||||
MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter];
|
||||
MPatch->Tex2 = BaseTexs[g_SecTexCounter];
|
||||
}
|
||||
else
|
||||
{
|
||||
MPatch->Tex2 = 0;
|
||||
MPatch->m_AlphaMap = 0;
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
|
||||
/*case SDLK_KP1:
|
||||
{
|
||||
CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX];
|
||||
|
||||
g_BaseTexCounter++;
|
||||
if (g_BaseTexCounter > 4)
|
||||
g_BaseTexCounter = 0;
|
||||
|
||||
MPatch->Tex1 = BaseTexs[g_BaseTexCounter];
|
||||
break;
|
||||
}
|
||||
|
||||
case SDLK_KP2:
|
||||
{
|
||||
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
|
||||
|
||||
if (MPatch->Tex2)
|
||||
{
|
||||
g_SecTexCounter++;
|
||||
if (g_SecTexCounter > 4)
|
||||
g_SecTexCounter = 0;
|
||||
|
||||
MPatch->Tex2 = BaseTexs[g_SecTexCounter];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SDLK_KP3:
|
||||
{
|
||||
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
|
||||
|
||||
if (MPatch->m_AlphaMap)
|
||||
{
|
||||
g_TransTexCounter++;
|
||||
if (g_TransTexCounter >= NUM_ALPHA_MAPS)
|
||||
g_TransTexCounter = 0;
|
||||
|
||||
MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter];
|
||||
}
|
||||
|
||||
break;
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void InitScene ()
|
||||
{
|
||||
// setup default lighting environment
|
||||
g_LightEnv.m_SunColor=RGBColor(1,1,1);
|
||||
g_LightEnv.m_Rotation=DEGTORAD(270);
|
||||
g_LightEnv.m_Elevation=DEGTORAD(45);
|
||||
g_LightEnv.m_TerrainAmbientColor=RGBColor(0,0,0);
|
||||
g_LightEnv.m_UnitsAmbientColor=RGBColor(0.4f,0.4f,0.4f);
|
||||
g_Renderer.SetLightEnv(&g_LightEnv);
|
||||
|
||||
// load terrain
|
||||
Handle ht = tex_load("terrain.raw");
|
||||
if(ht > 0)
|
||||
{
|
||||
const u8* p;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
tex_info(ht, &w, &h, NULL, NULL, (void **)&p);
|
||||
|
||||
printf("terrain.raw: %dx%d\n", w, h);
|
||||
|
||||
u16 *p16=new u16[w*h];
|
||||
u16 *p16p=p16;
|
||||
while (p16p < p16+(w*h))
|
||||
*p16p++ = (*p++) << 8;
|
||||
|
||||
g_Terrain.Resize(20);
|
||||
g_Terrain.SetHeightMap(p16);
|
||||
|
||||
delete[] p16;
|
||||
|
||||
tex_free(ht);
|
||||
}
|
||||
|
||||
// get default texture to apply to terrain
|
||||
CTextureEntry* texture=0;
|
||||
for (uint ii=0;ii<g_TexMan.m_TerrainTextures.size();ii++) {
|
||||
if (g_TexMan.m_TerrainTextures[ii].m_Textures.size()) {
|
||||
texture=g_TexMan.m_TerrainTextures[ii].m_Textures[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// cover entire terrain with default texture
|
||||
u32 patchesPerSide=g_Terrain.GetPatchesPerSide();
|
||||
for (uint pj=0; pj<patchesPerSide; pj++) {
|
||||
for (uint pi=0; pi<patchesPerSide; pi++) {
|
||||
|
||||
CPatch* patch=g_Terrain.GetPatch(pi,pj);
|
||||
|
||||
for (int j=0;j<16;j++) {
|
||||
for (int i=0;i<16;i++) {
|
||||
patch->m_MiniPatches[j][i].Tex1=texture ? texture->m_Handle :0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_Camera.SetProjection (1, 1000, DEGTORAD(20));
|
||||
g_Camera.m_Orientation.SetXRotation(DEGTORAD(30));
|
||||
g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
|
||||
|
||||
g_Camera.m_Orientation.Translate (100, 150, -100);
|
||||
|
||||
SelPX = SelPY = SelTX = SelTY = 0;
|
||||
}
|
||||
|
||||
void InitResources()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
g_TexMan.AddTextureType("grass");
|
||||
g_TexMan.AddTexture("Base1.tga", 0);
|
||||
#else
|
||||
g_TexMan.LoadTerrainTextures();
|
||||
g_ObjMan.LoadObjects();
|
||||
#endif
|
||||
|
||||
const char* fns[CRenderer::NumAlphaMaps] = {
|
||||
"art/textures/terrain/alphamaps/special/blendcircle.png",
|
||||
"art/textures/terrain/alphamaps/special/blendlshape.png",
|
||||
"art/textures/terrain/alphamaps/special/blendedge.png",
|
||||
"art/textures/terrain/alphamaps/special/blendedgecorner.png",
|
||||
"art/textures/terrain/alphamaps/special/blendedgetwocorners.png",
|
||||
"art/textures/terrain/alphamaps/special/blendfourcorners.png",
|
||||
"art/textures/terrain/alphamaps/special/blendtwooppositecorners.png",
|
||||
"art/textures/terrain/alphamaps/special/blendlshapecorner.png",
|
||||
"art/textures/terrain/alphamaps/special/blendtwocorners.png",
|
||||
"art/textures/terrain/alphamaps/special/blendcorner.png",
|
||||
"art/textures/terrain/alphamaps/special/blendtwoedges.png",
|
||||
"art/textures/terrain/alphamaps/special/blendthreecorners.png",
|
||||
"art/textures/terrain/alphamaps/special/blendushape.png",
|
||||
"art/textures/terrain/alphamaps/special/blendbad.png"
|
||||
};
|
||||
|
||||
g_Renderer.LoadAlphaMaps(fns);
|
||||
}
|
||||
#include "Matrix3D.h"
|
||||
#include "Renderer.h"
|
||||
#include "Terrain.h"
|
||||
#include "LightEnv.h"
|
||||
#include "TextureManager.h"
|
||||
#include "ObjectManager.h"
|
||||
#include "Prometheus.h"
|
||||
|
||||
#include "time.h"
|
||||
#include "sdl.h"
|
||||
#include "res/tex.h"
|
||||
#include "detect.h"
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
// TODO: fix scrolling hack - framerate independent, use SDL
|
||||
//#include "win.h" // REMOVEME
|
||||
|
||||
void InitScene ();
|
||||
void InitResources ();
|
||||
void RenderScene ();
|
||||
|
||||
extern bool keys[512]; // SDL also defines non-ascii keys; 512 should be enough
|
||||
|
||||
|
||||
CMatrix3D g_WorldMat;
|
||||
CRenderer g_Renderer;
|
||||
CTerrain g_Terrain;
|
||||
CCamera g_Camera;
|
||||
CLightEnv g_LightEnv;
|
||||
|
||||
int SelPX, SelPY, SelTX, SelTY;
|
||||
int g_BaseTexCounter = 0;
|
||||
int g_SecTexCounter = 1;
|
||||
int g_TransTexCounter = 0;
|
||||
|
||||
int g_TickCounter = 0;
|
||||
double g_LastTime;
|
||||
|
||||
|
||||
const int NUM_ALPHA_MAPS = 13;
|
||||
|
||||
int mouse_x=50, mouse_y=50;
|
||||
|
||||
void terr_init()
|
||||
{
|
||||
int xres,yres;
|
||||
get_cur_resolution(xres,yres);
|
||||
g_Renderer.Open(xres,yres,32);
|
||||
|
||||
SViewPort vp;
|
||||
vp.m_X=0;
|
||||
vp.m_Y=0;
|
||||
vp.m_Width=xres;
|
||||
vp.m_Height=yres;
|
||||
g_Camera.SetViewPort(&vp);
|
||||
|
||||
InitResources ();
|
||||
InitScene ();
|
||||
}
|
||||
|
||||
void terr_update(float time)
|
||||
{
|
||||
CVector3D right(time*60,0,time*60);
|
||||
CVector3D up(time*60,0,-time*60);
|
||||
|
||||
if (mouse_x >= g_xres-2)
|
||||
g_Camera.m_Orientation.Translate(right);
|
||||
if (mouse_x <= 3)
|
||||
g_Camera.m_Orientation.Translate(right*-1);
|
||||
|
||||
if (mouse_y >= g_yres-2)
|
||||
g_Camera.m_Orientation.Translate(up);
|
||||
if (mouse_y <= 3)
|
||||
g_Camera.m_Orientation.Translate(up*-1);
|
||||
|
||||
|
||||
|
||||
float fov = g_Camera.GetFOV();
|
||||
float d = DEGTORAD(0.4f);
|
||||
if(keys[SDLK_KP_MINUS])
|
||||
if (fov+d < DEGTORAD(90))
|
||||
g_Camera.SetProjection(1, 1000, fov + d);
|
||||
if(keys[SDLK_KP_PLUS])
|
||||
if (fov-d > DEGTORAD(20))
|
||||
g_Camera.SetProjection(1, 1000, fov - d);
|
||||
|
||||
g_Camera.UpdateFrustum ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool terr_handler(const SDL_Event& ev)
|
||||
{
|
||||
switch(ev.type)
|
||||
{
|
||||
case SDL_MOUSEMOTION:
|
||||
mouse_x = ev.motion.x;
|
||||
mouse_y = ev.motion.y;
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
switch(ev.key.keysym.sym)
|
||||
{
|
||||
case 'W':
|
||||
if (g_Renderer.GetTerrainRenderMode()==WIREFRAME) {
|
||||
g_Renderer.SetTerrainRenderMode(SOLID);
|
||||
} else {
|
||||
g_Renderer.SetTerrainRenderMode(WIREFRAME);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
// quick hack to return camera home, for screenshots (after alt+tabbing)
|
||||
g_Camera.SetProjection (1, 1000, DEGTORAD(20));
|
||||
g_Camera.m_Orientation.SetXRotation(DEGTORAD(30));
|
||||
g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
|
||||
g_Camera.m_Orientation.Translate (100, 150, -100);
|
||||
break;
|
||||
|
||||
/* case 'L':
|
||||
g_HillShading = !g_HillShading;
|
||||
break;*/
|
||||
|
||||
// tile selection
|
||||
case SDLK_DOWN:
|
||||
if(++SelTX > 15)
|
||||
if(SelPX == g_Terrain.GetPatchesPerSide()-1)
|
||||
SelTX = 15;
|
||||
else
|
||||
SelTX = 0, SelPX++;
|
||||
break;
|
||||
|
||||
case SDLK_UP:
|
||||
if(--SelTX < 0)
|
||||
if(SelPX == 0)
|
||||
SelTX = 0;
|
||||
else
|
||||
SelTX = 15, SelPX--;
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
if(++SelTY > 15)
|
||||
if(SelPY == g_Terrain.GetPatchesPerSide()-1)
|
||||
SelTY = 15;
|
||||
else
|
||||
SelTY = 0, SelPY++;
|
||||
break;
|
||||
|
||||
case SDLK_LEFT:
|
||||
if(--SelTY < 0)
|
||||
if(SelPY == 0)
|
||||
SelTY = 0;
|
||||
else
|
||||
SelTY = 15, SelPY--;
|
||||
break;
|
||||
|
||||
|
||||
case SDLK_KP0:
|
||||
{
|
||||
CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX];
|
||||
/*if (!MPatch->Tex2)
|
||||
{
|
||||
MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter];
|
||||
MPatch->Tex2 = BaseTexs[g_SecTexCounter];
|
||||
}
|
||||
else
|
||||
{
|
||||
MPatch->Tex2 = 0;
|
||||
MPatch->m_AlphaMap = 0;
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
|
||||
/*case SDLK_KP1:
|
||||
{
|
||||
CMiniPatch *MPatch = &g_Terrain.GetPatch(SelPY, SelPX)->m_MiniPatches[SelTY][SelTX];
|
||||
|
||||
g_BaseTexCounter++;
|
||||
if (g_BaseTexCounter > 4)
|
||||
g_BaseTexCounter = 0;
|
||||
|
||||
MPatch->Tex1 = BaseTexs[g_BaseTexCounter];
|
||||
break;
|
||||
}
|
||||
|
||||
case SDLK_KP2:
|
||||
{
|
||||
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
|
||||
|
||||
if (MPatch->Tex2)
|
||||
{
|
||||
g_SecTexCounter++;
|
||||
if (g_SecTexCounter > 4)
|
||||
g_SecTexCounter = 0;
|
||||
|
||||
MPatch->Tex2 = BaseTexs[g_SecTexCounter];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SDLK_KP3:
|
||||
{
|
||||
CMiniPatch *MPatch = &g_Terrain.m_Patches[SelPY][SelPX].m_MiniPatches[SelTY][SelTX];
|
||||
|
||||
if (MPatch->m_AlphaMap)
|
||||
{
|
||||
g_TransTexCounter++;
|
||||
if (g_TransTexCounter >= NUM_ALPHA_MAPS)
|
||||
g_TransTexCounter = 0;
|
||||
|
||||
MPatch->m_AlphaMap = AlphaMaps[g_TransTexCounter];
|
||||
}
|
||||
|
||||
break;
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void InitScene ()
|
||||
{
|
||||
// setup default lighting environment
|
||||
g_LightEnv.m_SunColor=RGBColor(1,1,1);
|
||||
g_LightEnv.m_Rotation=DEGTORAD(270);
|
||||
g_LightEnv.m_Elevation=DEGTORAD(45);
|
||||
g_LightEnv.m_TerrainAmbientColor=RGBColor(0,0,0);
|
||||
g_LightEnv.m_UnitsAmbientColor=RGBColor(0.4f,0.4f,0.4f);
|
||||
g_Renderer.SetLightEnv(&g_LightEnv);
|
||||
|
||||
// load terrain
|
||||
Handle ht = tex_load("terrain.raw");
|
||||
if(ht > 0)
|
||||
{
|
||||
const u8* p;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
tex_info(ht, &w, &h, NULL, NULL, (void **)&p);
|
||||
|
||||
printf("terrain.raw: %dx%d\n", w, h);
|
||||
|
||||
u16 *p16=new u16[w*h];
|
||||
u16 *p16p=p16;
|
||||
while (p16p < p16+(w*h))
|
||||
*p16p++ = (*p++) << 8;
|
||||
|
||||
g_Terrain.Resize(20);
|
||||
g_Terrain.SetHeightMap(p16);
|
||||
|
||||
delete[] p16;
|
||||
|
||||
tex_free(ht);
|
||||
}
|
||||
|
||||
// get default texture to apply to terrain
|
||||
CTextureEntry* texture=0;
|
||||
for (uint ii=0;ii<g_TexMan.m_TerrainTextures.size();ii++) {
|
||||
if (g_TexMan.m_TerrainTextures[ii].m_Textures.size()) {
|
||||
texture=g_TexMan.m_TerrainTextures[ii].m_Textures[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// cover entire terrain with default texture
|
||||
u32 patchesPerSide=g_Terrain.GetPatchesPerSide();
|
||||
for (uint pj=0; pj<patchesPerSide; pj++) {
|
||||
for (uint pi=0; pi<patchesPerSide; pi++) {
|
||||
|
||||
CPatch* patch=g_Terrain.GetPatch(pi,pj);
|
||||
|
||||
for (int j=0;j<16;j++) {
|
||||
for (int i=0;i<16;i++) {
|
||||
patch->m_MiniPatches[j][i].Tex1=texture ? texture->m_Handle :0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_Camera.SetProjection (1, 1000, DEGTORAD(20));
|
||||
g_Camera.m_Orientation.SetXRotation(DEGTORAD(30));
|
||||
g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
|
||||
|
||||
g_Camera.m_Orientation.Translate (100, 150, -100);
|
||||
|
||||
SelPX = SelPY = SelTX = SelTY = 0;
|
||||
}
|
||||
|
||||
void InitResources()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
g_TexMan.AddTextureType("grass");
|
||||
g_TexMan.AddTexture("Base1.tga", 0);
|
||||
#else
|
||||
g_TexMan.LoadTerrainTextures();
|
||||
g_ObjMan.LoadObjects();
|
||||
#endif
|
||||
|
||||
const char* fns[CRenderer::NumAlphaMaps] = {
|
||||
"art/textures/terrain/alphamaps/special/blendcircle.png",
|
||||
"art/textures/terrain/alphamaps/special/blendlshape.png",
|
||||
"art/textures/terrain/alphamaps/special/blendedge.png",
|
||||
"art/textures/terrain/alphamaps/special/blendedgecorner.png",
|
||||
"art/textures/terrain/alphamaps/special/blendedgetwocorners.png",
|
||||
"art/textures/terrain/alphamaps/special/blendfourcorners.png",
|
||||
"art/textures/terrain/alphamaps/special/blendtwooppositecorners.png",
|
||||
"art/textures/terrain/alphamaps/special/blendlshapecorner.png",
|
||||
"art/textures/terrain/alphamaps/special/blendtwocorners.png",
|
||||
"art/textures/terrain/alphamaps/special/blendcorner.png",
|
||||
"art/textures/terrain/alphamaps/special/blendtwoedges.png",
|
||||
"art/textures/terrain/alphamaps/special/blendthreecorners.png",
|
||||
"art/textures/terrain/alphamaps/special/blendushape.png",
|
||||
"art/textures/terrain/alphamaps/special/blendbad.png"
|
||||
};
|
||||
|
||||
g_Renderer.LoadAlphaMaps(fns);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user