# HG changeset patch # User John Tsiombikas # Date 1414017967 -10800 # Node ID 1cffe3409164d6293d60fed7dff6bba0ef146891 initial commit diff -r 000000000000 -r 1cffe3409164 TheLabDemo.sln --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TheLabDemo.sln Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TheLabDemo", "TheLabDemo.vcproj", "{5346BE25-4A84-4401-82EB-88E9E6B9009D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5346BE25-4A84-4401-82EB-88E9E6B9009D}.Debug|Win32.ActiveCfg = Debug|Win32 + {5346BE25-4A84-4401-82EB-88E9E6B9009D}.Debug|Win32.Build.0 = Debug|Win32 + {5346BE25-4A84-4401-82EB-88E9E6B9009D}.Release|Win32.ActiveCfg = Release|Win32 + {5346BE25-4A84-4401-82EB-88E9E6B9009D}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff -r 000000000000 -r 1cffe3409164 TheLabDemo.vcproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TheLabDemo.vcproj Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,493 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 000000000000 -r 1cffe3409164 fmod.dll Binary file fmod.dll has changed diff -r 000000000000 -r 1cffe3409164 libs/fmod/fmod.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/fmod/fmod.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,802 @@ +//========================================================================================== +// FMOD Main header file. Copyright (c), FireLight Multimedia 1999-2000. +//========================================================================================== + +#ifndef _FMOD_H_ +#define _FMOD_H_ + +//=============================================================================================== +// DEFINITIONS +//=============================================================================================== + +#if defined(__GNUC__) && defined(WIN32) + #define _cdecl +#endif /* defined(__GNUC__) && defined(WIN32) */ + +#if defined(PLATFORM_LINUX) + #define _cdecl + #define _stdcall + #define __cdecl + #define __stdcall + #define __declspec(x) + #define __PS __attribute__((packed)) /* gcc packed */ +#else + #define __PS /*dummy*/ +#endif + +#define F_API _stdcall + +#ifdef DLL_EXPORTS + #define DLL_API __declspec(dllexport) +#else + #ifdef __LCC__ + #define DLL_API F_API + #else + #define DLL_API + #endif // __LCC__ +#endif //DLL_EXPORTS + + +#define FMOD_VERSION 3.32f + + +// fmod defined types +typedef struct FSOUND_MATERIAL FSOUND_MATERIAL; +typedef struct FSOUND_GEOMLIST FSOUND_GEOMLIST; +typedef struct FSOUND_SAMPLE FSOUND_SAMPLE; +typedef struct FSOUND_STREAM FSOUND_STREAM; +typedef struct FSOUND_DSPUNIT FSOUND_DSPUNIT; +typedef struct FMUSIC_MODULE FMUSIC_MODULE; + +// callback types +typedef signed char (_cdecl *FSOUND_STREAMCALLBACK) (FSOUND_STREAM *stream, void *buff, int len, int param); +typedef void * (_cdecl *FSOUND_DSPCALLBACK) (void *originalbuffer, void *newbuffer, int length, int param); +typedef void (_cdecl *FMUSIC_CALLBACK) (FMUSIC_MODULE *mod, unsigned char param); + + +/* +[ENUM] +[ + [DESCRIPTION] + On failure of commands in FMOD, use FSOUND_GetError to attain what happened. + + [SEE_ALSO] + FSOUND_GetError +] +*/ +enum FMOD_ERRORS +{ + FMOD_ERR_NONE, // No errors + FMOD_ERR_BUSY, // Cannot call this command after FSOUND_Init. Call FSOUND_Close first. + FMOD_ERR_UNINITIALIZED, // This command failed because FSOUND_Init or FSOUND_SetOutput was not called + FMOD_ERR_INIT, // Error initializing output device. + FMOD_ERR_ALLOCATED, // Error initializing output device, but more specifically, the output device is already in use and cannot be reused. + FMOD_ERR_PLAY, // Playing the sound failed. + FMOD_ERR_OUTPUT_FORMAT, // Soundcard does not support the features needed for this soundsystem (16bit stereo output) + FMOD_ERR_COOPERATIVELEVEL, // Error setting cooperative level for hardware. + FMOD_ERR_CREATEBUFFER, // Error creating hardware sound buffer. + FMOD_ERR_FILE_NOTFOUND, // File not found + FMOD_ERR_FILE_FORMAT, // Unknown file format + FMOD_ERR_FILE_BAD, // Error loading file + FMOD_ERR_MEMORY, // Not enough memory + FMOD_ERR_VERSION, // The version number of this file format is not supported + FMOD_ERR_INVALID_PARAM, // An invalid parameter was passed to this function + FMOD_ERR_NO_EAX, // Tried to use an EAX command on a non EAX enabled channel or output. + FMOD_ERR_NO_EAX2, // Tried to use an advanced EAX2 command on a non EAX2 enabled channel or output. + FMOD_ERR_CHANNEL_ALLOC, // Failed to allocate a new channel + FMOD_ERR_RECORD, // Recording is not supported on this machine + FMOD_ERR_MEDIAPLAYER, // Windows Media Player not installed so cant play wma or use internet streaming. +}; + + +/* +[ENUM] +[ + [DESCRIPTION] + These output types are used with FSOUND_SetOutput, to choose which output driver to use. + + FSOUND_OUTPUT_A3D will cause FSOUND_Init to FAIL if you have not got a vortex + based A3D card. The suggestion for this is to immediately try and reinitialize FMOD with + FSOUND_OUTPUT_DSOUND, and if this fails, try initializing FMOD with FSOUND_OUTPUT_WAVEOUT. + + FSOUND_OUTPUT_DSOUND will not support hardware 3d acceleration if the sound card driver + does not support DirectX 6 Voice Manager Extensions. + + [SEE_ALSO] + FSOUND_SetOutput + FSOUND_GetOutput +] +*/ +enum FSOUND_OUTPUTTYPES +{ + FSOUND_OUTPUT_NOSOUND, // NoSound driver, all calls to this succeed but do nothing. + FSOUND_OUTPUT_WINMM, // Windows Multimedia driver. + FSOUND_OUTPUT_DSOUND, // DirectSound driver. You need this to get EAX or EAX2 support. + FSOUND_OUTPUT_A3D, // A3D driver. You need this to get geometry support. + FSOUND_OUTPUT_OSS, // Linux/Unix OSS (Open Sound System) driver, i.e. the kernel sound drivers. + FSOUND_OUTPUT_ESD, // Linux/Unix ESD (Enlightment Sound Daemon) driver. + FSOUND_OUTPUT_ALSA // Linux Alsa driver. +}; + + +/* +[ENUM] +[ + [DESCRIPTION] + These mixer types are used with FSOUND_SetMixer, to choose which mixer to use, or to act + upon for other reasons using FSOUND_GetMixer. + + [SEE_ALSO] + FSOUND_SetMixer + FSOUND_GetMixer +] +*/ +enum FSOUND_MIXERTYPES +{ + FSOUND_MIXER_AUTODETECT, // Enables autodetection of the fastest mixer based on your cpu. + FSOUND_MIXER_BLENDMODE, // Enables the standard non mmx, blendmode mixer. + FSOUND_MIXER_MMXP5, // Enables the mmx, pentium optimized blendmode mixer. + FSOUND_MIXER_MMXP6, // Enables the mmx, ppro/p2/p3 optimized mixer. + + FSOUND_MIXER_QUALITY_AUTODETECT,// Enables autodetection of the fastest quality mixer based on your cpu. + FSOUND_MIXER_QUALITY_FPU, // Enables the interpolating/volume ramping FPU mixer. + FSOUND_MIXER_QUALITY_MMXP5, // Enables the interpolating/volume ramping p5 MMX mixer. + FSOUND_MIXER_QUALITY_MMXP6, // Enables the interpolating/volume ramping ppro/p2/p3+ MMX mixer. +}; + +/* +[ENUM] +[ + [DESCRIPTION] + These definitions describe the type of song being played. + + [SEE_ALSO] + FMUSIC_GetType +] +*/ +enum FMUSIC_TYPES +{ + FMUSIC_TYPE_NONE, + FMUSIC_TYPE_MOD, // Protracker / Fasttracker + FMUSIC_TYPE_S3M, // ScreamTracker 3 + FMUSIC_TYPE_XM, // FastTracker 2 + FMUSIC_TYPE_IT, // Impulse Tracker. + FMUSIC_TYPE_MIDI, // MIDI file +}; + + +/* +[DEFINE_START] +[ + [NAME] + FSOUND_DSP_PRIORITIES + + [DESCRIPTION] + These default priorities are + + [SEE_ALSO] + FSOUND_DSP_Create + FSOUND_DSP_SetPriority +] +*/ +#define FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT 0 // DSP CLEAR unit - done first +#define FSOUND_DSP_DEFAULTPRIORITY_SFXUNIT 100 // DSP SFX unit - done second +#define FSOUND_DSP_DEFAULTPRIORITY_MUSICUNIT 200 // DSP MUSIC unit - done third +#define FSOUND_DSP_DEFAULTPRIORITY_USER 300 // User priority, use this as reference +#define FSOUND_DSP_DEFAULTPRIORITY_CLIPANDCOPYUNIT 1000 // DSP CLIP AND COPY unit - last +// [DEFINE_END] + + +/* +[DEFINE_START] +[ + [NAME] + FSOUND_CAPS + + [DESCRIPTION] + Driver description bitfields. Use FSOUND_Driver_GetCaps to determine if a driver enumerated + has the settings you are after. The enumerated driver depends on the output mode, see + FSOUND_OUTPUTTYPES + + [SEE_ALSO] + FSOUND_GetDriverCaps + FSOUND_OUTPUTTYPES +] +*/ +#define FSOUND_CAPS_HARDWARE 0x1 // This driver supports hardware accelerated 3d sound. +#define FSOUND_CAPS_EAX 0x2 // This driver supports EAX reverb +#define FSOUND_CAPS_GEOMETRY_OCCLUSIONS 0x4 // This driver supports (A3D) geometry occlusions +#define FSOUND_CAPS_GEOMETRY_REFLECTIONS 0x8 // This driver supports (A3D) geometry reflections +#define FSOUND_CAPS_EAX2 0x10 // This driver supports EAX2/A3D3 reverb +// [DEFINE_END] + + +/* +[DEFINE_START] +[ + [NAME] + FSOUND_MODES + + [DESCRIPTION] + Sample description bitfields, OR them together for loading and describing samples. +] +*/ +#define FSOUND_LOOP_OFF 0x00000001 // For non looping samples. +#define FSOUND_LOOP_NORMAL 0x00000002 // For forward looping samples. +#define FSOUND_LOOP_BIDI 0x00000004 // For bidirectional looping samples. (no effect if in hardware). +#define FSOUND_8BITS 0x00000008 // For 8 bit samples. +#define FSOUND_16BITS 0x00000010 // For 16 bit samples. +#define FSOUND_MONO 0x00000020 // For mono samples. +#define FSOUND_STEREO 0x00000040 // For stereo samples. +#define FSOUND_UNSIGNED 0x00000080 // For source data containing unsigned samples. +#define FSOUND_SIGNED 0x00000100 // For source data containing signed data. +#define FSOUND_DELTA 0x00000200 // For source data stored as delta values. +#define FSOUND_IT214 0x00000400 // For source data stored using IT214 compression. +#define FSOUND_IT215 0x00000800 // For source data stored using IT215 compression. +#define FSOUND_HW3D 0x00001000 // Attempts to make samples use 3d hardware acceleration. (if the card supports it) +#define FSOUND_2D 0x00002000 // Ignores any 3d processing. overrides FSOUND_HW3D. Located in software. +#define FSOUND_STREAMABLE 0x00004000 // For a streamable sound where you feed the data to it. If you dont supply this sound may come out corrupted. (only affects a3d output) +#define FSOUND_LOADMEMORY 0x00008000 // 'name' will be interpreted as a pointer to data for streaming and samples. +#define FSOUND_LOADRAW 0x00010000 // For will ignore file format and treat as raw pcm. +#define FSOUND_MPEGACCURATE 0x00020000 // For FSOUND_Stream_OpenFile - for accurate FSOUND_Stream_GetLengthMs/FSOUND_Stream_SetTime. WARNING, see FSOUNDStream_OpenFile for inital opening time performance issues. + +// Default sample type. Loop off, 8bit mono, signed, not hardware accelerated. +// Some API functions ignore 8bits and mono, as it may be an mpeg/wav/etc which has its format predetermined. +#define FSOUND_NORMAL (FSOUND_LOOP_OFF | FSOUND_8BITS | FSOUND_MONO) +// [DEFINE_END] + + +/* +[DEFINE_START] +[ + [NAME] + FSOUND_CDPLAYMODES + + [DESCRIPTION] + Playback method for a CD Audio track, using FSOUND_CD_Play + + [SEE_ALSO] + FSOUND_CD_Play +] +*/ +#define FSOUND_CD_PLAYCONTINUOUS 0 // Starts from the current track and plays to end of CD. +#define FSOUND_CD_PLAYONCE 1 // Plays the specified track then stops. +#define FSOUND_CD_PLAYLOOPED 2 // Plays the specified track looped, forever until stopped manually. +#define FSOUND_CD_PLAYRANDOM 3 // Plays tracks in random order +// [DEFINE_END] + + +/* +[DEFINE_START] +[ + [NAME] + FSOUND_CHANNELSAMPLEMODE + + [DESCRIPTION] + Miscellaneous values for FMOD functions. + + [SEE_ALSO] + FSOUND_PlaySound + FSOUND_PlaySound3DAttrib + + FSOUND_Sample_Alloc + FSOUND_Sample_Load + FSOUND_SetPan +] +*/ +#define FSOUND_FREE -1 // value to play on any free channel, or to allocate a sample in a free sample slot. +#define FSOUND_UNMANAGED -2 // value to allocate a sample that is NOT managed by FSOUND or placed in a sample slot. +#define FSOUND_ALL -3 // for a channel index , this flag will affect ALL channels available! Not supported by every function. +#define FSOUND_STEREOPAN -1 // value for FSOUND_SetPan so that stereo sounds are not played at half volume. See FSOUND_SetPan for more on this. +// [DEFINE_END] + + +/* +[ENUM] +[ + [DESCRIPTION] + These are environment types defined for use with the FSOUND_Reverb API. + + [SEE_ALSO] + FSOUND_Reverb_SetEnvironment + FSOUND_Reverb_SetEnvironmentAdvanced +] +*/ +enum FSOUND_REVERB_ENVIRONMENTS +{ + FSOUND_ENVIRONMENT_GENERIC, + FSOUND_ENVIRONMENT_PADDEDCELL, + FSOUND_ENVIRONMENT_ROOM, + FSOUND_ENVIRONMENT_BATHROOM, + FSOUND_ENVIRONMENT_LIVINGROOM, + FSOUND_ENVIRONMENT_STONEROOM, + FSOUND_ENVIRONMENT_AUDITORIUM, + FSOUND_ENVIRONMENT_CONCERTHALL, + FSOUND_ENVIRONMENT_CAVE, + FSOUND_ENVIRONMENT_ARENA, + FSOUND_ENVIRONMENT_HANGAR, + FSOUND_ENVIRONMENT_CARPETEDHALLWAY, + FSOUND_ENVIRONMENT_HALLWAY, + FSOUND_ENVIRONMENT_STONECORRIDOR, + FSOUND_ENVIRONMENT_ALLEY, + FSOUND_ENVIRONMENT_FOREST, + FSOUND_ENVIRONMENT_CITY, + FSOUND_ENVIRONMENT_MOUNTAINS, + FSOUND_ENVIRONMENT_QUARRY, + FSOUND_ENVIRONMENT_PLAIN, + FSOUND_ENVIRONMENT_PARKINGLOT, + FSOUND_ENVIRONMENT_SEWERPIPE, + FSOUND_ENVIRONMENT_UNDERWATER, + FSOUND_ENVIRONMENT_DRUGGED, + FSOUND_ENVIRONMENT_DIZZY, + FSOUND_ENVIRONMENT_PSYCHOTIC, + + FSOUND_ENVIRONMENT_COUNT +}; + +/* +[DEFINE_START] +[ + [NAME] + FSOUND_REVERBMIX_USEDISTANCE + + [DESCRIPTION] + Used with FSOUND_Reverb_SetMix, this setting allows reverb to attenuate based on distance from the listener. + Instead of hard coding a value with FSOUND_Reverb_SetMix, this value can be used instead, for a more natural + reverb dropoff. + + [SEE_ALSO] + FSOUND_Reverb_SetMix +] +*/ +#define FSOUND_REVERBMIX_USEDISTANCE -1.0f // used with FSOUND_Reverb_SetMix to scale reverb by distance +// [DEFINE_END] + + +/* +[DEFINE_START] +[ + [NAME] + FSOUND_REVERB_IGNOREPARAM + + [DESCRIPTION] + Used with FSOUND_Reverb_SetEnvironment and FSOUND_Reverb_SetEnvironmentAdvanced, this can + be placed in the place of a specific parameter for the reverb setting. It allows you to + not set any parameters except the ones you are interested in .. and example would be this. + FSOUND_Reverb_SetEnvironment(FSOUND_REVERB_IGNOREPARAM, + FSOUND_REVERB_IGNOREPARAM, + FSOUND_REVERB_IGNOREPARAM, + 0.0f); + This means env, vol and decay are left alone, but 'damp' is set to 0. + + [SEE_ALSO] + FSOUND_Reverb_SetEnvironment + FSOUND_Reverb_SetEnvironmentAdvanced +] +*/ +#define FSOUND_REVERB_IGNOREPARAM -9999999 // used with FSOUND_Reverb_SetEnvironmentAdvanced to ignore certain parameters by choice. +// [DEFINE_END] + + +/* +[DEFINE_START] +[ + [NAME] + FSOUND_REVERB_PRESETS + + [DESCRIPTION] + A set of predefined environment PARAMETERS, created by Creative Labs + These can be placed directly into the FSOUND_Reverb_SetEnvironment call + + [SEE_ALSO] + FSOUND_Reverb_SetEnvironment +] +*/ +#define FSOUND_PRESET_OFF FSOUND_ENVIRONMENT_GENERIC,0.0f,0.0f,0.0f +#define FSOUND_PRESET_GENERIC FSOUND_ENVIRONMENT_GENERIC,0.5f,1.493f,0.5f +#define FSOUND_PRESET_PADDEDCELL FSOUND_ENVIRONMENT_PADDEDCELL,0.25f,0.1f,0.0f +#define FSOUND_PRESET_ROOM FSOUND_ENVIRONMENT_ROOM,0.417f,0.4f,0.666f +#define FSOUND_PRESET_BATHROOM FSOUND_ENVIRONMENT_BATHROOM,0.653f,1.499f,0.166f +#define FSOUND_PRESET_LIVINGROOM FSOUND_ENVIRONMENT_LIVINGROOM,0.208f,0.478f,0.0f +#define FSOUND_PRESET_STONEROOM FSOUND_ENVIRONMENT_STONEROOM,0.5f,2.309f,0.888f +#define FSOUND_PRESET_AUDITORIUM FSOUND_ENVIRONMENT_AUDITORIUM,0.403f,4.279f,0.5f +#define FSOUND_PRESET_CONCERTHALL FSOUND_ENVIRONMENT_CONCERTHALL,0.5f,3.961f,0.5f +#define FSOUND_PRESET_CAVE FSOUND_ENVIRONMENT_CAVE,0.5f,2.886f,1.304f +#define FSOUND_PRESET_ARENA FSOUND_ENVIRONMENT_ARENA,0.361f,7.284f,0.332f +#define FSOUND_PRESET_HANGAR FSOUND_ENVIRONMENT_HANGAR,0.5f,10.0f,0.3f +#define FSOUND_PRESET_CARPETEDHALLWAY FSOUND_ENVIRONMENT_CARPETEDHALLWAY,0.153f,0.259f,2.0f +#define FSOUND_PRESET_HALLWAY FSOUND_ENVIRONMENT_HALLWAY,0.361f,1.493f,0.0f +#define FSOUND_PRESET_STONECORRIDOR FSOUND_ENVIRONMENT_STONECORRIDOR,0.444f,2.697f,0.638f +#define FSOUND_PRESET_ALLEY FSOUND_ENVIRONMENT_ALLEY,0.25f,1.752f,0.776f +#define FSOUND_PRESET_FOREST FSOUND_ENVIRONMENT_FOREST,0.111f,3.145f,0.472f +#define FSOUND_PRESET_CITY FSOUND_ENVIRONMENT_CITY,0.111f,2.767f,0.224f +#define FSOUND_PRESET_MOUNTAINS FSOUND_ENVIRONMENT_MOUNTAINS,0.194f,7.841f,0.472f +#define FSOUND_PRESET_QUARRY FSOUND_ENVIRONMENT_QUARRY,1.0f,1.499f,0.5f +#define FSOUND_PRESET_PLAIN FSOUND_ENVIRONMENT_PLAIN,0.097f,2.767f,0.224f +#define FSOUND_PRESET_PARKINGLOT FSOUND_ENVIRONMENT_PARKINGLOT,0.208f,1.652f,1.5f +#define FSOUND_PRESET_SEWERPIPE FSOUND_ENVIRONMENT_SEWERPIPE,0.652f,2.886f,0.25f +#define FSOUND_PRESET_UNDERWATER FSOUND_ENVIRONMENT_UNDERWATER,1.0f,1.499f,0.0f +#define FSOUND_PRESET_DRUGGED FSOUND_ENVIRONMENT_DRUGGED,0.875f, 8.392f,1.388f +#define FSOUND_PRESET_DIZZY FSOUND_ENVIRONMENT_DIZZY,0.139f,17.234f,0.666f +#define FSOUND_PRESET_PSYCHOTIC FSOUND_ENVIRONMENT_PSYCHOTIC,0.486f,7.563f,0.806f +// [DEFINE_END] + + +/* +[DEFINE_START] +[ + [NAME] + FSOUND_GEOMETRY_MODES + + [DESCRIPTION] + Geometry flags, used as the mode flag in FSOUND_Geometry_AddPolygon + + [SEE_ALSO] + FSOUND_Geometry_AddPolygon +] +*/ +#define FSOUND_GEOMETRY_NORMAL 0x0 // Default geometry type. Occluding polygon +#define FSOUND_GEOMETRY_REFLECTIVE 0x01 // This polygon is reflective +#define FSOUND_GEOMETRY_OPENING 0x02 // Overlays a transparency over the previous polygon. The 'openingfactor' value supplied is copied internally. +#define FSOUND_GEOMETRY_OPENING_REFERENCE 0x04 // Overlays a transparency over the previous polygon. The 'openingfactor' supplied is pointed to (for access when building a list) +// [DEFINE_END] + +/* +[DEFINE_START] +[ + [NAME] + FSOUND_INIT_FLAGS + + [DESCRIPTION] + Initialization flags. Use them with FSOUND_Init in the flags parameter to change various behaviour. + + [SEE_ALSO] + FSOUND_Init +] +*/ +#define FSOUND_INIT_USEDEFAULTMIDISYNTH 0x01 // Causes MIDI playback to force software decoding. +#define FSOUND_INIT_GLOBALFOCUS 0x02 // For DirectSound output - sound is not muted when window is out of focus. +// [DEFINE_END] + + + + +//=============================================================================================== +// FUNCTION PROTOTYPES +//=============================================================================================== + +#ifdef __cplusplus +extern "C" { +#endif + +// ================================== +// Initialization / Global functions. +// ================================== + +// *Pre* FSOUND_Init functions. These can't be called after FSOUND_Init is +// called (they will fail). They set up FMOD system functionality. +DLL_API signed char F_API FSOUND_SetOutput(int outputtype); +DLL_API signed char F_API FSOUND_SetDriver(int driver); +DLL_API signed char F_API FSOUND_SetMixer(int mixer); +DLL_API signed char F_API FSOUND_SetBufferSize(int len_ms); +DLL_API signed char F_API FSOUND_SetHWND(void *hwnd); +DLL_API signed char F_API FSOUND_SetMinHardwareChannels(int min); +DLL_API signed char F_API FSOUND_SetMaxHardwareChannels(int max); + +// Main initialization / closedown functions. +// Note : Use FSOUND_INIT_USEDEFAULTMIDISYNTH with FSOUND_Init for software override with MIDI playback. +// : Use FSOUND_INIT_GLOBALFOCUS with FSOUND_Init to make sound audible no matter which window is in focus. +DLL_API signed char F_API FSOUND_Init(int mixrate, int maxsoftwarechannels, unsigned int flags); +DLL_API void F_API FSOUND_Close(); + +// Runtime +DLL_API void F_API FSOUND_SetSFXMasterVolume(int volume); +DLL_API void F_API FSOUND_SetPanSeperation(float pansep); + +// System information. +DLL_API int F_API FSOUND_GetError(); +DLL_API float F_API FSOUND_GetVersion(); +DLL_API int F_API FSOUND_GetOutput(); +DLL_API int F_API FSOUND_GetDriver(); +DLL_API int F_API FSOUND_GetMixer(); +DLL_API int F_API FSOUND_GetNumDrivers(); +DLL_API signed char * F_API FSOUND_GetDriverName(int id); +DLL_API signed char F_API FSOUND_GetDriverCaps(int id, unsigned int *caps); +DLL_API int F_API FSOUND_GetOutputRate(); +DLL_API int F_API FSOUND_GetMaxChannels(); +DLL_API int F_API FSOUND_GetMaxSamples(); +DLL_API int F_API FSOUND_GetSFXMasterVolume(); +DLL_API int F_API FSOUND_GetNumHardwareChannels(); +DLL_API int F_API FSOUND_GetChannelsPlaying(); +DLL_API float F_API FSOUND_GetCPUUsage(); + +// =================================== +// Sample management / load functions. +// =================================== + +// Note : Use FSOUND_LOADMEMORY flag with FSOUND_Sample_Load to load from memory. +// Use FSOUND_LOADRAW flag with FSOUND_Sample_Load to treat as as raw pcm data. + +// Sample creation and management functions +DLL_API FSOUND_SAMPLE * F_API FSOUND_Sample_Load(int index, const char *name, unsigned int mode, int memlength); +DLL_API FSOUND_SAMPLE * F_API FSOUND_Sample_Alloc(int index, int length, unsigned int mode, int deffreq, int defvol, int defpan, int defpri); +DLL_API void F_API FSOUND_Sample_Free(FSOUND_SAMPLE *sptr); +DLL_API signed char F_API FSOUND_Sample_Upload(FSOUND_SAMPLE *sptr, void *srcdata, unsigned int mode); +DLL_API signed char F_API FSOUND_Sample_Lock(FSOUND_SAMPLE *sptr, int offset, int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2); +DLL_API signed char F_API FSOUND_Sample_Unlock(FSOUND_SAMPLE *sptr, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2); + +// Sample control functions +DLL_API signed char F_API FSOUND_Sample_SetLoopMode(FSOUND_SAMPLE *sptr, unsigned int loopmode); +DLL_API signed char F_API FSOUND_Sample_SetLoopPoints(FSOUND_SAMPLE *sptr, int loopstart, int loopend); +DLL_API signed char F_API FSOUND_Sample_SetDefaults(FSOUND_SAMPLE *sptr, int deffreq, int defvol, int defpan, int defpri); +DLL_API signed char F_API FSOUND_Sample_SetMinMaxDistance(FSOUND_SAMPLE *sptr, float min, float max); + +// Sample information +DLL_API FSOUND_SAMPLE * F_API FSOUND_Sample_Get(int sampno); +DLL_API char * F_API FSOUND_Sample_GetName(FSOUND_SAMPLE *sptr); +DLL_API unsigned int F_API FSOUND_Sample_GetLength(FSOUND_SAMPLE *sptr); +DLL_API signed char F_API FSOUND_Sample_GetLoopPoints(FSOUND_SAMPLE *sptr, int *loopstart, int *loopend); +DLL_API signed char F_API FSOUND_Sample_GetDefaults(FSOUND_SAMPLE *sptr, int *deffreq, int *defvol, int *defpan, int *defpri); +DLL_API unsigned int F_API FSOUND_Sample_GetMode(FSOUND_SAMPLE *sptr); + +// ============================ +// Channel control functions. +// ============================ + +// Playing and stopping sounds. +DLL_API int F_API FSOUND_PlaySound(int channel, FSOUND_SAMPLE *sptr); +DLL_API int F_API FSOUND_PlaySound3DAttrib(int channel, FSOUND_SAMPLE *sptr, int freq, int vol, int pan, float *pos, float *vel); +DLL_API signed char F_API FSOUND_StopSound(int channel); + +// Functions to control playback of a channel. +DLL_API signed char F_API FSOUND_SetFrequency(int channel, int freq); +DLL_API signed char F_API FSOUND_SetVolume(int channel, int vol); +DLL_API signed char F_API FSOUND_SetVolumeAbsolute(int channel, int vol); +DLL_API signed char F_API FSOUND_SetPan(int channel, int pan); +DLL_API signed char F_API FSOUND_SetSurround(int channel, signed char surround); +DLL_API signed char F_API FSOUND_SetMute(int channel, signed char mute); +DLL_API signed char F_API FSOUND_SetPriority(int channel, int priority); +DLL_API signed char F_API FSOUND_SetReserved(int channel, signed char reserved); +DLL_API signed char F_API FSOUND_SetPaused(int channel, signed char paused); +DLL_API signed char F_API FSOUND_SetLoopMode(int channel, unsigned int loopmode); + +// Channel information +DLL_API signed char F_API FSOUND_IsPlaying(int channel); +DLL_API int F_API FSOUND_GetFrequency(int channel); +DLL_API int F_API FSOUND_GetVolume(int channel); +DLL_API int F_API FSOUND_GetPan(int channel); +DLL_API signed char F_API FSOUND_GetSurround(int channel); +DLL_API signed char F_API FSOUND_GetMute(int channel); +DLL_API int F_API FSOUND_GetPriority(int channel); +DLL_API signed char F_API FSOUND_GetReserved(int channel); +DLL_API signed char F_API FSOUND_GetPaused(int channel); +DLL_API unsigned int F_API FSOUND_GetCurrentPosition(int channel); +DLL_API FSOUND_SAMPLE * F_API FSOUND_GetCurrentSample(int channel); +DLL_API float F_API FSOUND_GetCurrentVU(int channel); + +// =================== +// 3D sound functions. +// =================== +// see also FSOUND_PlaySound3DAttrib (above) +// see also FSOUND_Sample_SetMinMaxDistance (above) +DLL_API void F_API FSOUND_3D_Update(); +DLL_API signed char F_API FSOUND_3D_SetAttributes(int channel, float *pos, float *vel); +DLL_API signed char F_API FSOUND_3D_GetAttributes(int channel, float *pos, float *vel); +DLL_API void F_API FSOUND_3D_Listener_SetAttributes(float *pos, float *vel, float fx, float fy, float fz, float tx, float ty, float tz); +DLL_API void F_API FSOUND_3D_Listener_GetAttributes(float *pos, float *vel, float *fx, float *fy, float *fz, float *tx, float *ty, float *tz); +DLL_API void F_API FSOUND_3D_Listener_SetDopplerFactor(float scale); +DLL_API void F_API FSOUND_3D_Listener_SetDistanceFactor(float scale); +DLL_API void F_API FSOUND_3D_Listener_SetRolloffFactor(float scale); + +// ========================= +// File Streaming functions. +// ========================= + +// Note : Use FSOUND_LOADMEMORY flag with FSOUND_Stream_OpenFile to stream from memory. +// Use FSOUND_LOADRAW flag with FSOUND_Stream_OpenFile to treat stream as raw pcm data. +// Use FSOUND_MPEGACCURATE flag with FSOUND_Stream_OpenFile to open mpegs in 'accurate mode' for seeking etc. + +DLL_API FSOUND_STREAM * F_API FSOUND_Stream_OpenFile(const char *filename, unsigned int mode, int memlength); +DLL_API FSOUND_STREAM * F_API FSOUND_Stream_Create(FSOUND_STREAMCALLBACK callback, int length, unsigned int mode, int samplerate, int userdata); +DLL_API int F_API FSOUND_Stream_Play(int channel, FSOUND_STREAM *stream); +DLL_API int F_API FSOUND_Stream_Play3DAttrib(int channel, FSOUND_STREAM *stream, int freq, int vol, int pan, float *pos, float *vel); +DLL_API signed char F_API FSOUND_Stream_Stop(FSOUND_STREAM *stream); +DLL_API signed char F_API FSOUND_Stream_Close(FSOUND_STREAM *stream); +DLL_API signed char F_API FSOUND_Stream_SetEndCallback(FSOUND_STREAM *stream, FSOUND_STREAMCALLBACK callback, int userdata); +DLL_API signed char F_API FSOUND_Stream_SetSynchCallback(FSOUND_STREAM *stream, FSOUND_STREAMCALLBACK callback, int userdata); +DLL_API FSOUND_SAMPLE * F_API FSOUND_Stream_GetSample(FSOUND_STREAM *stream); +DLL_API FSOUND_DSPUNIT *F_API FSOUND_Stream_CreateDSP(FSOUND_STREAM *stream, FSOUND_DSPCALLBACK callback, int priority, int param); + +DLL_API signed char F_API FSOUND_Stream_SetPaused(FSOUND_STREAM *stream, signed char paused); +DLL_API signed char F_API FSOUND_Stream_GetPaused(FSOUND_STREAM *stream); +DLL_API signed char F_API FSOUND_Stream_SetPosition(FSOUND_STREAM *stream, int position); +DLL_API int F_API FSOUND_Stream_GetPosition(FSOUND_STREAM *stream); +DLL_API signed char F_API FSOUND_Stream_SetTime(FSOUND_STREAM *stream, int ms); +DLL_API int F_API FSOUND_Stream_GetTime(FSOUND_STREAM *stream); +DLL_API int F_API FSOUND_Stream_GetLength(FSOUND_STREAM *stream); +DLL_API int F_API FSOUND_Stream_GetLengthMs(FSOUND_STREAM *stream); + +// =================== +// CD audio functions. +// =================== + +DLL_API signed char F_API FSOUND_CD_Play(int track); +DLL_API void F_API FSOUND_CD_SetPlayMode(signed char mode); +DLL_API signed char F_API FSOUND_CD_Stop(); +DLL_API signed char F_API FSOUND_CD_SetPaused(signed char paused); +DLL_API signed char F_API FSOUND_CD_SetVolume(int volume); +DLL_API signed char F_API FSOUND_CD_Eject(); + +DLL_API signed char F_API FSOUND_CD_GetPaused(); +DLL_API int F_API FSOUND_CD_GetTrack(); +DLL_API int F_API FSOUND_CD_GetNumTracks(); +DLL_API int F_API FSOUND_CD_GetVolume(); +DLL_API int F_API FSOUND_CD_GetTrackLength(int track); +DLL_API int F_API FSOUND_CD_GetTrackTime(); + + +// ============== +// DSP functions. +// ============== + +// DSP Unit control and information functions. +DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_Create(FSOUND_DSPCALLBACK callback, int priority, int param); +DLL_API void F_API FSOUND_DSP_Free(FSOUND_DSPUNIT *unit); +DLL_API void F_API FSOUND_DSP_SetPriority(FSOUND_DSPUNIT *unit, int priority); +DLL_API int F_API FSOUND_DSP_GetPriority(FSOUND_DSPUNIT *unit); +DLL_API void F_API FSOUND_DSP_SetActive(FSOUND_DSPUNIT *unit, signed char active); +DLL_API signed char F_API FSOUND_DSP_GetActive(FSOUND_DSPUNIT *unit); + +// Functions to get hold of FSOUND 'system DSP unit' handles. +DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetClearUnit(); +DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetSFXUnit(); +DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetMusicUnit(); +DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetClipAndCopyUnit(); + +// misc DSP functions +DLL_API signed char F_API FSOUND_DSP_MixBuffers(void *destbuffer, void *srcbuffer, int len, int freq, int vol, int pan, unsigned int mode); +DLL_API void F_API FSOUND_DSP_ClearMixBuffer(); +DLL_API int F_API FSOUND_DSP_GetBufferLength(); + +// ============================================= +// Geometry functions. (NOT SUPPORTED IN LINUX) +// ============================================= + +// scene/polygon functions +DLL_API signed char F_API FSOUND_Geometry_AddPolygon(float *p1, float *p2, float *p3, float *p4, float *normal, unsigned int mode, float *openingfactor); +DLL_API int F_API FSOUND_Geometry_AddList(FSOUND_GEOMLIST *geomlist); + +// polygon list functions +DLL_API FSOUND_GEOMLIST * F_API FSOUND_Geometry_List_Create(signed char boundingvolume); +DLL_API signed char F_API FSOUND_Geometry_List_Free(FSOUND_GEOMLIST *geomlist); +DLL_API signed char F_API FSOUND_Geometry_List_Begin(FSOUND_GEOMLIST *geomlist); +DLL_API signed char F_API FSOUND_Geometry_List_End(FSOUND_GEOMLIST *geomlist); + +// material functions +DLL_API FSOUND_MATERIAL * F_API FSOUND_Geometry_Material_Create(); +DLL_API signed char F_API FSOUND_Geometry_Material_Free(FSOUND_MATERIAL *material); +DLL_API signed char F_API FSOUND_Geometry_Material_SetAttributes(FSOUND_MATERIAL *material, float reflectancegain, float reflectancefreq, float transmittancegain, float transmittancefreq); +DLL_API signed char F_API FSOUND_Geometry_Material_GetAttributes(FSOUND_MATERIAL *material, float *reflectancegain, float *reflectancefreq, float *transmittancegain, float *transmittancefreq); +DLL_API signed char F_API FSOUND_Geometry_Material_Set(FSOUND_MATERIAL *material); + +// ======================================================================== +// Reverb functions. (eax, eax2, a3d 3.0 reverb) (NOT SUPPORTED IN LINUX) +// ======================================================================== + +// eax1, eax2, a3d 3.0 (use FSOUND_REVERB_PRESETS if you like), (eax2 support through emulation/parameter conversion) +DLL_API signed char F_API FSOUND_Reverb_SetEnvironment(int env, float vol, float decay, float damp); +// eax2, a3d 3.0 only, does not work on eax1 +DLL_API signed char F_API FSOUND_Reverb_SetEnvironmentAdvanced( + int env, + int Room, // [-10000, 0] default: -10000 mB or use FSOUND_REVERB_IGNOREPARAM + int RoomHF, // [-10000, 0] default: 0 mB or use FSOUND_REVERB_IGNOREPARAM + float RoomRolloffFactor, // [0.0, 10.0] default: 0.0 or use FSOUND_REVERB_IGNOREPARAM + float DecayTime, // [0.1, 20.0] default: 1.0 s or use FSOUND_REVERB_IGNOREPARAM + float DecayHFRatio, // [0.1, 2.0] default: 0.5 or use FSOUND_REVERB_IGNOREPARAM + int Reflections, // [-10000, 1000] default: -10000 mB or use FSOUND_REVERB_IGNOREPARAM + float ReflectionsDelay, // [0.0, 0.3] default: 0.02 s or use FSOUND_REVERB_IGNOREPARAM + int Reverb, // [-10000, 2000] default: -10000 mB or use FSOUND_REVERB_IGNOREPARAM + float ReverbDelay, // [0.0, 0.1] default: 0.04 s or use FSOUND_REVERB_IGNOREPARAM + float EnvironmentSize, // [0.0, 100.0] default: 100.0 % or use FSOUND_REVERB_IGNOREPARAM + float EnvironmentDiffusion, // [0.0, 100.0] default: 100.0 % or use FSOUND_REVERB_IGNOREPARAM + float AirAbsorptionHF); // [20.0, 20000.0] default: 5000.0 Hz or use FSOUND_REVERB_IGNOREPARAM + +DLL_API signed char F_API FSOUND_Reverb_SetMix(int channel, float mix); + +// information functions +DLL_API signed char F_API FSOUND_Reverb_GetEnvironment(int *env, float *vol, float *decay, float *damp); +DLL_API signed char F_API FSOUND_Reverb_GetEnvironmentAdvanced( + int *env, + int *Room, + int *RoomHF, + float *RoomRolloffFactor, + float *DecayTime, + float *DecayHFRatio, + int *Reflections, + float *ReflectionsDelay, + int *Reverb, + float *ReverbDelay, + float *EnvironmentSize, + float *EnvironmentDiffusion, + float *AirAbsorptionHF); +DLL_API signed char F_API FSOUND_Reverb_GetMix(int channel, float *mix); + +// ============================================= +// Recording functions (NOT SUPPORTED IN LINUX) +// ============================================= + +// recording initialization functions +DLL_API signed char F_API FSOUND_Record_SetDriver(int outputtype); +DLL_API int F_API FSOUND_Record_GetNumDrivers(); +DLL_API signed char * F_API FSOUND_Record_GetDriverName(int id); +DLL_API int F_API FSOUND_Record_GetDriver(); + +// recording functionality. Only one recording session will work at a time +DLL_API signed char F_API FSOUND_Record_StartSample(FSOUND_SAMPLE *sptr, signed char loop);// record to sample +DLL_API signed char F_API FSOUND_Record_Stop(); // stop recording +DLL_API int F_API FSOUND_Record_GetPosition(); // offset in sample, or wav file + +// ========================= +// File system override +// ========================= + +DLL_API void F_API FSOUND_File_SetCallbacks(unsigned int (_cdecl *OpenCallback)(const char *name), + void (_cdecl *CloseCallback)(unsigned int handle), + int (_cdecl *ReadCallback)(void *buffer, int size, unsigned int handle), + int (_cdecl *SeekCallback)(unsigned int handle, int pos, signed char mode), + int (_cdecl *TellCallback)(unsigned int handle)); + +// ============================================================================================= +// FMUSIC API +// ============================================================================================= + +// Song management / playback functions. +DLL_API FMUSIC_MODULE * F_API FMUSIC_LoadSong(const char *name); +DLL_API FMUSIC_MODULE * F_API FMUSIC_LoadSongMemory(void *data, int length); +DLL_API signed char F_API FMUSIC_FreeSong(FMUSIC_MODULE *mod); +DLL_API signed char F_API FMUSIC_PlaySong(FMUSIC_MODULE *mod); +DLL_API signed char F_API FMUSIC_StopSong(FMUSIC_MODULE *mod); +DLL_API void F_API FMUSIC_StopAllSongs(); +DLL_API signed char F_API FMUSIC_SetZxxCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback); +DLL_API signed char F_API FMUSIC_SetRowCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int rowstep); +DLL_API signed char F_API FMUSIC_SetOrderCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int orderstep); +DLL_API signed char F_API FMUSIC_SetInstCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int instrument); +DLL_API signed char F_API FMUSIC_SetSample(FMUSIC_MODULE *mod, int sampno, FSOUND_SAMPLE *sptr); +DLL_API signed char F_API FMUSIC_OptimizeChannels(FMUSIC_MODULE *mod, int maxchannels, int minvolume); + +// Runtime song functions. +DLL_API signed char F_API FMUSIC_SetReverb(signed char reverb); // MIDI only. +DLL_API signed char F_API FMUSIC_SetOrder(FMUSIC_MODULE *mod, int order); +DLL_API signed char F_API FMUSIC_SetPaused(FMUSIC_MODULE *mod, signed char pause); +DLL_API signed char F_API FMUSIC_SetMasterVolume(FMUSIC_MODULE *mod, int volume); +DLL_API signed char F_API FMUSIC_SetPanSeperation(FMUSIC_MODULE *mod, float pansep); + +// Static song information functions. +DLL_API char * F_API FMUSIC_GetName(FMUSIC_MODULE *mod); +DLL_API signed char F_API FMUSIC_GetType(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetNumOrders(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetNumPatterns(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetNumInstruments(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetNumSamples(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetNumChannels(FMUSIC_MODULE *mod); +DLL_API FSOUND_SAMPLE * F_API FMUSIC_GetSample(FMUSIC_MODULE *mod, int sampno); +DLL_API int F_API FMUSIC_GetPatternLength(FMUSIC_MODULE *mod, int orderno); + +// Runtime song information. +DLL_API signed char F_API FMUSIC_IsFinished(FMUSIC_MODULE *mod); +DLL_API signed char F_API FMUSIC_IsPlaying(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetMasterVolume(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetGlobalVolume(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetOrder(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetPattern(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetSpeed(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetBPM(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetRow(FMUSIC_MODULE *mod); +DLL_API signed char F_API FMUSIC_GetPaused(FMUSIC_MODULE *mod); +DLL_API int F_API FMUSIC_GetTime(FMUSIC_MODULE *mod); + +#ifdef __cplusplus +} +#endif + +#endif diff -r 000000000000 -r 1cffe3409164 libs/fmod/fmodvc.lib Binary file libs/fmod/fmodvc.lib has changed diff -r 000000000000 -r 1cffe3409164 n3dinit.conf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/n3dinit.conf Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,20 @@ +; The Lab Demos +; 3D Engine Configuration File +; You are advised not to mess with this file :) +; -- Nuclear / the Lab -- + +fullscreen = false +resolution = 800x600 +bpp = 32 +zbufferdepth = 32 +device = hal +tnl = hw +refresh = 60 +antialiasing = high +flipchain = doublebuffering +vsync = false +dontcareabout = zbufferdepth, tnl, alpha + +; -- syntax reminder -- +; dontcareflags: bpp, refresh, alpha, zbufferdepth, tnl, flipchain, aamode, vsync +; antialiasing: none / low / high \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 readme.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/readme.txt Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,25 @@ +--------------------------------------------------------------- + The Lab Demos presents a rather unfinished demo in ReAct 2003 +--------------------------------------------------------------- + - a B s e n c e - + (final version) + + Code: Nuclear + Gfx: RawNoise + Music: Amigo +Additional Gfx: Amoivikos / ASD + +A big thank you to the ReAct organizers (nlogn) for organizing +once again a great party. + +We want to personally greet: +Nina, Eva-S, Amoivikos, vvas, Navis, Alias Medron, Zouzoulos +j0bo, Psyche, Raoul, zafos, moT, emc, Outsider, imak, Thor +^gfx, Fubyo, Apomakros, Palmuter, nagz, night, aMUSiC, Optimus +Badsector and all the demosceners around the world. + +contact: nuclear@siggraph.org + +--------------------------------------------------------------- +---------------- http://thelab.demoscene.gr ----------------- +--------------------------------------------------------------- \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 resource.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resource.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by resources.rc +// +#define IDI_ICON1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff -r 000000000000 -r 1cffe3409164 resources.rc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources.rc Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,5 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +IDI_ICON1 ICON "thelab.ico" \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/3deng.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/3deng.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,17 @@ +#ifndef _3DENG_H_ +#define _3DENG_H_ + +#include "switches.h" +#include "3dengine.h" +#include "exceptions.h" +#include "n3dmath.h" +#include "3dengtypes.h" +#include "lights.h" +#include "objects.h" +#include "camera.h" +#include "objectgen.h" +#include "3dscene.h" +#include "sceneloader.h" +#include "particles.h" + +#endif // _3DENG_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/3dengine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/3dengine.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,1388 @@ +#include +#include +#include +#include +#include "d3dx8.h" +#include "3dengine.h" +#include "exceptions.h" +#include "3dgeom.h" +#include "lights.h" + +// local helper functions +ColorDepth GetColorDepthFromPixelFormat(D3DFORMAT fmt); +D3DFORMAT GetPixelFormatFromColorDepth(ColorDepth cd, bool noalpha=false); +D3DFORMAT GetDepthStencilFormat(int depthbits, bool stencil); + +///////////// Graphics Context Member Functions ///////////////// + +GraphicsContext::GraphicsContext() { + D3DDevice = 0; + BackfaceCulling = true; +} + +/////////////////////////////////// +// ----==( SetDefaultStates )==---- +// (Public Member Function) +// Sets the default render states +/////////////////////////////////// +void GraphicsContext::SetDefaultStates() { + D3DDevice->SetRenderState(D3DRS_LOCALVIEWER, true); + SetPrimitiveType(TriangleList); + SetBackfaceCulling(true); + SetFrontFace(Clockwise); + SetLighting(true); + SetColorVertex(false); + SetAmbientLight(0.0f); + SetMipMapping(true); + SetTextureFiltering(BilinearFiltering); + SetBillboarding(false); + SetSpecular(true); + + Matrix4x4 ProjMat; + CreateProjectionMatrix(&ProjMat, QuarterPi, 1.33333333f, 1.0f, 10000.0f); + SetProjectionMatrix(ProjMat); +} + + +bool GraphicsContext::CreateVertexBuffer(uint32 VertexCount, UsageFlags usage, VertexBuffer **vb) const { + long hr = D3DDevice->CreateVertexBuffer(VertexCount * sizeof(Vertex), (dword)usage, VertexFormat, D3DPOOL_DEFAULT, vb); + return (hr == D3D_OK); +} + +bool GraphicsContext::CreateIndexBuffer(uint32 IndexCount, UsageFlags usage, IndexBuffer **ib) const { + long hr = D3DDevice->CreateIndexBuffer(IndexCount * IndexSize, (dword)usage, IndexFormat, D3DPOOL_DEFAULT, ib); + return (hr == D3D_OK); +} + +bool GraphicsContext::CreateSurface(uint32 Width, uint32 Height, Surface **surf) const { + long hr = D3DDevice->CreateImageSurface(Width, Height, ColorFormat, surf); + return (hr == D3D_OK); +} + +bool GraphicsContext::CreateDepthStencil(uint32 Width, uint32 Height, Surface **zsurf) const { + long hr = D3DDevice->CreateDepthStencilSurface(Width, Height, ZFormat, (D3DMULTISAMPLE_TYPE)AASamples, zsurf); + return (hr == D3D_OK); +} + +void GraphicsContext::Clear(dword color) const { + D3DDevice->Clear(0, 0, D3DCLEAR_TARGET, color, 1.0f, 0); +} + +void GraphicsContext::ClearZBuffer(float zval) const { + D3DDevice->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, zval, 0); +} + +void GraphicsContext::ClearStencil(byte sval) const { + D3DDevice->Clear(0, 0, D3DCLEAR_STENCIL, 0, 1.0f, sval); +} + +void GraphicsContext::ClearZBufferStencil(float zval, byte sval) const { + D3DDevice->Clear(0, 0, D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0, zval, sval); +} + +void GraphicsContext::Flip() const { + D3DDevice->Present(0, 0, 0, 0); +} + + +bool GraphicsContext::Draw(VertexBuffer *vb) { + D3DVERTEXBUFFER_DESC desc; + vb->GetDesc(&desc); + unsigned int verts = desc.Size / sizeof(Vertex); + + D3DDevice->SetStreamSource(0, vb, sizeof(Vertex)); + long res = D3DDevice->DrawPrimitive((D3DPRIMITIVETYPE)ptype, 0, verts / 3); + D3DDevice->SetStreamSource(0, 0, 0); + return res == D3D_OK; +} + +bool GraphicsContext::Draw(Vertex *varray, unsigned int VertexCount) { + long res = D3DDevice->DrawPrimitiveUP((D3DPRIMITIVETYPE)ptype, VertexCount / 3, varray, sizeof(Vertex)); + return res == D3D_OK; +} + +bool GraphicsContext::Draw(VertexBuffer *vb, IndexBuffer *ib) { + D3DVERTEXBUFFER_DESC vbdesc; + vb->GetDesc(&vbdesc); + unsigned int verts = vbdesc.Size / sizeof(Vertex); + + D3DINDEXBUFFER_DESC ibdesc; + ib->GetDesc(&ibdesc); + unsigned int indices = ibdesc.Size / sizeof(Index); + + D3DDevice->SetStreamSource(0, vb, sizeof(Vertex)); + D3DDevice->SetIndices(ib, 0); + long res = D3DDevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)ptype, 0, verts, 0, indices / 3); + D3DDevice->SetIndices(0, 0); + D3DDevice->SetStreamSource(0, 0, 0); + return res == D3D_OK; +} + +bool GraphicsContext::Draw(Vertex *varray, Index *iarray, unsigned int VertexCount, unsigned int IndexCount) { + long res = D3DDevice->DrawIndexedPrimitiveUP((D3DPRIMITIVETYPE)ptype, 0, VertexCount, IndexCount / 3, iarray, IndexFormat, varray, sizeof(Vertex)); + return res == D3D_OK; +} + +bool GraphicsContext::Draw(Vertex *varray, Triangle *triarray, unsigned int VertexCount, unsigned int TriCount) { + unsigned int IndexCount = TriCount * 3; + Index *iarray = new Index[IndexCount]; + for(dword i=0; iSetRenderState(D3DRS_CULLMODE, CullOrder); + } else { + D3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + } + BackfaceCulling = enable; +} + +void GraphicsContext::SetFrontFace(FaceOrder order) { + if(order == Clockwise) { + CullOrder = CounterClockwise; + } else { + CullOrder = Clockwise; + } + if(BackfaceCulling) SetBackfaceCulling(BackfaceCulling); +} + +void GraphicsContext::SetAutoNormalize(bool enable) { + D3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, enable); +} + +void GraphicsContext::SetBillboarding(bool enable) { + BillBoardingEnabled = enable; + if(enable) { + + Vector3 pos; + pos.Transform(WorldMat[0]); + + Matrix4x4 world; + world.Translate(pos.x, pos.y, pos.z); + Matrix4x4 BillBoardRot; + + Vector3 dir = ViewMat.Inverse().GetRowVector(2); + float yangle = dir.x > 0.0f ? -atanf(dir.z / dir.x) + HalfPi : -atanf(dir.z / dir.x) - HalfPi; + + BillBoardRot.Rotate(0.0f, yangle, 0.0f); + Vector3 xaxis = VECTOR3_I; + Vector3 normal = -VECTOR3_K; + xaxis.Transform(BillBoardRot); + normal.Transform(BillBoardRot); + + // find angle between quad normal and view direction + float xangle = acosf(DotProduct(normal, dir.Normalized())); + BillBoardRot.Rotate(xaxis, xangle); + + world = BillBoardRot * world; + + D3DDevice->SetTransform(D3DTS_WORLD, &world); + //D3DDevice->SetTransform(D3DTS_VIEW, &BillboardViewMatrix); + } else { + D3DDevice->SetTransform(D3DTS_WORLD, &WorldMat[0]); + //D3DDevice->SetTransform(D3DTS_VIEW, &ViewMat); + } +} + +void GraphicsContext::SetColorWrite(bool red, bool green, bool blue, bool alpha) { + dword channels = 0; + if(red) channels |= D3DCOLORWRITEENABLE_RED; + if(green) channels |= D3DCOLORWRITEENABLE_GREEN; + if(blue) channels |= D3DCOLORWRITEENABLE_BLUE; + if(alpha) channels |= D3DCOLORWRITEENABLE_ALPHA; + + D3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, channels); +} + +// blending states +void GraphicsContext::SetAlphaBlending(bool enable) { + D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, enable); +} + +void GraphicsContext::SetBlendFunc(BlendingFactor src, BlendingFactor dest) { + D3DDevice->SetRenderState(D3DRS_SRCBLEND, src); + D3DDevice->SetRenderState(D3DRS_DESTBLEND, dest); +} + +// zbuffer states +void GraphicsContext::SetZBuffering(bool enable) { + D3DDevice->SetRenderState(D3DRS_ZENABLE, enable); +} + +void GraphicsContext::SetZWrite(bool enable) { + D3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, enable); +} + +void GraphicsContext::SetZFunc(CmpFunc func) { + D3DDevice->SetRenderState(D3DRS_ZFUNC, func); +} + +// set stencil buffer states +void GraphicsContext::SetStencilBuffering(bool enable) { + D3DDevice->SetRenderState(D3DRS_STENCILENABLE, enable); +} + +void GraphicsContext::SetStencilPassOp(StencilOp sop) { + D3DDevice->SetRenderState(D3DRS_STENCILPASS, sop); +} + +void GraphicsContext::SetStencilFailOp(StencilOp sop) { + D3DDevice->SetRenderState(D3DRS_STENCILFAIL, sop); +} + +void GraphicsContext::SetStencilPassZFailOp(StencilOp sop) { + D3DDevice->SetRenderState(D3DRS_STENCILZFAIL, sop); +} + +void GraphicsContext::SetStencilOp(StencilOp Fail, StencilOp StencilPassZFail, StencilOp Pass) { + D3DDevice->SetRenderState(D3DRS_STENCILPASS, Pass); + D3DDevice->SetRenderState(D3DRS_STENCILFAIL, Fail); + D3DDevice->SetRenderState(D3DRS_STENCILZFAIL, StencilPassZFail); +} + +void GraphicsContext::SetStencilFunc(CmpFunc func) { + D3DDevice->SetRenderState(D3DRS_STENCILFUNC, func); +} + +void GraphicsContext::SetStencilReference(dword value) { + D3DDevice->SetRenderState(D3DRS_STENCILREF, value); +} + +// texture & material states + +void GraphicsContext::SetTextureFactor(dword factor) { + D3DDevice->SetRenderState(D3DRS_TEXTUREFACTOR, factor); +} + +void GraphicsContext::SetTextureFiltering(TextureFilteringType texfilter, int TextureStage) { + dword TexFilter, MipFilter; + + switch(texfilter) { + case PointSampling: + TexFilter = MipFilter = D3DTEXF_POINT; + break; + + case BilinearFiltering: + TexFilter = D3DTEXF_LINEAR; + MipFilter = D3DTEXF_POINT; + break; + + case TrilinearFiltering: + TexFilter = MipFilter = D3DTEXF_LINEAR; + break; + + case AnisotropicFiltering: + TexFilter = D3DTEXF_ANISOTROPIC; + MipFilter = D3DTEXF_LINEAR; + break; + + default: break; + } + + this->MipFilter = MipFilter; + + if(!MipMapEnabled) MipFilter = D3DTEXF_NONE; + + if(TextureStage == 0xa11) { + for(int i=0; iSetTextureStageState(i, D3DTSS_MINFILTER, TexFilter); + D3DDevice->SetTextureStageState(i, D3DTSS_MAGFILTER, TexFilter); + D3DDevice->SetTextureStageState(i, D3DTSS_MIPFILTER, MipFilter); + } + } else { + D3DDevice->SetTextureStageState(TextureStage, D3DTSS_MINFILTER, TexFilter); + D3DDevice->SetTextureStageState(TextureStage, D3DTSS_MAGFILTER, TexFilter); + D3DDevice->SetTextureStageState(TextureStage, D3DTSS_MIPFILTER, MipFilter); + } +} + +void GraphicsContext::SetTextureAddressing(TextureAddressing uaddr, TextureAddressing vaddr, int TextureStage) { + if(TextureStage == 0xa11) { + for(int i=0; iSetTextureStageState(i, D3DTSS_ADDRESSU, uaddr); + D3DDevice->SetTextureStageState(i, D3DTSS_ADDRESSV, vaddr); + } + } else { + D3DDevice->SetTextureStageState(TextureStage, D3DTSS_ADDRESSU, uaddr); + D3DDevice->SetTextureStageState(TextureStage, D3DTSS_ADDRESSV, vaddr); + } +} + +void GraphicsContext::SetTextureBorderColor(dword color, int TextureStage) { + if(TextureStage == 0xa11) { + for(int i=0; iSetTextureStageState(i, D3DTSS_BORDERCOLOR, color); + } + } else { + D3DDevice->SetTextureStageState(TextureStage, D3DTSS_BORDERCOLOR, color); + } +} + +void GraphicsContext::SetTexture(int index, Texture *tex) { + D3DDevice->SetTexture(index, tex); +} + +void GraphicsContext::SetMipMapping(bool enable, int TextureStage) { + MipMapEnabled = enable; + dword mip = (enable ? MipFilter : D3DTEXF_NONE); + + if(TextureStage == 0xa11) { + for(int i=0; iSetTextureStageState(i, D3DTSS_MIPFILTER, mip); + } + } else { + D3DDevice->SetTextureStageState(TextureStage, D3DTSS_MIPFILTER, mip); + } +} + +void GraphicsContext::SetMaterial(const Material &mat) { + D3DDevice->SetMaterial(&mat); +} + +static unsigned long TLVertexFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1; + +struct TLVertex { + Vector3 pos; + float rhw; + unsigned long color; + TexCoord tex; + + TLVertex() { + pos = Vector3(0.0f, 0.0f, 0.0f); + color = 0xffffffff; + tex.u = tex.v = 0.0f; + rhw = pos.z; + } + + TLVertex(const Vector3 &pos, const Color &col, float u=0.0f, float v=0.0f) { + this->pos = pos; + rhw = pos.z; + color = col.GetPacked32(); + tex.u = u; + tex.v = v; + } +}; + +void GraphicsContext::BlitTexture(const Texture *texture, RECT *rect, const Color &col) { + bool norect = rect ? false : true; + if(norect) { + rect = new RECT; + rect->left = rect->top = 0; + rect->right = ContextParams.x; + rect->bottom = ContextParams.y; + } + + SetVertexProgram(TLVertexFVF); + + TLVertex tlverts[4]; + tlverts[0] = TLVertex(Vector3((float)rect->right, (float)rect->top, 1.0f), col, 1.0f, 0.0f); + tlverts[1] = TLVertex(Vector3((float)rect->right, (float)rect->bottom, 1.0f), col, 1.0f, 1.0f); + tlverts[2] = TLVertex(Vector3((float)rect->left, (float)rect->top, 1.0f), col, 0.0f, 0.0f); + tlverts[3] = TLVertex(Vector3((float)rect->left, (float)rect->bottom, 1.0f), col, 0.0f, 1.0f); + + EnableTextureStage(0); + DisableTextureStage(1); + SetTexture(0, const_cast(texture)); + + SetZBuffering(false); + D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, tlverts, sizeof(TLVertex)); + SetZBuffering(true); + + SetTexture(0, 0); + + SetVertexProgram(VertexFormat); + + if(norect) { + delete rect; + } +} + +// multitexturing interface +void GraphicsContext::EnableTextureStage(int stage) { + SetTextureStageColor(stage, TexBlendModulate, TexArgTexture, TexArgCurrent); +} + +void GraphicsContext::DisableTextureStage(int stage) { + D3DDevice->SetTextureStageState(stage, D3DTSS_COLOROP, D3DTOP_DISABLE); +} + +void GraphicsContext::SetTextureStageColor(int stage, TextureBlendFunction op, TextureBlendArgument arg1, TextureBlendArgument arg2, TextureBlendArgument arg3) { + D3DDevice->SetTextureStageState(stage, D3DTSS_COLOROP, op); + D3DDevice->SetTextureStageState(stage, D3DTSS_COLORARG1, arg1); + D3DDevice->SetTextureStageState(stage, D3DTSS_COLORARG2, arg2); + if(arg3) D3DDevice->SetTextureStageState(stage, D3DTSS_COLORARG0, arg3); +} + +void GraphicsContext::SetTextureStageAlpha(int stage, TextureBlendFunction op, TextureBlendArgument arg1, TextureBlendArgument arg2, TextureBlendArgument arg3) { + D3DDevice->SetTextureStageState(stage, D3DTSS_ALPHAOP, op); + D3DDevice->SetTextureStageState(stage, D3DTSS_ALPHAARG1, arg1); + D3DDevice->SetTextureStageState(stage, D3DTSS_ALPHAARG2, arg2); + if(arg3) D3DDevice->SetTextureStageState(stage, D3DTSS_ALPHAARG0, arg3); +} + +void GraphicsContext::SetTextureCoordIndex(int stage, int index) { + D3DDevice->SetTextureStageState(stage, D3DTSS_TEXCOORDINDEX, index); +} + +void GraphicsContext::SetTextureTransformState(int stage, TexTransformState TexXForm) { + D3DDevice->SetTextureStageState(stage, D3DTSS_TEXTURETRANSFORMFLAGS, TexXForm); +} + +// programmable pipeline interface +void GraphicsContext::SetVertexProgram(dword vs) { + D3DDevice->SetVertexShader(vs); +} + +void GraphicsContext::SetPixelProgram(dword ps) { + D3DDevice->SetPixelShader(ps); +} + +dword GraphicsContext::CreateVertexProgram(const char *fname) { + + // vertex format declaration + dword VertDecl[] = { + D3DVSD_STREAM(0), + D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), + D3DVSD_REG(D3DVSDE_BLENDWEIGHT, D3DVSDT_FLOAT1), + D3DVSD_REG(D3DVSDE_BLENDINDICES, D3DVSDT_UBYTE4), + D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3), + D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR), + D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2), + D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT2), + D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT2), + D3DVSD_REG(D3DVSDE_TEXCOORD3, D3DVSDT_FLOAT2), + D3DVSD_END() + }; + + + ID3DXBuffer *code, *errors; + if(D3DXAssembleShaderFromFile(fname, 0, 0, &code, &errors) != D3D_OK) { + return 0xffffffff; + } + + dword vprog; + if(D3DDevice->CreateVertexShader(VertDecl, (dword*)code->GetBufferPointer(), &vprog, 0) != D3D_OK) { + // could not create hardware vertex shader, try driver emulation... + if(D3DDevice->CreateVertexShader(VertDecl, (dword*)code->GetBufferPointer(), &vprog, D3DUSAGE_SOFTWAREPROCESSING) != D3D_OK) { + throw EngineGeneralException("The system lacks required programmable vertex processing unit support"); + } + } + + return vprog; +} + +void GraphicsContext::DestroyVertexProgram(dword vprog) { + D3DDevice->DeleteVertexShader(vprog); +} + +void GraphicsContext::SetVertexProgramConstant(dword creg, float val) { + float block[4] = {val, 0.0f, 0.0f, 1.0f}; + D3DDevice->SetVertexShaderConstant(creg, &block, 1); +} + +void GraphicsContext::SetVertexProgramConstant(dword creg, const Vector3 &val) { + Vector4 vec(val); + D3DDevice->SetVertexShaderConstant(creg, &vec, 1); +} + +void GraphicsContext::SetVertexProgramConstant(dword creg, const Vector4 &val) { + D3DDevice->SetVertexShaderConstant(creg, &val, 1); +} + +void GraphicsContext::SetVertexProgramConstant(dword creg, const Color &val) { + D3DDevice->SetVertexShaderConstant(creg, &val, 1); +} + +void GraphicsContext::SetVertexProgramConstant(dword creg, const Matrix4x4 &val) { + D3DDevice->SetVertexShaderConstant(creg, &val, 4); +} + +void GraphicsContext::SetVertexProgramConstant(dword creg, const void *data, dword size) { + D3DDevice->SetVertexShaderConstant(creg, data, size); +} + + +// Lighting states +void GraphicsContext::SetLighting(bool enable) { + D3DDevice->SetRenderState(D3DRS_LIGHTING, enable); +} + +void GraphicsContext::SetColorVertex(bool enable) { + D3DDevice->SetRenderState(D3DRS_COLORVERTEX, enable); +} + +void GraphicsContext::SetAmbientLight(Color AmbientColor) { + D3DDevice->SetRenderState(D3DRS_AMBIENT, AmbientColor.GetPacked32()); +} + +void GraphicsContext::SetShadingMode(ShadeMode mode) { + D3DDevice->SetRenderState(D3DRS_SHADEMODE, mode); +} + +void GraphicsContext::SetSpecular(bool enable) { + D3DDevice->SetRenderState(D3DRS_SPECULARENABLE, enable); +} + +// transformation states +void GraphicsContext::SetWorldMatrix(const Matrix4x4 &WorldMat, unsigned int BlendIndex) { + assert(BlendIndex < 256); + this->WorldMat[BlendIndex] = WorldMat; + if(!BillBoardingEnabled) { + D3DDevice->SetTransform(D3DTS_WORLDMATRIX(BlendIndex), &WorldMat); + } else { + SetBillboarding(true); + } +} + +void GraphicsContext::SetViewMatrix(const Matrix4x4 &ViewMat) { + this->ViewMat = ViewMat; + if(!BillBoardingEnabled) { + D3DDevice->SetTransform(D3DTS_VIEW, &ViewMat); + } else { + SetBillboarding(true); + } +} + +void GraphicsContext::SetProjectionMatrix(const Matrix4x4 &ProjMat) { + this->ProjMat = ProjMat; + D3DDevice->SetTransform(D3DTS_PROJECTION, &ProjMat); +} + +void GraphicsContext::SetTextureMatrix(const Matrix4x4 &TexMat, unsigned int TextureStage) { + assert(TextureStage < 8); + this->TexMat[TextureStage] = TexMat; + D3DDevice->SetTransform((D3DTRANSFORMSTATETYPE)((int)D3DTS_TEXTURE0 + TextureStage), &TexMat); +} + +void GraphicsContext::SetViewport(unsigned int x, unsigned int y, unsigned int xsize, unsigned int ysize, float MinZ, float MaxZ) { + D3DVIEWPORT8 viewport; + viewport.X = x; + viewport.Y = y; + viewport.Width = xsize; + viewport.Height = ysize; + viewport.MinZ = MinZ; + viewport.MaxZ = MaxZ; + + D3DDevice->SetViewport(&viewport); +} + + +const Matrix4x4 &GraphicsContext::GetWorldMatrix(unsigned int BlendIndex) { + assert(BlendIndex < 256); + return WorldMat[BlendIndex]; +} + +const Matrix4x4 &GraphicsContext::GetViewMatrix() { + return ViewMat; +} + +const Matrix4x4 &GraphicsContext::GetProjectionMatrix() { + return ProjMat; +} + +const Matrix4x4 &GraphicsContext::GetTextureMatrix(unsigned int TextureStage) { + assert(TextureStage < 8); + return TexMat[TextureStage]; +} + + +// render target +void GraphicsContext::ResetRenderTarget() { + D3DDevice->SetRenderTarget(MainRenderTarget.ColorSurface, MainRenderTarget.DepthStencilSurface); +} + +void GraphicsContext::SetRenderTarget(RenderTarget &rtarg) { + D3DDevice->SetRenderTarget(rtarg.ColorSurface, rtarg.DepthStencilSurface); +} + +void GraphicsContext::SetRenderTarget(Texture *rtarg, Texture *ztarg) { + Surface *rendsurf, *zsurf = 0; + rtarg->GetSurfaceLevel(0, &rendsurf); + if(ztarg) ztarg->GetSurfaceLevel(0, &zsurf); + + D3DDevice->SetRenderTarget(rendsurf, zsurf); +} + +void GraphicsContext::SetRenderTarget(Texture *rtarg, Surface *ztarg) { + Surface *rendsurf; + rtarg->GetSurfaceLevel(0, &rendsurf); + + D3DDevice->SetRenderTarget(rendsurf, ztarg); +} + + +//////////////////////////////////////////////////// +//////////// Engine3D Member Functions ///////////// +//////////////////////////////////////////////////// + +Engine3D::Engine3D() { + + if(!(d3d = Direct3DCreate8(D3D_SDK_VERSION))) { + // actually this will never occur, if directx8 is not available in the system then + // the OS loader will hit the problem first when it'll try to load d3d8.dll that is + // linked through d3d8.lib, and complain for missing imports + throw EngineInitException("DirectX 8.1 is required to run this program"); + } + + RetrieveAdapterInfo(); +} + +Engine3D::~Engine3D() { + + GraphicsContexts.erase(GraphicsContexts.begin(), GraphicsContexts.end()); + + if(d3d) { + d3d->Release(); + d3d = 0; + } +} + + +//////////////////////////////////// +// ----==( RetrieveAdapterInfo )==---- +// (Private Member Function) +// Gets the list of adapters on the system and additional +// information for each adapter including its capabilities +//////////////////////////////////// +void Engine3D::RetrieveAdapterInfo() { + + // retrieve adapter list + AdapterCount = d3d->GetAdapterCount(); + adapters = new Adapter[AdapterCount]; + + for(unsigned int i=0; iGetAdapterIdentifier(i, D3DENUM_NO_WHQL_LEVEL, &AdapterIdentifier); + adapters[i].Description = new char[strlen(AdapterIdentifier.Description)+1]; + strcpy(adapters[i].Description, AdapterIdentifier.Description); + adapters[i].Driver = new char[strlen(AdapterIdentifier.Driver)+1]; + strcpy(adapters[i].Driver, AdapterIdentifier.Driver); + + adapters[i].DeviceGUID = AdapterIdentifier.DeviceIdentifier; + adapters[i].DeviceID = AdapterIdentifier.DeviceId; + adapters[i].DriverVersion = AdapterIdentifier.DriverVersion.QuadPart; + adapters[i].Revision = AdapterIdentifier.Revision; + adapters[i].SubSysID = AdapterIdentifier.SubSysId; + adapters[i].VentorID = AdapterIdentifier.VendorId; + + // get a list of display modes for this adapter + LinkedList dmlist; + adapters[i].ModeCount = d3d->GetAdapterModeCount(i); + for(unsigned int j=0; jEnumAdapterModes(i, j, &d3dmode); + mode.XRes = d3dmode.Width; + mode.YRes = d3dmode.Height; + mode.RefreshRate = d3dmode.RefreshRate; + mode.ColorFormat = GetColorDepthFromPixelFormat(d3dmode.Format); + + // check if this mode is supported from the HAL device + D3DFORMAT dispfmt = GetPixelFormatFromColorDepth(mode.ColorFormat, true); + if(d3d->CheckDeviceType(i, D3DDEVTYPE_HAL, dispfmt, d3dmode.Format, false) == D3D_OK) { + dmlist.PushBack(mode); + } + } + adapters[i].ModeCount = dmlist.Size(); // count of the modes that are supported through HW + adapters[i].Modes = new DisplayMode[adapters[i].ModeCount]; + ListNode *iter = dmlist.Begin(); + int j = 0; + while(iter) { + adapters[i].Modes[j++] = iter->data; + iter = iter->next; + } + + // get the device capabilities + d3d->GetDeviceCaps(i, D3DDEVTYPE_HAL, &adapters[i].Capabilities); + int vsver_major = D3DSHADER_VERSION_MAJOR(adapters[i].Capabilities.VertexShaderVersion); + int vsver_minor = D3DSHADER_VERSION_MINOR(adapters[i].Capabilities.VertexShaderVersion); + } +} + +//////////////////////////////////// +// ----==( CreateModesList )==---- +// (Private Member Function) +// Creates a linked list of the available modes +// of a single adapter for further processing +//////////////////////////////////// +LinkedList *Engine3D::CreateModesList(unsigned int AdapterID) const { + + if(AdapterID >= AdapterCount) return 0; + + LinkedList *newlist = new LinkedList; + for(unsigned int i=0; iPushBack(adapters[AdapterID].Modes[i]); + } + return newlist; +} + +//////////////////////////////////// +// ----==( NarrowModesList )==---- +// (Private Member Function) +// Narrows down the list of available modes +// to those that have the requested item +//////////////////////////////////// +void Engine3D::NarrowModesList(LinkedList *list, DisplayModeItem item, long value, long value2) const { + + ListNode *iter = list->Begin(); + while(iter) { + switch(item) { + case ModeItemSize: + if(iter->data.XRes != value || iter->data.YRes != value2) { + iter = list->Erase(iter); + } else { + if(iter) iter = iter->next; + } + break; + + case ModeItemBpp: + if(iter->data.ColorFormat.bpp != value) { + iter = list->Erase(iter); + } else { + if(iter) iter = iter->next; + } + break; + + case ModeItemAlpha: + if(!iter->data.ColorFormat.alpha && value) { + iter = list->Erase(iter); + } else { + if(iter) iter = iter->next; + } + break; + + case ModeItemRefresh: + if(iter->data.RefreshRate != value) { + iter = list->Erase(iter); + } else { + if(iter) iter = iter->next; + } + break; + + default: break; + } + } +} + +/////////////////////////////////// +// ----==( ChooseBestMode )==---- +// (Private Member Function) +// given a (ideally) narrowed down modes list +// choose the best possible among them +/////////////////////////////////// +DisplayMode Engine3D::ChooseBestMode(LinkedList *modes) const { + + DisplayMode dmode; + memset(&dmode, 0, sizeof(DisplayMode)); + + if(!modes || !modes->Size()) return dmode; + + // find the highest resolution and get only the modes with that resolution + ListNode *iter = modes->Begin(); + unsigned int maxx = 0, maxy = 0; + while(iter) { + if(iter->data.XRes > maxx) maxx = iter->data.XRes; + if(iter->data.YRes > maxy) maxy = iter->data.YRes; + iter = iter->next; + } + NarrowModesList(modes, ModeItemSize, maxx, maxy); + + // find the modes with alpha if any + iter = modes->Begin(); + bool AnyWithAlpha = false; + while(iter) { + if(iter->data.ColorFormat.alpha) { + AnyWithAlpha = true; + break; + } + iter = iter->next; + } + if(AnyWithAlpha) NarrowModesList(modes, ModeItemAlpha, 1); + + // find the modes with the highest bpp + iter = modes->Begin(); + int maxbpp = 0; + while(iter) { + if(iter->data.ColorFormat.bpp > maxbpp) maxbpp = iter->data.ColorFormat.bpp; + iter = iter->next; + } + NarrowModesList(modes, ModeItemBpp, maxbpp); + + // find the modes with the highest refresh rate + iter = modes->Begin(); + unsigned int maxrefresh = 0; + while(iter) { + if(iter->data.RefreshRate > maxrefresh) maxrefresh = iter->data.RefreshRate; + iter = iter->next; + } + NarrowModesList(modes, ModeItemRefresh, maxrefresh); + + // if there is more than one mode left, then there is a problem :) + assert(modes->Size() == 1); + + dmode = modes->Begin()->data; + return dmode; +} + +////////////////////////////////////////// +// ----==( CreateGraphicsContext )==---- +// (Public Member Function) +// Creates a graphics context with the specified parameters +////////////////////////////////////////// +GraphicsContext *Engine3D::CreateGraphicsContext(HWND WindowHandle, unsigned int AdapterID, ContextInitParameters *GCParams) { + + if(AdapterID >= AdapterCount) return 0; + + // check adapter's Transformation & Lighting capability + bool hwtnl = (bool)(adapters[AdapterID].Capabilities.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT); + if(!(GCParams->DontCareFlags & GCPDONTCARE_TNL)) { // bit not set, we want specific TnL mode + if(hwtnl != GCParams->HardwareTnL && !hwtnl) return 0; // we asked for hw tnl and is not available + // else either we asked for sw and found hw so we continue with our initial sw setting + // or we found exactly what we asked, so we still continue with our choice + } else { + GCParams->HardwareTnL = hwtnl; // if we don't care use what we have available + } + + // decide which mode to use + LinkedList *modes = CreateModesList(AdapterID); + NarrowModesList(modes, ModeItemSize, GCParams->x, GCParams->y); + + if(!(GCParams->DontCareFlags & GCPDONTCARE_BPP)) { // we want specific bpp + NarrowModesList(modes, ModeItemBpp, GCParams->bpp); + } + + if(!(GCParams->DontCareFlags & GCPDONTCARE_ALPHA)) { // alpha setting exactly as asked + NarrowModesList(modes, ModeItemAlpha, (long)GCParams->AlphaChannel); + } + + if(!(GCParams->DontCareFlags & GCPDONTCARE_REFRESH)) { // specific refresh rate + NarrowModesList(modes, ModeItemRefresh, GCParams->RefreshRate); + } + + if(!modes->Size()) { // didn't find any mode with the properties that we asked + throw EngineInitException("Requested video mode parameters not available"); + } + + DisplayMode mode = ChooseBestMode(modes); + delete modes; // delete the list of modes + + D3DFORMAT PixelFormat = GetPixelFormatFromColorDepth(mode.ColorFormat); + + // find out if we have the requested zbuffer format avaialble + if(!GCParams->DepthBits) GCParams->DepthBits = 32; // not specified, trying highest possible first + D3DFORMAT zfmt = GetDepthStencilFormat(GCParams->DepthBits, true); + + bool res = !(bool)d3d->CheckDeviceFormat(AdapterID, (D3DDEVTYPE)GCParams->DevType, PixelFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, zfmt); + if(!res) { // try a format without stencil + zfmt = GetDepthStencilFormat(GCParams->DepthBits, false); + res = !(bool)d3d->CheckDeviceFormat(AdapterID, (D3DDEVTYPE)GCParams->DevType, PixelFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, zfmt); + } + + if(!res) { // didn't find requested zbuffer even with no stencil + // if we asked for specific zformat and didn't find it or if the zbuffer that + // we failed to set was 16bits and can't go less, bail out + if(!(GCParams->DontCareFlags & GCPDONTCARE_DEPTH) || GCParams->DepthBits == 16) return 0; + + // try to set a smaller zbuffer with stencil + GCParams->DepthBits = 16; + zfmt = GetDepthStencilFormat(GCParams->DepthBits, true); + res = !(bool)d3d->CheckDeviceFormat(AdapterID, (D3DDEVTYPE)GCParams->DevType, PixelFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, zfmt); + if(!res) { // try a format without stencil + zfmt = GetDepthStencilFormat(GCParams->DepthBits, false); + res = !(bool)d3d->CheckDeviceFormat(AdapterID, (D3DDEVTYPE)GCParams->DevType, PixelFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, zfmt); + } + + if(!res) throw EngineInitException("Requested ZBuffer depth not available"); + } + + int AASamples = 0; + if(GCParams->Antialiasing) { + if(GCParams->BestAA) { + // find the best supported AA mode + for(AASamples=16; AASamples > 0; AASamples--) { + long result = d3d->CheckDeviceMultiSampleType(AdapterID, (D3DDEVTYPE)GCParams->DevType, PixelFormat, !GCParams->FullScreen, (D3DMULTISAMPLE_TYPE)AASamples); + if(result == D3D_OK) break; + } + } else { + // check for cheap AA + AASamples = 2; + long result = d3d->CheckDeviceMultiSampleType(AdapterID, (D3DDEVTYPE)GCParams->DevType, PixelFormat, !GCParams->FullScreen, (D3DMULTISAMPLE_TYPE)AASamples); + if(result != D3D_OK) AASamples = 0; + } + + if(!AASamples && !(GCParams->DontCareFlags & GCPDONTCARE_AA)) { + throw EngineInitException("Requested Antialiasing mode not available"); + } + } + + D3DFORMAT FinalColorFormat; + if(GCParams->FullScreen) { + FinalColorFormat = GetPixelFormatFromColorDepth(mode.ColorFormat); + } else { + D3DDISPLAYMODE CurrentMode; + d3d->GetAdapterDisplayMode(AdapterID, &CurrentMode); + FinalColorFormat = CurrentMode.Format; + } + + // if everything went well, now we can set that mode + D3DPRESENT_PARAMETERS d3dppar; + d3dppar.BackBufferWidth = GCParams->x; + d3dppar.BackBufferHeight = GCParams->y; + d3dppar.BackBufferFormat = FinalColorFormat; + d3dppar.BackBufferCount = (unsigned int)GCParams->Buffers; + d3dppar.MultiSampleType = (D3DMULTISAMPLE_TYPE)AASamples; + d3dppar.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dppar.hDeviceWindow = WindowHandle; + d3dppar.Windowed = !GCParams->FullScreen; + d3dppar.EnableAutoDepthStencil = true; + d3dppar.AutoDepthStencilFormat = zfmt; + d3dppar.Flags = 0; + d3dppar.FullScreen_RefreshRateInHz = (GCParams->FullScreen) ? mode.RefreshRate : 0; + if(GCParams->FullScreen) { + d3dppar.FullScreen_PresentationInterval = (GCParams->VSync) ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + } else { + d3dppar.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } + + // create the rendering context + GraphicsContext *gc = new GraphicsContext; + + TnLMode tnlmode = (GCParams->HardwareTnL) ? HardwareTnL : SoftwareTnL; + + long result = d3d->CreateDevice(AdapterID, (D3DDEVTYPE)GCParams->DevType, WindowHandle, tnlmode, &d3dppar, &gc->D3DDevice); + if(result != D3D_OK) { + if(d3dppar.BackBufferCount != GCParams->Buffers) { + if((GCParams->DontCareFlags & GCPDONTCARE_BUFFERS)) { + result = d3d->CreateDevice(AdapterID, (D3DDEVTYPE)GCParams->DevType, WindowHandle, tnlmode, &d3dppar, &gc->D3DDevice); + } else { + throw EngineInitException("Could not create Direct3D device"); + } + } + } + + if(result != D3D_OK) { + throw EngineInitException("Could not create Direct3D device"); + } + + gc->WindowHandle = WindowHandle; + gc->D3DDevice->GetRenderTarget(&gc->MainRenderTarget.ColorSurface); + gc->D3DDevice->GetDepthStencilSurface(&gc->MainRenderTarget.DepthStencilSurface); + gc->ContextParams = *GCParams; + gc->ZFormat = zfmt; + gc->AASamples = AASamples; + gc->ColorFormat = FinalColorFormat; + gc->MaxTextureStages = adapters[AdapterID].Capabilities.MaxSimultaneousTextures; + gc->texman = new TextureManager(gc); + + gc->SetDefaultStates(); + + GraphicsContexts.push_back(gc); + + return gc; +} + +////////////////////////////////////////// +// ----==( CreateGraphicsContext )==---- +// (Public Member Function) +// Creates a graphics context with the specified parameters +// Light version, basic info passed, fills in the rest +////////////////////////////////////////// +GraphicsContext *Engine3D::CreateGraphicsContext(HWND WindowHandle, int x, int y, int bpp, word flags) { + + ContextInitParameters gcp; + gcp.x = x; + gcp.y = y; + gcp.bpp = bpp; + gcp.DepthBits = 24; + gcp.DevType = DeviceHardware; + gcp.FullScreen = (flags & GCCREATE_FULLSCREEN) ? true : false; + gcp.HardwareTnL = true; + gcp.RefreshRate = 75; + gcp.Antialiasing = false; + gcp.Buffers = DoubleBuffering; + gcp.VSync = false; + gcp.DontCareFlags = GCPDONTCARE_DEPTH | GCPDONTCARE_REFRESH | GCPDONTCARE_ALPHA | GCPDONTCARE_VSYNC; + + return CreateGraphicsContext(WindowHandle, D3DADAPTER_DEFAULT, &gcp); +} + +using std::string; +using std::getline; + +string GetValue(string line) { + int nexttoken = (int)line.find("=") + 1; + while(line[++nexttoken] == ' '); + int tokenend = (int)line.find_first_of(" \n\r\t"); + return line.substr(nexttoken, tokenend - nexttoken); +} + +ContextInitParameters Engine3D::LoadContextParamsConfigFile(const char *cfgfilename) { + ContextInitParameters cip; + memset(&cip, 0, sizeof(ContextInitParameters)); + + std::ifstream file(cfgfilename); + if(!file.is_open()) throw EngineInitException("Could not open configuration file"); + + string line; + getline(file, line); + while(!file.eof()) { + if(line[0] != ';' && line[0] != '\n' && line[0] != '\r' && line[0] != ' ') { + int tokenend = (int)line.find(" "); + string token = line.substr(0, tokenend); + + if(token == "fullscreen") { + string value = GetValue(line); + cip.FullScreen = (value == "true") ? true : false; + } else if(token == "resolution") { + string value = GetValue(line); + int x = (int)value.find("x"); + cip.x = atoi(value.substr(0, x).c_str()); + cip.y = atoi(value.substr(x+1, value.size()).c_str()); + } else if(token == "bpp") { + cip.bpp = atoi(GetValue(line).c_str()); + } else if(token == "zbufferdepth") { + cip.DepthBits = atoi(GetValue(line).c_str()); + } else if(token == "device") { + cip.DevType = (GetValue(line) == "ref") ? DeviceReference : DeviceHardware; + } else if(token == "tnl") { + cip.HardwareTnL = (GetValue(line) == "false") ? false : true; + } else if(token == "refresh") { + cip.RefreshRate = atoi(GetValue(line).c_str()); + } else if(token == "antialiasing") { + string value = GetValue(line); + cip.Antialiasing = (value == "none") ? false : true; + if(cip.Antialiasing) { + cip.BestAA = (value == "speed" || value == "low") ? false : true; + } + } else if(token == "flipchain") { + cip.Buffers = (GetValue(line) == "triplebuffering") ? TripleBuffering : DoubleBuffering; + } else if(token == "vsync") { + cip.VSync = (GetValue(line) == "true") ? true : false; + } else if(token == "dontcareabout") { + cip.DontCareFlags = 0; + string flags = GetValue(line); + string part; + while(1) { + int begin = (int)flags.find_first_not_of(", "); + int end = (int)flags.find(",", begin) - begin; + part = flags.substr(begin, end); + //part = flags.substr(0, flags.find(","));// \n\r\t")); + if(part.empty()) break; + if(part == "bpp") cip.DontCareFlags |= GCPDONTCARE_BPP; + if(part == "refresh") cip.DontCareFlags |= GCPDONTCARE_REFRESH; + if(part == "alpha") cip.DontCareFlags |= GCPDONTCARE_ALPHA; + if(part == "zbufferdepth") cip.DontCareFlags |= GCPDONTCARE_DEPTH; + if(part == "tnl") cip.DontCareFlags |= GCPDONTCARE_TNL; + if(part == "flipchain") cip.DontCareFlags |= GCPDONTCARE_BUFFERS; + if(part == "aamode") cip.DontCareFlags |= GCPDONTCARE_AA; + if(part == "vsync") cip.DontCareFlags |= GCPDONTCARE_VSYNC; + int temp = (int)flags.find_first_of(",\n\r"); + if(temp == string::npos) break; + flags.erase(0, temp+1); + } + } + + } + + getline(file, line); + } + + return cip; +} + +void Engine3D::DestroyGraphicsContext(GraphicsContext *gc) { + gc->D3DDevice->Release(); +} + +int Engine3D::GetAdapterCount() const { + return AdapterCount; +} + +const Adapter *Engine3D::GetAdapterInfo(int adapter) const { + return &adapters[adapter]; +} + + +////////////////////////////////////////////////////////////////////////////// +// helper functions + +bool Lock(VertexBuffer *vb, Vertex **data) { + D3DVERTEXBUFFER_DESC desc; + vb->GetDesc(&desc); + dword flags = (desc.Usage & D3DUSAGE_DYNAMIC) ? D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE : 0; + + return (vb->Lock(0, 0, (byte**)data, flags) == D3D_OK); +} + +bool Lock(IndexBuffer *ib, Index **data) { + D3DINDEXBUFFER_DESC desc; + ib->GetDesc(&desc); + dword flags = (desc.Usage & D3DUSAGE_DYNAMIC) ? D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE : 0; + + return (ib->Lock(0, 0, (byte**)data, flags) == D3D_OK); +} + +void Unlock(VertexBuffer *vb) { + vb->Unlock(); +} + +void Unlock(IndexBuffer *ib) { + ib->Unlock(); +} + + +void CreateProjectionMatrix(Matrix4x4 *mat, float yFOV, float Aspect, float NearClip, float FarClip) { + + float h, w, Q; + float xFOV = yFOV * Aspect; + + w = (float)(1.0f/tan(xFOV*0.5f)); // 1/tan(x) == cot(x) + h = (float)(1.0f/tan(yFOV*0.5f)); // 1/tan(x) == cot(x) + Q = FarClip / (FarClip - NearClip); + + /* Projection Matrix + [ w 0.0f 0.0f 0.0f] + |0.0f h 0.0f 0.0f| + |0.0f 0.0f Q 1.0f| + [0.0f 0.0f -Q*NearClip 0.0f] + */ + + mat->ResetIdentity(); + mat->m[0][0] = w; + mat->m[1][1] = h; + mat->m[2][2] = Q; + mat->m[3][2] = -Q*NearClip; + mat->m[2][3] = 1.0f; +} + +dword PackVector(const Vector3 &vec, float Height) { + dword r = (dword)(127.0f * vec.x + 128.0f); + dword g = (dword)(127.0f * vec.y + 128.0f); + dword b = (dword)(127.0f * vec.z + 128.0f); + dword a = (dword)(255.0f * Height); + + return( (a<<24L) + (r<<16L) + (g<<8L) + (b<<0L) ); +} + +void NormalMapFromHeightField(Texture *tex) { + + // Lock the texture + D3DLOCKED_RECT d3dlr; + D3DSURFACE_DESC d3dsd; + + int LevelCount = tex->GetLevelCount(); + for(int i=0; iGetLevelDesc(i, &d3dsd); + tex->LockRect(i, &d3dlr, 0, 0); + DWORD* pPixel = (DWORD*)d3dlr.pBits; + + // For each pixel, generate a vector normal that represents the change + // in thea height field at that pixel + for( DWORD j=0; j> 16) / 255.0f; + float fHeight10 = (float)((color10 & 0x00ff0000) >> 16) / 255.0f; + float fHeight01 = (float)((color01 & 0x00ff0000) >> 16) / 255.0f; + + Vector3 vPoint00(i+0.0f, j+0.0f, fHeight00); + Vector3 vPoint10(i+1.0f, j+0.0f, fHeight10); + Vector3 vPoint01(i+0.0f, j+1.0f, fHeight01); + Vector3 v10 = vPoint10 - vPoint00; + Vector3 v01 = vPoint01 - vPoint00; + + Vector3 Normal = v10.CrossProduct(v01); + Normal.Normalize(); + + // Store the normal as an RGBA value in the normal map + *pPixel++ = PackVector(Normal, fHeight00); + } + } + tex->UnlockRect(i); + } +} + +void UpdateMipmapChain(Texture *tex) { + D3DXFilterTexture(tex, 0, 0, D3DX_FILTER_BOX); +} + +dword AddEdge(Edge *edges, dword EdgeCount, const Edge &newedge) { + // remove internal edges + for(dword i=0; iGetType() == LTDir ? l->GetDirection() : p - l->GetPosition()) +inline Vector3 GetLightDir(const Light *light, const Vector3 &pos, const Matrix4x4 &mat) { + if(light->GetType() == LTDir) { + return light->GetDirection(); + } else { + Vector3 lpos = light->GetPosition(); + lpos.Transform(mat); + return pos - lpos; + } + return Vector3(); +} + + +////////////////////////////////////////// +// ----==( CreateShadowVolume )==---- +// (Helper Function) +// Creates a graphics context with the specified parameters +// Light version, basic info passed, fills in the rest +////////////////////////////////////////// + +TriMesh *CreateShadowVolume(const TriMesh &mesh, const Light *light, const Matrix4x4 &MeshXForm, bool WorldCoords) { + + // transform light into object's local coordinate system + //const_cast(light)->Transform(MeshXForm.Inverse()); + Matrix4x4 InvXForm = MeshXForm.Inverse(); + + const Vertex *varray = mesh.GetVertexArray(); + const Triangle *triarray = mesh.GetTriangleArray(); + + dword VertexCount = mesh.GetVertexCount(); + dword TriangleCount = mesh.GetTriangleCount(); + + Edge *edges = new Edge[TriangleCount]; + dword EdgeCount = 0; + + // first find the contour edges + + for(dword i=0; i= 0.0f) { + EdgeCount = AddEdge(edges, EdgeCount, Edge(triarray[i].vertices[0], triarray[i].vertices[1])); + EdgeCount = AddEdge(edges, EdgeCount, Edge(triarray[i].vertices[1], triarray[i].vertices[2])); + EdgeCount = AddEdge(edges, EdgeCount, Edge(triarray[i].vertices[2], triarray[i].vertices[0])); + } + } + + // now extract the contour edges to build the shadow volume boundrary + const float ExtrudeMagnitude = 100000.0f; + Vertex *ShadowVertices = new Vertex[EdgeCount * 6]; + + for(dword i=0; iSetData(ShadowVertices, 0, EdgeCount * 6, 0); + + delete [] ShadowVertices; + delete [] edges; + + //const_cast(light)->Transform(MeshXForm); // return light to world coordinate system + + return ShadowMesh; +} + + +///////////// local ////////////// + +ColorDepth GetColorDepthFromPixelFormat(D3DFORMAT fmt) { + switch(fmt) { + case D3DFMT_R8G8B8: return ColorDepth(24, 24, 0); + case D3DFMT_A8R8G8B8: return ColorDepth(32, 24, 8); + case D3DFMT_X8R8G8B8: return ColorDepth(32, 24, 0); + case D3DFMT_R5G6B5: return ColorDepth(16, 16, 0); + case D3DFMT_X1R5G5B5: return ColorDepth(16, 15, 0); + case D3DFMT_A1R5G5B5: return ColorDepth(16, 15, 1); + case D3DFMT_P8: return ColorDepth(8, 8, 0); + default: return ColorDepth(0, 0, 0); + } +} + +bool operator ==(const ColorDepth &lhs, const ColorDepth &rhs) { + return (lhs.bpp == rhs.bpp && lhs.colorbits == rhs.colorbits && lhs.alpha == rhs.alpha); +} + +D3DFORMAT GetPixelFormatFromColorDepth(ColorDepth cd, bool noalpha) { + if(cd == ColorDepth(24, 24, 0)) return D3DFMT_R8G8B8; + if(cd == ColorDepth(32, 24, 8)) return noalpha ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; + if(cd == ColorDepth(32, 24, 0)) return D3DFMT_X8R8G8B8; + if(cd == ColorDepth(16, 16, 0)) return D3DFMT_R5G6B5; + if(cd == ColorDepth(16, 15, 0)) return D3DFMT_X1R5G5B5; + if(cd == ColorDepth(16, 15, 1)) return noalpha ? D3DFMT_X1R5G5B5 : D3DFMT_A1R5G5B5; + if(cd == ColorDepth(8, 8, 0)) return D3DFMT_P8; + return (D3DFORMAT)0; +} + + +D3DFORMAT GetDepthStencilFormat(int depthbits, bool stencil) { + switch(depthbits) { + case 32: + return (stencil) ? D3DFMT_D24S8 : D3DFMT_D32; + break; + + case 24: + return (stencil) ? D3DFMT_D24S8 : D3DFMT_D24X8; + break; + + case 16: + return (stencil) ? D3DFMT_D15S1 : D3DFMT_D16; + break; + + default: + break; + } + + return (D3DFORMAT)0; +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/3dengine.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/3dengine.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,391 @@ +#ifndef _3DENGINE_H_ +#define _3DENGINE_H_ + +// standard includes +#include +// system includes +#include "d3d8.h" +// includes from my codebase +#include "typedefs.h" +#include "linkedlist.h" +#include "color.h" +// 3d engine includes +#include "n3dmath.h" +#include "switches.h" +#include "3dengtypes.h" +#include "material.h" +#include "textureman.h" +#include "3dgeom.h" + +enum DeviceType {DeviceHardware = D3DDEVTYPE_HAL, DeviceReference = D3DDEVTYPE_REF}; +enum TnLMode {HardwareTnL = D3DCREATE_HARDWARE_VERTEXPROCESSING, SoftwareTnL = D3DCREATE_SOFTWARE_VERTEXPROCESSING}; +enum BufferChainMode {DoubleBuffering = 1, TripleBuffering = 2}; +enum UsageFlags {UsageStatic = 0, UsageDynamic = D3DUSAGE_DYNAMIC}; +enum ShadeMode {FlatShading = D3DSHADE_FLAT, GouraudShading = D3DSHADE_GOURAUD}; +enum FaceOrder {Clockwise = D3DCULL_CW, CounterClockwise = D3DCULL_CCW}; + +enum PhongComponent {Ambient, Diffuse, Specular}; + +enum PrimitiveType { + TriangleList = D3DPT_TRIANGLELIST, + TriangleStrip = D3DPT_TRIANGLESTRIP, + TriangleFan = D3DPT_TRIANGLEFAN, + LineList = D3DPT_LINELIST, + LineStrip = D3DPT_LINESTRIP, + PointList = D3DPT_POINTLIST +}; + +enum BlendingFactor { + BLEND_ZERO = D3DBLEND_ZERO, + BLEND_ONE = D3DBLEND_ONE, + BLEND_SRCCOLOR = D3DBLEND_SRCCOLOR, + BLEND_INVSRCCOLOR = D3DBLEND_INVSRCCOLOR, + BLEND_SRCALPHA = D3DBLEND_SRCALPHA, + BLEND_INVSRCALPHA = D3DBLEND_INVSRCALPHA, + BLEND_DESTCOLOR = D3DBLEND_DESTCOLOR, + BLEND_INVDESTCOLOR = D3DBLEND_INVDESTCOLOR, + BLEND_DESTALPHA = D3DBLEND_DESTALPHA, + BLEND_INVDESTALPHA = D3DBLEND_INVDESTALPHA, + BLEND_SRCALPHASAT = D3DBLEND_SRCALPHASAT +}; + +enum CmpFunc { + CMP_NEVER = D3DCMP_NEVER, + CMP_LESS = D3DCMP_LESS, + CMP_EQUAL = D3DCMP_EQUAL, + CMP_LEQUAL = D3DCMP_LESSEQUAL, + CMP_GREATER = D3DCMP_GREATER, + CMP_NOTEQUAL = D3DCMP_NOTEQUAL, + CMP_GEQUAL = D3DCMP_GREATEREQUAL, + CMP_ALWAYS = D3DCMP_ALWAYS +}; + +enum StencilOp { + SOP_KEEP = D3DSTENCILOP_KEEP, + SOP_ZERO = D3DSTENCILOP_ZERO, + SOP_REPLACE = D3DSTENCILOP_REPLACE, + SOP_INCSAT = D3DSTENCILOP_INCRSAT, + SOP_DECSAT = D3DSTENCILOP_DECRSAT, + SOP_INVERT = D3DSTENCILOP_INVERT, + SOP_INC = D3DSTENCILOP_INCR, + SOP_DEC = D3DSTENCILOP_DECR +}; + +enum TextureBlendFunction { + TexBlendSelectArg1 = D3DTOP_SELECTARG1, // S[rgba] = Arg1 + TexBlendSelectArg2 = D3DTOP_SELECTARG2, // S[rgba] = Arg2 + TexBlendAdd = D3DTOP_ADD, // S[rgba] = Arg1 + Arg2 + TexBlendAddSigned = D3DTOP_ADDSIGNED, // S[rgba] = Arg1 + Arg2 - 0.5 + TexBlendAddSigned2x = D3DTOP_ADDSIGNED2X, // S[rgba] = (Arg1 + Arg2 - 0.5) << 1 + TexBlendSubtract = D3DTOP_SUBTRACT, // S[rgba] = Arg1 - Arg2 + TexBlendAddSmooth = D3DTOP_ADDSMOOTH, // S[rgba] = (Arg1 + Arg2) - (Arg1 * Arg2) + TexBlendModulate = D3DTOP_MODULATE, // S[rgba] = Arg1 * Arg2 + TexBlendModulate2x = D3DTOP_MODULATE2X, // S[rgba] = (Arg1 * Arg2) << 1 + TexBlendModulate4x = D3DTOP_MODULATE4X, // S[rgba] = (Arg1 * Arg2) << 2 + TexBlendVertexAlpha = D3DTOP_BLENDDIFFUSEALPHA, // S[rgba] = Arg1*Alpha + Arg2*(1-Alpha) + TexBlendTextureAlpha = D3DTOP_BLENDTEXTUREALPHA, // S[rgba] = Arg1*Alpha + Arg2*(1-Alpha) + TexBlendFactorAlpha = D3DTOP_BLENDFACTORALPHA, // S[rgba] = Arg1*Alpha + Arg2*(1-Alpha) + TexBlendPrevAlpha = D3DTOP_BLENDFACTORALPHA, // S[rgba] = Arg1*Alpha + Arg2*(1-Alpha) + TexBlendPreMulAlpha = D3DTOP_BLENDTEXTUREALPHAPM, // S[rgba] = Arg1 + Arg2*(1-Alpha) + TexBlendPreModulate = D3DTOP_PREMODULATE, + TexBlendModAlphaAddColor = D3DTOP_MODULATEALPHA_ADDCOLOR,// S[rgba] = Arg1[rgb] + Arg1[a] * Arg2[rgb] + TexBlendModulateAddAlpha = D3DTOP_MODULATECOLOR_ADDALPHA,// S[rgba] = Arg1[rgb] * Arg2[rgb] + Arg1[a] + TexBlendModInvAlphaAddColor = D3DTOP_MODULATEINVALPHA_ADDCOLOR, // S[rgba] = Arg1[rgb] + (1-Arg1[a]) * Arg2[rgb] + TexBlendModulateInvAddAlpha = D3DTOP_MODULATEINVCOLOR_ADDALPHA, // S[rgba] = (1-Arg1[rgb]) * Arg2[rgb] + Arg1[a] + TexBlendBumpEnv = D3DTOP_BUMPENVMAP, // bump mapping with next stage's env map + TexBlendBumpEnvLuminance = D3DTOP_BUMPENVMAPLUMINANCE, // bump mapping with next stage's env map with luminance + TexBlendDotProduct = D3DTOP_DOTPRODUCT3, // S[rgba] = Arg1[rgb] (dot) Arg2[rgb] + TexBlendMultiplyAdd = D3DTOP_MULTIPLYADD, // S[rgba] = Arg1 + Arg2 * Arg3 + TexBlendLerp = D3DTOP_LERP // S[rgba] = Arg2 + (Arg3 - Arg2) * Arg1 +}; + +enum TextureBlendArgument { + TexArgNone = 0, // valid only for arg3 + TexArgCurrent = D3DTA_CURRENT, // the color from the previous stage output (diffuse for 1st) + TexArgDiffuseColor = D3DTA_DIFFUSE, // the diffuse interpolated color + TexArgSpecularColor = D3DTA_SPECULAR, // the specular interpolated color + TexArgTexture = D3DTA_TEXTURE, // the texture bound to this stage + TexArgFactor = D3DTA_TFACTOR, // a user defined factor + TexArgTemp = D3DTA_TEMP // temp register +}; + +enum TextureFilteringType { + PointSampling, + BilinearFiltering, + TrilinearFiltering, + AnisotropicFiltering +}; + +enum TextureAddressing { + TexAddrWrap = D3DTADDRESS_WRAP, + TexAddrMirror = D3DTADDRESS_MIRROR, + TexAddrClamp = D3DTADDRESS_CLAMP, + TexAddrBorder = D3DTADDRESS_BORDER, + TexAddrMirrorOnce = D3DTADDRESS_MIRRORONCE +}; + +enum TexTransformState { + TexTransformDisable = D3DTTFF_DISABLE, + TexTransform1D = D3DTTFF_COUNT1, + TexTransform2D = D3DTTFF_COUNT2, + TexTransform3D = D3DTTFF_COUNT3, + TexTransform4D = D3DTTFF_COUNT4, + TexTransformProjected = D3DTTFF_PROJECTED +}; + +// don't care flags for context creation +const unsigned short GCPDONTCARE_NONE = 0; // 0000000000000000 +const unsigned short GCPDONTCARE_BPP = 1; // 0000000000000001 +const unsigned short GCPDONTCARE_REFRESH = 2; // 0000000000000010 +const unsigned short GCPDONTCARE_ALPHA = 4; // 0000000000000100 +const unsigned short GCPDONTCARE_DEPTH = 8; // 0000000000001000 +const unsigned short GCPDONTCARE_TNL = 16; // 0000000000010000 +const unsigned short GCPDONTCARE_BUFFERS = 32; // 0000000000100000 +const unsigned short GCPDONTCARE_AA = 64; // 0000000001000000 +const unsigned short GCPDONTCARE_VSYNC = 128; // 0000000010000000 + +// fullscreen / windowed flags +const unsigned short GCCREATE_WINDOWED = 0; +const unsigned short GCCREATE_FULLSCREEN = 1; + + + +class Vertex; + +struct ColorDepth { + int bpp, colorbits, alpha; + + ColorDepth(int bits=0, int c=0, int a=0) {colorbits = c; alpha = a; bpp = bits; } +}; + +struct DisplayMode { + unsigned int XRes, YRes, RefreshRate; + ColorDepth ColorFormat; +}; + +enum DisplayModeItem {ModeItemSize, ModeItemBpp, ModeItemAlpha, ModeItemRefresh}; + +struct Adapter { + char *Driver, *Description; + int64 DriverVersion; + dword VentorID, DeviceID, SubSysID, Revision; + GUID DeviceGUID; + + unsigned int ModeCount; + DisplayMode *Modes; + D3DCAPS8 Capabilities; +}; + +struct RenderTarget { + Surface *ColorSurface, *DepthStencilSurface; +}; + +struct RenderParams { + ShadeMode Shading; + bool Billboarded; + dword VertexProgram; + dword PixelProgram; + bool ZWrite; + BlendingFactor SourceBlendFactor, DestBlendFactor; +}; + +struct ContextInitParameters { + int x, y; + int bpp; + int RefreshRate; + bool AlphaChannel; + int DepthBits; + DeviceType DevType; + bool HardwareTnL; + bool FullScreen; + bool Antialiasing; + bool BestAA; + bool VSync; + BufferChainMode Buffers; + unsigned short DontCareFlags; +}; + + +class GraphicsContext { +private: + PrimitiveType ptype; + FaceOrder CullOrder; + bool BackfaceCulling; + bool MipMapEnabled; + bool BillBoardingEnabled; + dword MipFilter; + + // cache of current transformation matrices + Matrix4x4 WorldMat[256], ViewMat, ProjMat, TexMat[8]; + + // disable copying contexts by making copy constructor and assignment private + GraphicsContext(const GraphicsContext &gc); + const GraphicsContext &operator =(const GraphicsContext &gc); + +public: + HWND WindowHandle; + RenderTarget MainRenderTarget; + IDirect3DDevice8 *D3DDevice; + ContextInitParameters ContextParams; + D3DFORMAT ColorFormat, ZFormat; + int AASamples; + int MaxTextureStages; + + TextureManager *texman; // texture manager + + GraphicsContext(); + + void SetDefaultStates(); + + bool CreateVertexBuffer(uint32 VertexCount, UsageFlags usage, VertexBuffer **vb) const; + bool CreateIndexBuffer(uint32 IndexCount, UsageFlags usage, IndexBuffer **ib) const; + + bool CreateSurface(uint32 Width, uint32 Height, Surface **surf) const; + bool CreateDepthStencil(uint32 Width, uint32 Height, Surface **zsurf) const; + + void Clear(dword color) const; + void ClearZBuffer(float zval) const; + void ClearStencil(byte sval) const; + void ClearZBufferStencil(float zval, byte sval) const; + + void Flip() const; + + bool Draw(VertexBuffer *vb); + bool Draw(Vertex *varray, unsigned int VertexCount); + bool Draw(VertexBuffer *vb, IndexBuffer *ib); + bool Draw(Vertex *varray, Index *iarray, unsigned int VertexCount, unsigned int IndexCount); + bool Draw(Vertex *varray, Triangle *triarray, unsigned int VertexCount, unsigned int TriCount); + + IDirect3DDevice8 *GetDevice() const; + int GetTextureStageNumber() const {return MaxTextureStages;} + + ////// render states ////// + void SetPrimitiveType(PrimitiveType pt); + void SetBackfaceCulling(bool enable); + void SetFrontFace(FaceOrder order); + void SetAutoNormalize(bool enable); + void SetBillboarding(bool enable); + void SetColorWrite(bool red, bool green, bool blue, bool alpha); + + // blending states + void SetAlphaBlending(bool enable); + void SetBlendFunc(BlendingFactor src, BlendingFactor dest); + + // zbuffer states + void SetZBuffering(bool enable); + void SetZWrite(bool enable); + void SetZFunc(CmpFunc func); + + // set stencil buffer states + void SetStencilBuffering(bool enable); + void SetStencilPassOp(StencilOp sop); + void SetStencilFailOp(StencilOp sop); + void SetStencilPassZFailOp(StencilOp sop); + void SetStencilOp(StencilOp Fail, StencilOp StencilPassZFail, StencilOp Pass); + void SetStencilFunc(CmpFunc func); + void SetStencilReference(dword value); + + // texture & material states + void SetTextureFiltering(TextureFilteringType texfilter, int TextureStage = 0xa11); + void SetTextureAddressing(TextureAddressing uaddr, TextureAddressing vaddr, int TextureStage = 0xa11); + void SetTextureBorderColor(dword color, int TextureStage = 0xa11); + void SetTexture(int index, Texture *tex); + void SetTextureFactor(dword factor); + void SetMipMapping(bool enable, int TextureStage = 0xa11); + void SetMaterial(const Material &mat); + + void BlitTexture(const Texture *texture, RECT *rect, const Color &col = Color(1.0f)); + + // multitexturing interface + void EnableTextureStage(int stage); + void DisableTextureStage(int stage); + void SetTextureStageColor(int stage, TextureBlendFunction op, TextureBlendArgument arg1, TextureBlendArgument arg2, TextureBlendArgument arg3 = TexArgNone); + void SetTextureStageAlpha(int stage, TextureBlendFunction op, TextureBlendArgument arg1, TextureBlendArgument arg2, TextureBlendArgument arg3 = TexArgNone); + void SetTextureCoordIndex(int stage, int index); + void SetTextureTransformState(int stage, TexTransformState TexXForm); + //void SetTextureCoordGenerator(int stage, TexGen tgen); + + // programmable interface + void SetVertexProgram(dword vs); + void SetPixelProgram(dword ps); + + dword CreateVertexProgram(const char *fname); + void DestroyVertexProgram(dword vprog); + void SetVertexProgramConstant(dword creg, float val); + void SetVertexProgramConstant(dword creg, const Vector3 &val); + void SetVertexProgramConstant(dword creg, const Vector4 &val); + void SetVertexProgramConstant(dword creg, const Color &val); + void SetVertexProgramConstant(dword creg, const Matrix4x4 &val); + void SetVertexProgramConstant(dword creg, const void *data, dword size); + + + // lighting states + void SetLighting(bool enable); + void SetColorVertex(bool enable); + void SetAmbientLight(Color AmbientColor); + void SetShadingMode(ShadeMode mode); + void SetSpecular(bool enable); + + // Transformation Matrices + void SetWorldMatrix(const Matrix4x4 &WorldMat, unsigned int BlendIndex = 0); + void SetViewMatrix(const Matrix4x4 &ViewMat); + void SetProjectionMatrix(const Matrix4x4 &ProjMat); + void SetTextureMatrix(const Matrix4x4 &TexMat, unsigned int TextureStage = 0); + void SetViewport(unsigned int x, unsigned int y, unsigned int xsize, unsigned int ysize, float MinZ = 0.0f, float MaxZ = 1.0f); + + const Matrix4x4 &GetWorldMatrix(unsigned int BlendIndex = 0); + const Matrix4x4 &GetViewMatrix(); + const Matrix4x4 &GetProjectionMatrix(); + const Matrix4x4 &GetTextureMatrix(unsigned int TextureStage = 0); + + // render target + void ResetRenderTarget(); + void SetRenderTarget(RenderTarget &rtarg); + void SetRenderTarget(Texture *rtarg, Texture *ztarg); + void SetRenderTarget(Texture *rtarg, Surface *ztarg); + //RenderTarget GetRenderTarget() const; +}; + + + +class Engine3D { +private: + IDirect3D8 *d3d; + unsigned int AdapterCount; + Adapter *adapters; // array of adapters (filled in at the constructor) + std::vector GraphicsContexts; // a list of active graphics contexts + + void RetrieveAdapterInfo(); + LinkedList *CreateModesList(unsigned int AdapterID) const; + void NarrowModesList(LinkedList *list, DisplayModeItem item, long value, long value2=0) const; + DisplayMode ChooseBestMode(LinkedList *modes) const; + int MaxAntialiasingSamples() const; + +public: + + Engine3D(); + ~Engine3D(); + + int GetAdapterCount() const; + const Adapter *GetAdapterInfo(int adapter) const; + + GraphicsContext *CreateGraphicsContext(HWND WindowHandle, int x, int y, int bpp, word flags); + GraphicsContext *CreateGraphicsContext(HWND WindowHandle, unsigned int AdapterID, ContextInitParameters *GCParams); + ContextInitParameters LoadContextParamsConfigFile(const char *cfgfilename); + + void DestroyGraphicsContext(GraphicsContext *gc); +}; + +class Light; + +// helper functions +bool Lock(VertexBuffer *vb, Vertex **data); +bool Lock(IndexBuffer *ib, Index **data); +void Unlock(VertexBuffer *vb); +void Unlock(IndexBuffer *ib); +void CreateProjectionMatrix(Matrix4x4 *mat, float yFOV, float Aspect, float NearClip, float FarClip); +void NormalMapFromHeightField(Texture *tex); +void UpdateMipmapChain(Texture *tex); +TriMesh *CreateShadowVolume(const TriMesh &mesh, const Light *light, const Matrix4x4 &MeshXForm, bool WorldCoords = false); + +#endif // _3DENGINE_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/3dengtypes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/3dengtypes.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,22 @@ +#ifndef _3DENGTYPES_H_ +#define _3DENGTYPES_H_ + +#include "d3d8.h" +#include "typedefs.h" + +typedef IDirect3DSurface8 Surface; +typedef IDirect3DTexture8 Texture; +typedef IDirect3DVertexBuffer8 VertexBuffer; +typedef IDirect3DIndexBuffer8 IndexBuffer; + +#define FixedFunction VertexFormat + +//const dword VertexFormat = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX4; +//const dword VertexFormat = D3DFVF_XYZ | D3DFVF_XYZB1 | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX4; +const dword VertexFormat = D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4 | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX4; +const D3DFORMAT IndexFormat = D3DFMT_INDEX16; +const dword IndexSize = 2; +typedef uint16 Index; + + +#endif // _3DENGTYPES_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/3dgeom.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/3dgeom.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,478 @@ +#include +#include "3dgeom.h" +#include "3dengine.h" + +using std::vector; + +TexCoord::TexCoord(float u, float v) { + this->u = u; + this->v = v; +} + +// Vertex class implementation + +Vertex::Vertex() { + color = 0x00ffffff; + memset(tex, 0, 4*sizeof(TexCoord)); +} + +Vertex::Vertex(const Vector3 &position, float tu, float tv, dword color) { + pos = position; + tex[0].u = tex[1].u = tex[2].u = tex[3].u = tu; + tex[0].v = tex[1].v = tex[2].v = tex[3].v = tv; + this->color = color; +} + +void Vertex::CalculateNormal(const Vertex *vbuffer, const Triangle *triangles, long trinum) { + + // find the position of the curent vertex in the vertex buffer + dword index = (dword)(this - vbuffer); + + normal = Vector3(0, 0, 0); + const Triangle *tri = triangles; + for(int i=0; ivertices[0] == index || tri->vertices[1] == index || tri->vertices[2] == index) { + normal += tri->normal; + } + } + + normal.Normalize(); +} + +/////////// Edge class implementation /////////// + +Edge::Edge() { + vertices[0] = vertices[1] = adjfaces[0] = adjfaces[1] = 0; +} + +Edge::Edge(Index v1, Index v2, Index af1, Index af2) { + vertices[0] = v1; + vertices[1] = v2; + adjfaces[0] = af1; + adjfaces[1] = af2; +} + +/////////// Triangle class implementation ///////////// +Triangle::Triangle(Index v1, Index v2, Index v3) { + vertices[0] = v1; + vertices[1] = v2; + vertices[2] = v3; +} + +void Triangle::CalculateNormal(Vertex *vbuffer, bool normalize) { + Vector3 v1 = vbuffer[vertices[1]].pos - vbuffer[vertices[0]].pos; + Vector3 v2 = vbuffer[vertices[2]].pos - vbuffer[vertices[0]].pos; + normal = v1.CrossProduct(v2); + if(normalize) normal.Normalize(); +} + + +/////////////// Triangular Mesh implementation ///////////// + +TriMesh::TriMesh(byte LODLevels, GraphicsContext *gc) { + memset(this, 0, sizeof(TriMesh)); + this->gc = gc; + Levels = LODLevels; + + varray = new Vertex*[Levels]; + memset(varray, 0, Levels * sizeof(Vertex*)); + + triarray = new Triangle*[Levels]; + memset(triarray, 0, Levels * sizeof(Triangle*)); + + vbuffer = new VertexBuffer*[Levels]; + memset(vbuffer, 0, Levels * sizeof(VertexBuffer*)); + + ibuffer = new IndexBuffer*[Levels]; + memset(ibuffer, 0, Levels * sizeof(IndexBuffer*)); + + AdjTriangles = new std::vector*[Levels]; + memset(AdjTriangles, 0, Levels * sizeof(std::vector*)); + + VertexCount = new dword[Levels]; + TriCount = new dword[Levels]; + + BuffersValid = new bool[Levels]; + memset(BuffersValid, 0, Levels * sizeof(bool)); + + AdjValid = new bool[Levels]; + memset(AdjValid, 0, Levels * sizeof(bool)); +} + +TriMesh::TriMesh(const TriMesh &mesh) { + + memcpy(this, &mesh, sizeof(TriMesh)); + + BuffersValid = new bool[Levels]; + memset(BuffersValid, 0, Levels * sizeof(bool)); + + varray = new Vertex*[Levels]; + triarray = new Triangle*[Levels]; + vbuffer = new VertexBuffer*[Levels]; + ibuffer = new IndexBuffer*[Levels]; + + VertexCount = new dword[Levels]; + TriCount = new dword[Levels]; + + for(int i=0; iRelease(); + } + } + if(ibuffer) { + for(int i=0; iRelease(); + } + } + + if(AdjTriangles) { + for(int i=0; i= Levels) return 0; + return varray[level]; +} + +const Triangle *TriMesh::GetTriangleArray(byte level) const { + if(level >= Levels) return 0; + return triarray[level]; +} + + +Vertex *TriMesh::GetModVertexArray() { + memset(BuffersValid, 0, Levels * sizeof(bool)); + return varray[0]; +} + +Triangle *TriMesh::GetModTriangleArray() { + memset(BuffersValid, 0, Levels * sizeof(bool)); + memset(AdjValid, 0, Levels * sizeof(bool)); + return triarray[0]; +} + +const VertexBuffer *TriMesh::GetVertexBuffer(byte level) const { + if(level >= Levels) return 0; + + if(!BuffersValid[level]) { + const_cast(this)->UpdateSystemBuffers(level); + } + return vbuffer[level]; +} + +const IndexBuffer *TriMesh::GetIndexBuffer(byte level) const { + if(level >= Levels) return 0; + + if(!BuffersValid[level]) { + const_cast(this)->UpdateSystemBuffers(level); + } + + return ibuffer[level]; +} + + +dword TriMesh::GetVertexCount(byte level) const { + if(level >= Levels) return 0xdeadbeef; + return VertexCount[level]; +} + +dword TriMesh::GetTriangleCount(byte level) const { + if(level >= Levels) return 0xdeadbeef; + return TriCount[level]; +} + +byte TriMesh::GetLevelCount() const { + return Levels; +} + +void TriMesh::SetGraphicsContext(GraphicsContext *gc) { + this->gc = gc; + memset(BuffersValid, 0, Levels * sizeof(bool)); // invalidate all system buffers in all levels +} + +void TriMesh::SetData(const Vertex *vdata, const Triangle *tridata, dword vcount, dword tricount) { + + memset(BuffersValid, 0, Levels * sizeof(bool)); + memset(AdjValid, 0, Levels * sizeof(bool)); + + if(varray[0]) delete [] varray[0]; + if(triarray[0]) delete [] triarray[0]; + varray[0] = new Vertex[vcount]; + triarray[0] = new Triangle[tricount]; + + if(vdata) memcpy(varray[0], vdata, vcount * sizeof(Vertex)); + if(tridata) memcpy(triarray[0], tridata, tricount * sizeof(Triangle)); + VertexCount[0] = vcount; + TriCount[0] = tricount; + + UpdateLODChain(); +} + +bool TriMesh::UpdateSystemBuffers(byte level) { + + if(!gc || level >= Levels) return false; + + if(vbuffer[level]) { + D3DVERTEXBUFFER_DESC vbdesc; + vbuffer[level]->GetDesc(&vbdesc); + if(vbdesc.Size / sizeof(Vertex) != VertexCount[level]) { + vbuffer[level]->Release(); + + if(gc->D3DDevice->CreateVertexBuffer(VertexCount[level] * sizeof(Vertex), dynamic ? D3DUSAGE_DYNAMIC : 0, VertexFormat, D3DPOOL_DEFAULT, &vbuffer[level]) != D3D_OK) { + return false; + } + } + } else { + if(gc->D3DDevice->CreateVertexBuffer(VertexCount[level] * sizeof(Vertex), dynamic ? D3DUSAGE_DYNAMIC : 0, VertexFormat, D3DPOOL_DEFAULT, &vbuffer[level]) != D3D_OK) { + return false; + } + } + + Vertex *vbdata; + Lock(vbuffer[level], &vbdata); + memcpy(vbdata, varray[level], VertexCount[level] * sizeof(Vertex)); + Unlock(vbuffer[level]); + + if(ibuffer[level]) { + D3DINDEXBUFFER_DESC ibdesc; + ibuffer[level]->GetDesc(&ibdesc); + if(ibdesc.Size / IndexSize != TriCount[level] * 3) { + ibuffer[level]->Release(); + + if(gc->D3DDevice->CreateIndexBuffer(TriCount[level] * 3 * IndexSize, dynamic ? D3DUSAGE_DYNAMIC : 0, IndexFormat, D3DPOOL_DEFAULT, &ibuffer[level]) != D3D_OK) { + return false; + } + } + } else { + if(gc->D3DDevice->CreateIndexBuffer(TriCount[level] * 3 * IndexSize, dynamic ? D3DUSAGE_DYNAMIC : 0, IndexFormat, D3DPOOL_DEFAULT, &ibuffer[level]) != D3D_OK) { + return false; + } + } + + + Index *ibdata; + Lock(ibuffer[level], &ibdata); + for(dword i=0; i[VertexCount[0]]; + } + + for(dword i=0; iCalculateNormal(varray[0], true); + varray[0][tri->vertices[0]].normal = tri->normal; + varray[0][tri->vertices[1]].normal = tri->normal; + varray[0][tri->vertices[2]].normal = tri->normal; + tri++; + } + + UpdateLODChain(); +} + +void TriMesh::ChangeMode(TriMeshMode mode) { + dynamic = mode == TriMeshDynamic; +} + +/* + +void TriMesh::CalculateEdges() { + + //build a list of triangles that share each vertex + std::list *ShareTris = new std::list[VertexCount[0]]; + + for(dword i=0; iedges[j].vertices[0] = tri->vertices[j]; + tri->edges[j].vertices[1] = tri->vertices[(j+1) % 3]; + tri->edges[j].adjfaces[0] = (Index)i; + } + + for(int j=0; j<3; j++) { + Index v0 = (Index)((Vertex*)&varray[0][tri->edges[j].vertices[0]] - (Vertex*)&varray[0][0]); + Index v1 = (Index)((Vertex*)&varray[0][tri->edges[j].vertices[1]] - (Vertex*)&varray[0][0]); + + std::list::iterator iter = ShareTris[v0].begin(); + while(iter != ShareTris[v0].end()) { + Index TriIndex = (Index)(*iter - &triarray[0][0]); + + if((TriIndex != i) && ((*iter)->vertices[0] == v1 || (*iter)->vertices[1] == v1 || (*iter)->vertices[2] == v1)) { + tri->edges[j].adjfaces[1] = TriIndex; + break; + } + iter++; + } + if(iter == ShareTris[v0].end()) tri->edges[j].adjfaces[1] = (Index)0xffffffff; + } + } + + // TODO: wield duplicate edges +} + +*/ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/3dgeom.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/3dgeom.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,112 @@ +#ifndef _3DGEOM_H_ +#define _3DGEOM_H_ + +#include +#include "n3dmath.h" +#include "3dengtypes.h" +#include "switches.h" + +struct TexCoord { + float u, v; + + TexCoord(float u = 0.0f, float v = 0.0f); +}; + +class Triangle; // fwd declaration + +class Vertex { +public: + Vector3 pos; + float BlendFactor; + dword BlendIndex; + Vector3 normal; + dword color; + TexCoord tex[4]; + + Vertex(); + Vertex(const Vector3 &position, float tu = 0.0f, float tv = 0.0f, dword color = 0x00ffffff); + + void CalculateNormal(const Vertex *vbuffer, const Triangle *triangles, long trinum); +}; + + +class Edge { +public: + Index vertices[2]; + Index adjfaces[2]; + + Edge(); + Edge(Index v1, Index v2, Index af1 = 0, Index af2 = 0); +}; + + +class Triangle { +public: + Index vertices[3]; + Vector3 normal; + dword SmoothingGroup; + + Triangle(Index v1 = 0, Index v2 = 0, Index v3 = 0); + + void CalculateNormal(Vertex *vbuffer, bool normalize=0); +}; + + +enum TriMeshMode {TriMeshDynamic, TriMeshStatic}; + +class GraphicsContext; + +class TriMesh { +private: + GraphicsContext *gc; + + // LOD arrays of vertex and triangle arrays for the mesh + Vertex **varray; + Triangle **triarray; + // system managed copy of the data (probably on the video ram or something) + VertexBuffer **vbuffer; + IndexBuffer **ibuffer; + + std::vector **AdjTriangles; + bool *AdjValid; + + dword *VertexCount, *TriCount; + byte Levels; + + bool *BuffersValid; + bool dynamic; + + // synchronizes the system managed copy of vertices/indices with the local data + bool UpdateSystemBuffers(byte level); + void UpdateLODChain(); + +public: + TriMesh(byte LODLevels, GraphicsContext *gc = 0); + TriMesh(const TriMesh &mesh); + ~TriMesh(); + + const TriMesh &operator =(const TriMesh &mesh); + + const Vertex *GetVertexArray(byte level = 0) const; + const Triangle *GetTriangleArray(byte level = 0) const; + + Vertex *GetModVertexArray(); + Triangle *GetModTriangleArray(); + + const VertexBuffer *GetVertexBuffer(byte level = 0) const; + const IndexBuffer *GetIndexBuffer(byte level = 0) const; + + dword GetVertexCount(byte level = 0) const; + dword GetTriangleCount(byte level = 0) const; + byte GetLevelCount() const; + + void ChangeMode(TriMeshMode mode); + void SetGraphicsContext(GraphicsContext *gc); + void SetData(const Vertex *vdata, const Triangle *tridata, dword vcount, dword tricount); + + void CalculateNormals(); + void CalculateNormalsFast(); + //void CalculateEdges(); +}; + +#endif // _3DGEOM_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/3dscene.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/3dscene.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,351 @@ +#include +#include "3dscene.h" + +using std::string; + +Scene::Scene(GraphicsContext *gc) { + this->gc = gc; + + ActiveCamera = 0; + Shadows = false; + LightHalos = false; + HaloSize = 10.0f; + UseFog = false; + + memset(lights, 0, 8 * sizeof(Light*)); + + AmbientLight = Color(0.0f, 0.0f, 0.0f); + ManageData = true; +} + +Scene::~Scene() { + + if(ManageData) { + std::list::iterator obj = objects.begin(); + while(obj != objects.end()) { + delete *obj++; + } + + std::list::iterator cam = cameras.begin(); + while(cam != cameras.end()) { + delete *cam++; + } + + for(int i=0; i<8; i++) { + delete lights[i]; + } + + std::list::iterator citer = curves.begin(); + while(citer != curves.end()) { + delete *citer++; + } + + std::list::iterator sv = StaticShadowVolumes.begin(); + while(sv != StaticShadowVolumes.end()) { + delete (*sv++).shadow_mesh; + } + } + +} + +void Scene::SetGraphicsContext(GraphicsContext *gc) { + this->gc = gc; +} + +void Scene::AddCamera(Camera *cam) { + cameras.push_back(cam); + if(!ActiveCamera) ActiveCamera = cam; +} + +void Scene::AddLight(Light *light) { + for(int i=0; i<8; i++) { + if(!lights[i]) { + lights[i] = light; + break; + } + } +} + +void Scene::AddObject(Object *obj) { + if(obj->material.Alpha < 1.0f) { + objects.push_back(obj); + } else { + objects.push_front(obj); + } +} + +void Scene::AddStaticShadowVolume(TriMesh *mesh, const Light *light) { + ShadowVolume svol; + svol.shadow_mesh = mesh; + svol.light = light; + StaticShadowVolumes.push_back(svol); +} + +void Scene::AddCurve(Curve *curve) { + curves.push_back(curve); +} + + +void Scene::RemoveObject(const Object *obj) { + std::list::iterator iter = objects.begin(); + while(iter != objects.end()) { + if(obj == *iter) { + objects.erase(iter); + return; + } + iter++; + } +} + +void Scene::RemoveLight(const Light *light) { + for(int i=0; i<8; i++) { + if(light = lights[i]) { + lights[i] = 0; + return; + } + } +} + + +Camera *Scene::GetCamera(const char *name) { + std::list::iterator iter = cameras.begin(); + while(iter != cameras.end()) { + if(!strcmp((*iter)->name.c_str(), name)) return *iter; + iter++; + } + return 0; +} + +Light *Scene::GetLight(const char *name) { + for(int i=0; i<8; i++) { + if(!strcmp(lights[i]->name.c_str(), name)) return lights[i]; + } + return 0; +} + +Object *Scene::GetObject(const char *name) { + std::list::iterator iter = objects.begin(); + while(iter != objects.end()) { + if(!strcmp((*iter)->name.c_str(), name)) return *iter; + iter++; + } + return 0; +} + +Curve *Scene::GetCurve(const char *name) { + std::list::iterator iter = curves.begin(); + while(iter != curves.end()) { + if(!strcmp((*iter)->name.c_str(), name)) return *iter; + iter++; + } + return 0; +} + + +std::list *Scene::GetObjectsList() { + return &objects; +} + + +void Scene::SetActiveCamera(Camera *cam) { + ActiveCamera = cam; +} + +Camera *Scene::GetActiveCamera() const { + return ActiveCamera; +} + +void Scene::SetShadows(bool enable) { + Shadows = enable; +} + +void Scene::SetHaloDrawing(bool enable) { + LightHalos = enable; +} + +void Scene::SetHaloSize(float size) { + HaloSize = size; +} + +void Scene::SetAmbientLight(Color ambient) { + AmbientLight = ambient; +} + +Color Scene::GetAmbientLight() const { + return AmbientLight; +} + +void Scene::SetFog(bool enable, Color FogColor, float Near, float Far) { + UseFog = enable; + if(enable) { + this->FogColor = FogColor; + NearFogRange = Near; + FarFogRange = Far; + } +} + + +void Scene::SetupLights() const { + int LightIndex = 0; + for(int i=0; i<8; i++) { + if(lights[i]) { + lights[i]->SetLight(LightIndex++, gc); + } + } + gc->D3DDevice->LightEnable(LightIndex, false); +} + + +void Scene::RenderShadows() const { + + for(int i=0, slight=0; i<8; i++) { + if(!lights[i] || !lights[i]->GetShadowCasting()) continue; + + // disable shadow casting light and render the scene (first pass) + gc->SetAlphaBlending(true); + gc->D3DDevice->LightEnable(i, false); + std::list::const_iterator iter = objects.begin(); + while(iter != objects.end()) { + Object *obj = *iter++; + obj->Render(); + } + gc->D3DDevice->LightEnable(i, true); + gc->SetAlphaBlending(false); + + // shadow volume front faces + gc->SetZWrite(false); + gc->SetColorWrite(false, false, false, false); + gc->SetLighting(false); + + gc->SetStencilBuffering(true); + gc->SetStencilFunc(CMP_ALWAYS); + gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_INC); + + iter = objects.begin(); + while(iter != objects.end()) { + Object *obj = *iter++; + TriMesh *mesh = obj->GetShadowVolume(slight); + if(mesh) { + gc->SetWorldMatrix(obj->GetWorldTransform()); + gc->Draw(const_cast(mesh->GetVertexArray()), mesh->GetVertexCount()); + + // back faces pass + //gc->SetFrontFace(CounterClockwise); + //gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_DEC); + + //gc->Draw(const_cast(mesh->GetVertexArray()), mesh->GetVertexCount()); + } + } + + // static shadow volumes + gc->SetWorldMatrix(Matrix4x4()); + std::list::const_iterator shadow_iter = StaticShadowVolumes.begin(); + while(shadow_iter != StaticShadowVolumes.end()) { + if(shadow_iter->light == lights[i]) { + gc->Draw(const_cast(shadow_iter->shadow_mesh->GetVertexArray()), shadow_iter->shadow_mesh->GetVertexCount()); + } + shadow_iter++; + } + + // back faces pass + gc->SetFrontFace(CounterClockwise); + gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_DEC); + + iter = objects.begin(); + while(iter != objects.end()) { + Object *obj = *iter++; + TriMesh *mesh = obj->GetShadowVolume(slight); + if(mesh) { + gc->SetWorldMatrix(obj->GetWorldTransform()); + gc->Draw(const_cast(mesh->GetVertexArray()), mesh->GetVertexCount()); + } + } + + // static shadow volumes + gc->SetWorldMatrix(Matrix4x4()); + shadow_iter = StaticShadowVolumes.begin(); + while(shadow_iter != StaticShadowVolumes.end()) { + if(shadow_iter->light == lights[i]) { + gc->Draw(const_cast(shadow_iter->shadow_mesh->GetVertexArray()), shadow_iter->shadow_mesh->GetVertexCount()); + } + shadow_iter++; + } + + gc->SetFrontFace(Clockwise); + + gc->SetLighting(true); + gc->SetZWrite(true); + gc->SetColorWrite(true, true, true, true); + + gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_KEEP); + gc->SetStencilFunc(CMP_EQUAL); + gc->SetStencilReference(0); + + gc->SetLighting(true); + //SetupLights(); + + slight++; + } +} + +void Scene::Render() const { + gc->SetAmbientLight(AmbientLight); + + // set camera + if(!ActiveCamera) return; + ActiveCamera->CreateCameraMatrix(); + gc->SetViewMatrix(ActiveCamera->GetCameraMatrix()); + + // set projection matrix + float NearClip, FarClip; + Matrix4x4 ProjMat; + ActiveCamera->GetClippingPlanes(&NearClip, &FarClip); + CreateProjectionMatrix(&ProjMat, ActiveCamera->GetFOV(), 1.3333333f, NearClip, FarClip); + gc->SetProjectionMatrix(ProjMat); + + SetupLights(); + + // render shadows + if(Shadows) { + + // make array of shadow-casting lights + Light *ShadowCasters[8]; + Light **lptr = ShadowCasters; + for(int i=0; i<8; i++) { + if(lights[i] && lights[i]->GetShadowCasting()) { + *lptr++ = lights[i]; + } + } + int ShadowCasterCount = (int)(lptr - ShadowCasters); + + std::list::const_iterator iter = objects.begin(); + while(iter != objects.end()) { + Object *obj = *iter++; + + if(obj->GetShadowCasting()) { + obj->CalculateShadows((const Light**)ShadowCasters, ShadowCasterCount); + } + } + + RenderShadows(); + } + + // render objects + std::list::const_iterator iter = objects.begin(); + while(iter != objects.end()) { + Object *obj = *iter++; + + obj->Render(); + } + + if(Shadows) { + gc->SetStencilBuffering(false); + gc->SetStencilFunc(CMP_ALWAYS); + } + + if(LightHalos) { + for(int i=0; i<8; i++) { + if(lights[i]) lights[i]->Draw(gc, HaloSize); + } + } +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/3dscene.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/3dscene.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,81 @@ +#ifndef _3DSCENE_H_ +#define _3DSCENE_H_ + +#include +#include "3dengine.h" +#include "camera.h" +#include "lights.h" +#include "objects.h" +#include "curves.h" + +struct ShadowVolume { + TriMesh *shadow_mesh; + const Light *light; +}; + +class Scene { +private: + GraphicsContext *gc; + + Light *lights[8]; + std::list cameras; + std::list objects; + std::list StaticShadowVolumes; + std::list curves; + bool ManageData; + + Camera *ActiveCamera; + + bool Shadows; + bool LightHalos; + float HaloSize; + + Color AmbientLight; + + bool UseFog; + Color FogColor; + float NearFogRange, FarFogRange; + +public: + + Scene(GraphicsContext *gc = 0); + ~Scene(); + + void SetGraphicsContext(GraphicsContext *gc); + + void AddCamera(Camera *cam); + void AddLight(Light *light); + void AddObject(Object *obj); + void AddStaticShadowVolume(TriMesh *mesh, const Light *light); + void AddCurve(Curve *curve); + + void RemoveObject(const Object *obj); + void RemoveLight(const Light *light); + + Camera *GetCamera(const char *name); + Light *GetLight(const char *name); + Object *GetObject(const char *name); + Curve *GetCurve(const char *name); + + std::list *GetObjectsList(); + + void SetActiveCamera(Camera *cam); + Camera *GetActiveCamera() const; + + void SetShadows(bool enable); + void SetHaloDrawing(bool enable); + void SetHaloSize(float size); + void SetAmbientLight(Color ambient); + Color GetAmbientLight() const; + void SetFog(bool enable, Color FogColor = Color(0l), float Near = 0.0f, float Far = 1000.0f); + + // render states + void SetupLights() const; + + void RenderShadows() const; + void Render() const; +}; + + + +#endif // _3DSCENE_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/3dschunks.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/3dschunks.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,160 @@ +#ifndef _3DSCHUNKS_H_ +#define _3DSCHUNKS_H_ + +enum ChunkID { + Chunk_Color_Float3 = 0x0010, // o Floating point color + Chunk_Color_Byte3 = 0x0011, // o 24bit color + Chunk_Color_GammaByte3 = 0x0012, // o 24bit gamma corrected + Chunk_Color_GammaFloat3 = 0x0013, // o Floating point gamma corrected + Chunk_PercentInt = 0x0030, // o Percent Chunk int 0 - 100 + Chunk_PercentFloat = 0x0031, // o Percent Chunk float 0 - 1 + + Chunk_3DSMain = 0x4D4D, // + Root Chunk + Chunk_Main_3DSVersion = 0x0002, // - 3DS Version + Chunk_Main_3DEditor = 0x3D3D, // + 3D Editor Chunk + Chunk_Edit_Unit = 0x0100, // - Unit + Chunk_Edit_BGBitmap = 0x1100, // - Background Bitmap + Chunk_Edit_UseBGBitmap = 0x1101, // - Use Background Bitmap + Chunk_Edit_BGColor = 0x1200, // - Background Color + Chunk_Edit_UseBGColor = 0x1201, // - Use Background Color + Chunk_Edit_GradColor = 0x1300, // - Background Gradient + Chunk_Edit_UseGradColor = 0x1301, // - Use Gradient Color + Chunk_Edit_ShadowMapBias = 0x1400, // - Shadow map bias + Chunk_Edit_ShadowMapSize = 0x1420, // - Shadow map size + Chunk_Edit_ShadowMapSampleRange = 0x1450, // - Shadow map sample range + Chunk_Edit_RaytraceBias = 0x1460, // - Raytrace bias + Chunk_Edit_UseRaytrace = 0x1470, // - Use Raytrace + Chunk_Edit_AmbientColor = 0x2100, // - Ambient Color + Chunk_Edit_Fog = 0x2200, // + Fog + Chunk_Fog_FogColor = 0x2210, // - Fog Color + Chunk_Edit_UseFog = 0x2201, // - Use Fog + Chunk_Edit_DistanceQue = 0x2300, // + Distance que + Chunk_Dist_DimBackground = 0x2310, // - Dim Background + Chunk_Edit_UseDistanceQue = 0x2301, // - Use distance que + Chunk_Edit_LayeredFogOptions = 0x2302, // - Layered fog options + Chunk_Edit_UseLayeredFog = 0x2303, // - Use Layered Fog + Chunk_Edit_MeshVersion = 0x3D3E, // - Mesh Version + + Chunk_Edit_Object = 0x4000, // + Object + Chunk_Obj_Hidden = 0x4010, // - Hidden + Chunk_Obj_DontCastShadows = 0x4012, // - Object doesn't cast shadows + Chunk_Obj_MatteObject = 0x4013, // - Matte + Chunk_Obj_ExternalProcessOn = 0x4015, // - External Process on (?) + Chunk_Obj_DontReceiveShadows = 0x4017, // - doesn't reseive shadows + Chunk_Obj_TriMesh = 0x4100, // + TriMesh + Chunk_TriMesh_VertexList = 0x4110, // - Vertex List + Chunk_TriMesh_FaceDesc = 0x4120, // + Faces description + Chunk_Face_Material = 0x4130, // - Face Materials* + Chunk_TriMesh_TexCoords = 0x4140, // - Texture Coordinates + Chunk_TriMesh_SmoothingGroup = 0x4150, // - Smoothing group + Chunk_TriMesh_WorldTransform = 0x4160, // - Position and Orientation + Chunk_TriMesh_Color = 0x4165, // - Object color + Chunk_TriMesh_ExternalProcessName = 0x4181, // - External Process name (?) + Chunk_TriMesh_ExternalProcessParams = 0x4182, // - External Process parameters (?) + + Chunk_Obj_Light = 0x4600, // + Light + Chunk_Light_SpotLight = 0x4610, // + SpotLight + Chunk_Spot_Raytrace = 0x4627, // - Raytrace + Chunk_Spot_CastShadows = 0x4630, // - Light casts shadows + Chunk_Spot_ShadowMap = 0x4641, // - Shadow Map + Chunk_Spot_ShowCone = 0x4650, // - Show Cone + Chunk_Spot_Rectangular = 0x4651, // - Rectangular shaped spotlight + Chunk_Spot_OverShoot = 0x4652, // - Overshoot + Chunk_Spot_ProjMap = 0x4653, // - Projector Map + Chunk_Spot_Roll = 0x4656, // - Roll around dir + Chunk_Spot_RaytraceBias = 0x4658, // - Raytrace Bias + Chunk_Light_Off = 0x4620, // - Light is disabled + Chunk_Light_Attenuation = 0x4625, // - Attenuation enabled + Chunk_Light_AttenuationStart = 0x4659, // - Attenuation Start Range + Chunk_Light_AttenuationEnd = 0x465A, // - Attenuation End Range + Chunk_Light_Intensity = 0x465B, // - Light Intensity + + Chunk_Obj_Camera = 0x4700, // - Camera + Chunk_Edit_ViewSettings = 0x7001, // - View Settings + Chunk_Edit_ViewDesc2 = 0x7011, // - View Description 2 + Chunk_Edit_ViewDesc1 = 0x7012, // - View Description 1 + Chunk_Edit_MeshWindows = 0x7020, // - Mesh Windows (?) + + Chunk_Edit_Material = 0xAFFF, // + Material Block + Chunk_Mat_Name = 0xA000, // - Material Name + Chunk_Mat_AmbientColor = 0xA010, // - Ambient Color + Chunk_Mat_DiffuseColor = 0xA020, // - Diffuse Color + Chunk_Mat_SpecularColor = 0xA030, // - Specular Color + Chunk_Mat_Specular = 0xA040, // - Shininness (Specular Power) + Chunk_Mat_SpecularIntensity = 0xA041, // - Shininness Strength (specular intensity) + Chunk_Mat_Transparency = 0xA050, // - Transparency (alpha) + Chunk_Mat_TransparencyFalloff = 0xA052, // - Transparency Falloff + Chunk_Mat_ReflectionBlur = 0xA053, // - Reflection Blur + Chunk_Mat_TwoSided = 0xA081, // - Two Sided + Chunk_Mat_AddTransparency = 0xA083, // - ? + Chunk_Mat_SelfIllumination = 0xA084, // - Self Illumination (emissive) + Chunk_Mat_Wireframe = 0xA085, // - Render in wireframe + Chunk_Mat_WireframeThickness = 0xA087, // - Wire thickness + Chunk_Mat_FaceMapping = 0xA088, // - Apply maps to faces seperatly (ignore uv) + Chunk_Mat_InTranc = 0xA08A, // ? + Chunk_Mat_Soften = 0xA08C, // - Soft Shading + Chunk_Mat_WireUnits = 0xA08E, // - Wire units (?) + Chunk_Mat_RenderType = 0xA100, // - Render Type + Chunk_Mat_BumpMapPercent = 0xA252, // - Bump map intensity + Chunk_Mat_TextureMap = 0xA200, // + Texture Map + Chunk_Mat_TextureMap2 = 0xA33A, // + Texture Map 2 + Chunk_Mat_OpacityMap = 0xA210, // + Opacity Map + Chunk_Mat_BumpMap = 0xA230, // + Bump Map + Chunk_Mat_SpecularMap = 0xA33C, // + Specular Intensity map + Chunk_Mat_SpecularColorMap = 0xA204, // + Specular color (texture) map + Chunk_Mat_SelfIlluminationMap = 0xA33D, // + Self Illumination Map + Chunk_Mat_ReflectionMap = 0xA220, // + Reflection Map + Chunk_Mat_TextureMask = 0xA33E, // - Texture Mask + Chunk_Mat_Texture2Mask = 0xA340, // - Texture 2 Mask + Chunk_Mat_OpacityMask = 0xA342, // - Opacity Mask + Chunk_Mat_BumpMask = 0xA344, // - Bump Mask + Chunk_Mat_SpecularMask = 0xA346, // - Specular Mask + Chunk_Mat_SpecularColorMask = 0xA348, // - Specular color mask + Chunk_Mat_SelfIlluminationMask = 0xA34A, // - Self Illumination mask + Chunk_Mat_ReflectionMask = 0xA34C, // - Reflection mask + + // map subchunks // ----------------------- + Chunk_Map_FileName = 0xA300, // - Filename + Chunk_Map_Params = 0xA351, // - Parameters + Chunk_Map_BlurPercent = 0xA353, // - Blur ammount + Chunk_Map_VScale = 0xA354, // - Texture V Scale + Chunk_Map_UScale = 0xA356, // - Texture U Scale + Chunk_Map_UOffset = 0xA358, // - Texture U Offset + Chunk_MAP_VOffset = 0xA35A, // - Texture V Offset + Chunk_Map_RotationAngle = 0xA35C, // - Texture Rotation Angle + Chunk_Map_RGBLumAlphaTint1 = 0xA360, // - RGB Luminance Alpha Tint 1 + Chunk_Map_RGBLumAlphaTint2 = 0xA362, // - RGB Luminance Alpha Tint 2 + Chunk_Map_RGBTintR = 0xA364, // - RGB Tint R + Chunk_Map_RGBTintG = 0xA366, // - RGB Tint G + Chunk_Map_RGBTintB = 0xA368, // - RGB Tint B + // map subchunks end // ----------------------- + + Chunk_Main_Keyframer = 0xB000, // + Keyframer Chunk + Chunk_Key_AmbientInfo = 0xB001, // - Ambient animation info + Chunk_Key_MeshInfo = 0xB002, // - Mesh animation info + Chunk_Key_CameraInfo = 0xB003, // - Camera animation info + Chunk_Key_CameraTargetInfo = 0xB004, // - Camera Target animation info + Chunk_Key_OmniLightInfo = 0xB005, // - Omni Light animation info + Chunk_Key_SpotLightTargetInfo = 0xB006, // - Spotlight target animation info + Chunk_Key_SpotLightInfo = 0xB007, // - Spotlight animation info + Chunk_Key_Frames = 0xB008, // - Animation Frames + + // animation information subchunks // ----------------------- + Chunk_Info_Object = 0xB010, // - Object information + Chunk_Info_ObjectPivot = 0xB013, // - Object Pivot + Chunk_Info_ObjectMorphAngle = 0xB015, // - Object Morph Angle + Chunk_Info_PositionTrack = 0xB020, // - Position Track + Chunk_Info_RotationTrack = 0xB021, // - Rotation Track + Chunk_Info_ScaleTrack = 0xB022, // - Scaling Track + Chunk_Info_FOVTrack = 0xB023, // - FOV Track + Chunk_Info_RollTrack = 0xB024, // - Roll Track + Chunk_Info_ColorTrack = 0xB025, // - Color Track + Chunk_Info_MorphTrack = 0xB026, // - Morph Track + Chunk_Info_HotSpotTrack = 0xB027, // - HotSpot Track + Chunk_Info_FalloffTrack = 0xB028, // - Falloff Track + Chunk_Info_HideTrack = 0xB029, // - Hide Track + Chunk_Info_HierarchyPosition = 0xB030 // - Hierarchy Position +}; + +#endif // _3DSCHUNKS_H_ + diff -r 000000000000 -r 1cffe3409164 src/3deng/SceneLoader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/SceneLoader.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,18 @@ +#ifndef _SCENELOADER_H_ +#define _SCENELOADER_H_ + +#include "3deng/objects.h" +#include "3deng/3dscene.h" +#include "3deng/material.h" + +namespace SceneLoader { + void SetGraphicsContext(GraphicsContext *gfx); + void SetDataPath(const char *path); + void SetNormalFileSaving(bool enable); + + bool LoadObject(const char *fname, const char *ObjectName, Object **obj); + bool LoadScene(const char *fname, Scene **scene); + bool LoadMaterials(const char *fname, Material **materials); +} + +#endif // _SCENELOADER_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/camera.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/camera.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,228 @@ +#include "camera.h" + +// camera constructor +Camera::Camera() { + Pos = Vector3(0.0f, 0.0f, 0.0f); + LookAt = Vector3(0.0f, 0.0f, 5.0f); + Up = Vector3(0.0f, 1.0f, 0.0f); + FOV = QuarterPi; // 45 deg + CreateCameraMatrix(); + + FlipRight = false; + + path = 0; + targpath = 0; + + NearClip = 1.0f; + FarClip = 10000.0f; +} + +void Camera::SetCamera(const Vector3 &pos, const Vector3 &lookat, const Vector3 &up) { + Pos = pos; + LookAt = lookat; + Up = up; +} + +void Camera::SetClippingPlanes(float NearClip, float FarClip) { + this->NearClip = NearClip; + this->FarClip = FarClip; +} + +void Camera::GetClippingPlanes(float *NearClip, float *FarClip) const { + *NearClip = this->NearClip; + *FarClip = this->FarClip; +} + +Matrix4x4 &Camera::GetCameraMatrix() { + return CCSmat; +} + +Vector3 Camera::GetViewVector() const { + return LookAt - Pos; +} + +Vector3 Camera::GetPosition() const { + return Pos; +} + +Vector3 Camera::GetUpVector() const { + return Up; +} + +Vector3 Camera::GetTargetPosition() const { + return LookAt; +} + +Base Camera::GetCameraBase() const { + Base base; + base.k = (LookAt - Pos).Normalized(); + base.j = Up.Normalized(); + base.i = CrossProduct(base.j, base.k); + base.j = CrossProduct(base.i, base.k); + + return base; +} + +////////////////////////////////////////////////////////////// +// Create a camera matrix from 3 vectors position/lookat/up // +////////////////////////////////////////////////////////////// +void Camera::CreateCameraMatrix(Matrix4x4 *matrix, const Vector3 &Pos, const Vector3 &LookAt, const Vector3 &Up) const { + + Vector3 n = LookAt - Pos; + n.Normalize(); + Vector3 u = Up.CrossProduct(n); + u.Normalize(); + Vector3 v = n.CrossProduct(u); + float Tx = -(u.DotProduct(Pos)); + float Ty = -(v.DotProduct(Pos)); + float Tz = -(n.DotProduct(Pos)); + + matrix->ResetIdentity(); + matrix->m[0][0] = u.x; matrix->m[0][1] = v.x; matrix->m[0][2] = n.x; + matrix->m[1][0] = u.y; matrix->m[1][1] = v.y; matrix->m[1][2] = n.y; + matrix->m[2][0] = u.z; matrix->m[2][1] = v.z; matrix->m[2][2] = n.z; + matrix->m[3][0] = Tx; matrix->m[3][1] = Ty; matrix->m[3][2] = Tz; +} + +void Camera::CreateCameraMatrix() { + CreateCameraMatrix(&CCSmat, Pos, LookAt, Up); +} + +/////////////////////////////////////////////////////// +// controling the camera + +// moves the camera x/y/z units +void Camera::Move(float x, float y, float z) { + PosTranslate.Translate(x,y,z); + LookTranslate.Translate(x,y,z); + UpTranslate.Translate(x,y,z); +} + +// moves the camera TO the new coords +void Camera::MoveTo(float x, float y, float z) { + Vector3 newpos = Vector3(x,y,z); + // find the difference between the old and new position + Vector3 translation = newpos - Pos; + PosTranslate.Translate(translation.x, translation.y, translation.z); + LookTranslate.Translate(translation.x, translation.y, translation.z); + UpTranslate.Translate(translation.x, translation.y, translation.z); +} + +void Camera::Rotate(float x, float y, float z) { + // find the inverted lookat vector + Vector3 ilook = Pos - LookAt; + Vector3 newilook = ilook; + // rotate it + Matrix4x4 rot; + rot.ResetIdentity(); + rot.Rotate(x,y,z); + newilook.Transform(rot); + // find the translation difference between the two vectors + Vector3 transl = newilook - ilook; + //do it + PosTranslate.ResetIdentity(); + PosTranslate.Translate(transl.x, transl.y, transl.z); + UpRotate.ResetIdentity(); + UpRotate.Rotate(x, y, z); + + // apply the transformation + Pos.Transform(PosTranslate); + Up.Transform(UpRotate); +} + + +////////////////// rotates the camera around the target /////////////// + +inline void Camera::RotateTarget(float x, float y, float z) { + LookRotate.Rotate(x, y, z); +} + +inline void Camera::MoveTarget(float x, float y, float z) { + LookTranslate.Translate(x,y,z); +} + +// moves the look at point at the point specified +inline void Camera::MoveTargetTo(float x, float y, float z) { + Vector3 translation = Vector3(x,y,z) - LookAt; + LookTranslate.Translate(translation.x, translation.y, translation.z); +} + +void Camera::Zoom(float factor) { + // find the new vector between the camera and the target + Vector3 offset = (LookAt - Pos) * factor; + Vector3 diff = offset - LookAt; + Pos += offset; + + //PosTranslate.ResetIdentity(); + //PosTranslate.Translate(diff.x, diff.y, diff.z); + //Pos.Transform(PosTranslate); +} + +void Camera::Spin(float rads) { + Up.Rotate((LookAt - Pos).Normalized(), rads); +} + +void Camera::SetRightFlipping(bool enable) { + FlipRight = enable; +} +void Camera::SetPosition(const Vector3 &pos) { + this->Pos = pos; +} + +void Camera::SetUpVector(const Vector3 &up) { + Up = up; +} + +void Camera::SetTarget(const Vector3 &targ) { + this->LookAt = targ; +} + + +void Camera::ResetRotation() { + PosRotate.ResetIdentity(); +} + + +void Camera::SetCameraPath(const Curve *path, const Curve *tpath, dword StartTime, dword EndTime) { + this->path = path; + this->targpath = tpath; + this->StartTime = StartTime; + this->EndTime = EndTime; +} + +void Camera::FollowPath(dword time, bool Cycle) { + if(Cycle || (!Cycle && time >= StartTime && time < EndTime)) { + float t = (float)(time - StartTime) / (float)(EndTime - StartTime); + if(Cycle) { + t = (float)fmod(t, 1.0f); + } else { + if(t < 0.0f) t = 0.0f; + if(t > 1.0f) t = 1.0f; + } + if(path) { + SetPosition(const_cast(path)->Interpolate(t)); + } + if(targpath) { + SetTarget(const_cast(targpath)->Interpolate(t)); + } + } +} + +void Camera::FollowPath(float t) { + if(t < 0.0f) t = 0.0f; + if(t > 1.0f) t = 1.0f; + if(path) { + SetPosition(const_cast(path)->Interpolate(t)); + } + if(targpath) { + SetTarget(const_cast(targpath)->Interpolate(t)); + } +} + +dword Camera::GetStartTime() const { + return StartTime; +} + +dword Camera::GetEndTime() const { + return EndTime; +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/camera.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/camera.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,77 @@ +#ifndef _CAMERA_H_ +#define _CAMERA_H_ + +#include +#include "switches.h" +#include "n3dmath.h" +#include "curves.h" +#include "typedefs.h" + +class Camera { +private: + Vector3 Pos, LookAt, Up; + float FOV; + float NearClip, FarClip; + // transformation matrices for each vector + Matrix4x4 PosTranslate, LookTranslate, UpTranslate; + Matrix4x4 PosRotate, LookRotate, UpRotate; + Matrix4x4 PosScale, LookScale, UpScale; + + bool FlipRight; + + const Curve *path, *targpath; + dword StartTime, EndTime; + +public: + std::string name; + Matrix4x4 CCSmat; + + Camera(); + float GetFOV() const {return FOV;} + void SetFOV(float FOV) {this->FOV = FOV;} + + void SetClippingPlanes(float NearClip, float FarClip); + void GetClippingPlanes(float *NearClip, float *FarClip) const; + + void SetCamera(const Vector3 &pos, const Vector3 &lookat, const Vector3 &up); + Matrix4x4 &GetCameraMatrix(); + + // camera controls + void Move(float x, float y, float z); + void MoveTo(float x, float y, float z); + void Rotate(float x, float y, float z); + void Zoom(float factor); + + // haphazard additions + void SetRightFlipping(bool enable); + void SetPosition(const Vector3 &pos); + void SetUpVector(const Vector3 &up); + void SetTarget(const Vector3 &targ); + + Vector3 GetViewVector() const; + Vector3 GetPosition() const; + Vector3 GetUpVector() const; + Vector3 GetTargetPosition() const; + + Base GetCameraBase() const; + + inline void MoveTarget(float x, float y, float z); + inline void MoveTargetTo(float x, float y, float z); + inline void RotateTarget(float x, float y, float z); + + void ResetRotation(); + + void CreateCameraMatrix(); + void CreateCameraMatrix(Matrix4x4 *matrix, const Vector3 &Pos, const Vector3 &LookAt, const Vector3 &Up) const; + + void Spin(float rads); + + void SetCameraPath(const Curve *path, const Curve *tpath, dword StartTime, dword EndTime); + void FollowPath(dword time, bool Cycle = false); + void FollowPath(float t); + + dword GetStartTime() const; + dword GetEndTime() const; +}; + +#endif // _CAMERA_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/exceptions.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/exceptions.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,44 @@ +#include "exceptions.h" + +EngineInitException::EngineInitException() { + str = "Unknown"; +} + +EngineInitException::EngineInitException(string reason) { + str = reason; +} + +string EngineInitException::GetReason() const { + string tmp = "An error occured while initializing the 3D Engine\nReason: "; + tmp += str; + return tmp; +} + +EngineModuleNotFoundException::EngineModuleNotFoundException() { + str = "Unknown Module"; +} + +EngineModuleNotFoundException::EngineModuleNotFoundException(string modulename) { + str = modulename; +} + +string EngineModuleNotFoundException::GetReason() const { + string tmp = "The 3D Engine could not link a required module.\n"; + tmp += "Please contact the program ventor to obtain the missing file.\nMissing File: "; + tmp += str; + return tmp; +} + +EngineGeneralException::EngineGeneralException() { + str = "Unknown"; +} + +EngineGeneralException::EngineGeneralException(string reason) { + str = reason; +} + +string EngineGeneralException::GetReason() const { + string tmp = "An error occured in the 3D Engine\nReason: "; + tmp += str; + return tmp; +} diff -r 000000000000 -r 1cffe3409164 src/3deng/exceptions.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/exceptions.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,41 @@ +#ifndef _EXCEPTIONS_H_ +#define _EXCEPTIONS_H_ + +#include + +using std::string; + +class EngineBaseException { +protected: + string str; + +public: + + virtual string GetReason() const = 0; +}; + +class EngineInitException : protected EngineBaseException { +public: + EngineInitException(); + EngineInitException(string reason); + + virtual string GetReason() const; +}; + +class EngineModuleNotFoundException : protected EngineBaseException { +public: + EngineModuleNotFoundException(); + EngineModuleNotFoundException(string modulename); + + virtual string GetReason() const; +}; + +class EngineGeneralException : protected EngineBaseException { +public: + EngineGeneralException(); + EngineGeneralException(string reason); + + virtual string GetReason() const; +}; + +#endif // _EXCEPTIONS_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/lights.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/lights.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,586 @@ +#include "lights.h" +#include + +Light::Light() { + intensity = 1.0f; + ambient_color = 0.0f; + diffuse_color = specular_color = 1.0f; + CastShadows = false; +} + +void Light::SetIntensity(float intensity) { + this->intensity = intensity; +} + +float Light::GetIntensity() const { + return intensity; +} + +void Light::SetColor(const Color &color, PhongComponent comp) { + if(comp == (PhongComponent)-1) { + diffuse_color = specular_color = color; + } else { + switch(comp) { + case Ambient: + ambient_color = color; + break; + case Diffuse: + diffuse_color = color; + break; + case Specular: + specular_color = color; + break; + } + } +} + +const Color &Light::GetColor(PhongComponent comp) const { + switch(comp) { + case Ambient: + return ambient_color; + case Diffuse: + return diffuse_color; + case Specular: + return specular_color; + } +} + +void Light::SetShadowCasting(bool enable) { + CastShadows = enable; +} + +bool Light::GetShadowCasting() const { + return CastShadows; +} + +////////// Directional Light /////////// + +// Non-Applicable functions for this type of light +void DirLight::SetPosition(const Vector3 &pos) {} +void DirLight::SetRange(float range) {} +void DirLight::SetAttenuation(float att0, float att1, float att2) {} +Vector3 DirLight::GetPosition() const {return Direction;} +float DirLight::GetRange() const {return 0.0f;} +float DirLight::GetAttenuation(int degree) const {return 0.0f;} +void DirLight::ResetTransform() {} +void DirLight::ResetTranslation() {} +void DirLight::ResetRotation() {} +void DirLight::Transform(const Matrix4x4 &matrix) {} +void DirLight::Translate(float x, float y, float z) {} +void DirLight::Rotate(float x, float y, float z) {} +void DirLight::Rotate(const Vector3 &axis, float angle) {} +void DirLight::SetCone(float InnerCone, float OuterCone) {} +float DirLight::GetInnerCone() const {return 0.0f;} +float DirLight::GetOuterCone() const {return 0.0f;} +void DirLight::SetFalloff(float falloff) {} +float DirLight::GetFalloff() const {return 0.0f;} +void DirLight::ResetTargetTransform() {} +void DirLight::ResetTargetTranslation() {} +void DirLight::ResetTargetRotation() {} +void DirLight::TargetTransform(const Matrix4x4 &matrix) {} +void DirLight::TargetTranslate(float x, float y, float z) {} +void DirLight::TargetRotate(float x, float y, float z) {} +void DirLight::TargetRotate(const Vector3 &axis, float angle) {} + + + +DirLight::DirLight() { + Direction = Vector3(0, -1, 0); +} + +DirLight::DirLight(const Vector3 &dir) { + Direction = dir; +} + + +void DirLight::SetDirection(const Vector3 &dir) { + Direction = dir; +} + +Vector3 DirLight::GetDirection() const { + Vector3 dir = Direction; + dir.Transform(DirRot); + return dir; +} + +LightType DirLight::GetType() const { + return LTDir; +} + +// direction transformations +void DirLight::ResetDirTransform() { + DirRot.ResetIdentity(); +} + +void DirLight::ResetDirRotation() { + DirRot.ResetIdentity(); +} + +void DirLight::TransformDir(const Matrix4x4 &matrix) { + DirRot *= matrix; +} + +void DirLight::RotateDir(float x, float y, float z) { + DirRot.Rotate(x, y, z); +} + +void DirLight::RotateDir(const Vector3 &axis, float angle) { + DirRot.Rotate(axis, angle); +} + + +void DirLight::SetLight(dword index, GraphicsContext *gc) const { + + Vector3 dir = Direction; + dir.Transform(DirRot); + + D3DLIGHT8 light; + memset(&light, 0, sizeof(D3DLIGHT8)); + light.Ambient.r = ambient_color.r * intensity; + light.Diffuse.r = diffuse_color.r * intensity; + light.Specular.r = specular_color.r * intensity; + light.Ambient.g = ambient_color.g * intensity; + light.Diffuse.g = diffuse_color.g * intensity; + light.Specular.g = specular_color.g * intensity; + light.Ambient.b = ambient_color.b * intensity; + light.Diffuse.b = diffuse_color.b * intensity; + light.Specular.b = specular_color.b * intensity; + light.Direction = dir; + light.Type = (D3DLIGHTTYPE)LTDir; + + gc->D3DDevice->SetLight(index, &light); + gc->D3DDevice->LightEnable(index, true); +} + +Vertex DirLightVisVertices[] = { + Vertex(Vector3(0.0f, 0.0f, 0.1f), 0.0f, 0.0f, 0x00ff0000), + Vertex(Vector3(0.03f, 0.03f, 0.0f), 0.0f, 0.0f, 0x000000ff), + Vertex(Vector3(-0.03f, 0.03f, 0.0f), 0.0f, 0.0f, 0x000000ff), + Vertex(Vector3(0.0f, -0.03f, 0.0f), 0.0f, 0.0f, 0x000000ff) +}; + +Index DirLightVisIndices[] = { + 0, 1, 2, + 0, 2, 3, + 0, 3, 1, + 1, 3, 2 +}; + + +void DirLight::Draw(GraphicsContext *gc, float size) { + + Material mat(0.9f, 0.8f, 0.3f); + gc->SetMaterial(mat); + gc->SetTexture(0, 0); + gc->SetColorVertex(true); + gc->SetLighting(false); + gc->SetZBuffering(false); + + Matrix4x4 WorldMat = (Matrix4x4)Base(Direction).CreateRotationMatrix() * DirRot; + gc->SetWorldMatrix(WorldMat); + + Matrix4x4 ViewMat = gc->GetViewMatrix(); + Matrix4x4 AugViewMat; + + for(int i=0; i<4; i++) { + AugViewMat.SetRowVector(ViewMat.GetRowVector(i).Normalized(), i); + } + + gc->SetViewMatrix(AugViewMat); + + gc->Draw(DirLightVisVertices, DirLightVisIndices, 4, 12); + + gc->SetViewMatrix(ViewMat); + + gc->SetZBuffering(true); + gc->SetLighting(true); + gc->SetColorVertex(false); + +} + +/////////// Point Light ////////////// + +// Non-Applicable member functions +void PointLight::SetDirection(const Vector3 &dir) {} +Vector3 PointLight::GetDirection() const {return Position;} +void PointLight::ResetDirTransform() {} +void PointLight::ResetDirRotation() {} +void PointLight::TransformDir(const Matrix4x4 &matrix) {} +void PointLight::RotateDir(float x, float y, float z) {} +void PointLight::RotateDir(const Vector3 &axis, float angle) {} +void PointLight::SetCone(float InnerCone, float OuterCone) {} +float PointLight::GetInnerCone() const {return 0.0f;} +float PointLight::GetOuterCone() const {return 0.0f;} +void PointLight::SetFalloff(float falloff) {} +float PointLight::GetFalloff() const {return 0.0f;} +void PointLight::ResetTargetTransform() {} +void PointLight::ResetTargetTranslation() {} +void PointLight::ResetTargetRotation() {} +void PointLight::TargetTransform(const Matrix4x4 &matrix) {} +void PointLight::TargetTranslate(float x, float y, float z) {} +void PointLight::TargetRotate(float x, float y, float z) {} +void PointLight::TargetRotate(const Vector3 &axis, float angle) {} + + + +PointLight::PointLight() { + Position = Vector3(0, 100, 0); + Range = 300.0f; + Attenuation[0] = 1.0f; + Attenuation[1] = 0.0f; + Attenuation[2] = 0.0f; +} + +PointLight::PointLight(const Vector3 &pos, float range, float att0, float att1, float att2) { + Position = pos; + Range = range; + Attenuation[0] = att0; + Attenuation[1] = att1; + Attenuation[2] = att2; +} + +Matrix4x4 PointLight::GetTransform() const { + return PosXForm * PosRot * PosTrans; +} + +void PointLight::SetPosition(const Vector3 &pos) { + Position = pos; +} + +void PointLight::SetRange(float range) { + Range = range; +} + +void PointLight::SetAttenuation(float att0, float att1, float att2) { + Attenuation[0] = att0; + Attenuation[1] = att1; + Attenuation[2] = att2; +} + +Vector3 PointLight::GetPosition() const { + Vector3 pos = Position; + pos.Transform(GetTransform()); + return pos; +} + +float PointLight::GetRange() const { + return Range; +} + +float PointLight::GetAttenuation(int degree) const { + return Attenuation[degree]; +} + +LightType PointLight::GetType() const { + return LTPoint; +} + +// position transformations +void PointLight::ResetTransform() { + PosRot.ResetIdentity(); + PosTrans.ResetIdentity(); + PosXForm.ResetIdentity(); +} + +void PointLight::ResetTranslation() { + PosTrans.ResetIdentity(); +} + +void PointLight::ResetRotation() { + PosRot.ResetIdentity(); +} + +void PointLight::Transform(const Matrix4x4 &matrix) { + PosXForm *= matrix; +} + +void PointLight::Translate(float x, float y, float z) { + PosTrans.Translate(x, y, z); +} + +void PointLight::Rotate(float x, float y, float z) { + PosRot.Rotate(x, y, z); +} + +void PointLight::Rotate(const Vector3 &axis, float angle) { + PosRot.Rotate(axis, angle); +} + + +void PointLight::SetLight(dword index, GraphicsContext *gc) const { + + Vector3 pos = Position; + pos.Transform(GetTransform()); + + D3DLIGHT8 light; + memset(&light, 0, sizeof(D3DLIGHT8)); + light.Ambient.r = ambient_color.r * intensity; + light.Diffuse.r = diffuse_color.r * intensity; + light.Specular.r = specular_color.r * intensity; + light.Ambient.g = ambient_color.g * intensity; + light.Diffuse.g = diffuse_color.g * intensity; + light.Specular.g = specular_color.g * intensity; + light.Ambient.b = ambient_color.b * intensity; + light.Diffuse.b = diffuse_color.b * intensity; + light.Specular.b = specular_color.b * intensity; + light.Position = pos; + light.Range = Range; + light.Attenuation0 = Attenuation[0]; + light.Attenuation1 = Attenuation[1]; + light.Attenuation2 = Attenuation[2]; + light.Type = (D3DLIGHTTYPE)LTPoint; + + gc->D3DDevice->SetLight(index, &light); + gc->D3DDevice->LightEnable(index, true); +} + + + +Index PointLightVisIndices[] = {0, 2, 1, 0, 3, 2}; + +void PointLight::Draw(GraphicsContext *gc, float size) { + + dword color = (diffuse_color * intensity).GetPacked32(); + + float PtHalfSz = size / 2.0f; + Vertex PointLightVisVertices[] = { + Vertex(Vector3(-PtHalfSz, PtHalfSz, 0.0f), 0.0f, 0.0f, color), + Vertex(Vector3(PtHalfSz, PtHalfSz, 0.0f), 1.0f, 0.0f, color), + Vertex(Vector3(PtHalfSz, -PtHalfSz, 0.0f), 1.0f, 1.0f, color), + Vertex(Vector3(-PtHalfSz, -PtHalfSz, 0.0f), 0.0f, 1.0f, color) + }; + + Texture *tex = gc->texman->LoadTexture("STOCKTEX_BLOB"); + gc->SetTexture(0, tex); + gc->SetTextureStageColor(0, TexBlendModulate, TexArgTexture, TexArgCurrent); + gc->SetTexture(1, 0); + + gc->SetAlphaBlending(true); + gc->SetBlendFunc(BLEND_ONE, BLEND_ONE); + + gc->SetColorVertex(true); + gc->SetLighting(false); + + Matrix4x4 InvPos; + InvPos.Translate(Position.x, Position.y, Position.z); + gc->SetWorldMatrix(InvPos * GetTransform()); + + gc->SetZWrite(false); + gc->SetBillboarding(true); + gc->Draw(PointLightVisVertices, PointLightVisIndices, 4, 6); + gc->SetBillboarding(false); + gc->SetZWrite(true); + + gc->SetAlphaBlending(false); + gc->SetLighting(true); + gc->SetColorVertex(false); + gc->SetTexture(0, 0); +} + + +////////////// Spot Light //////////////// +void SpotLight::ResetTargetTransform() {} +void SpotLight::ResetTargetTranslation() {} +void SpotLight::ResetTargetRotation() {} +void SpotLight::TargetTransform(const Matrix4x4 &matrix) {} +void SpotLight::TargetTranslate(float x, float y, float z) {} +void SpotLight::TargetRotate(float x, float y, float z) {} +void SpotLight::TargetRotate(const Vector3 &axis, float angle) {} + +SpotLight::SpotLight() { + Position = Vector3(0, 100, 0); + Direction = Vector3(0, -1, 0); + Falloff = 1.0f; + Phi = QuarterPi; + Theta = Phi - (Phi / 9.0f); +} + +SpotLight::SpotLight(const Vector3 &pos, const Vector3 &dir, float InnerCone, float OuterCone, float range, float att0, float att1, float att2) { + Position = pos; + Direction = dir; + SetCone(InnerCone, OuterCone); + Range = range; + Attenuation[0] = att0; + Attenuation[1] = att1; + Attenuation[2] = att2; + Falloff = 1.0f; +} + +void SpotLight::SetDirection(const Vector3 &dir) { + Direction = dir; +} + +Vector3 SpotLight::GetDirection() const { + Vector3 dir = Direction; + dir.Transform(DirRot); + return dir; +} + +// direction transformations +void SpotLight::ResetDirTransform() { + DirRot.ResetIdentity(); +} + +void SpotLight::ResetDirRotation() { + DirRot.ResetIdentity(); +} + +void SpotLight::TransformDir(const Matrix4x4 &matrix) { + DirRot *= matrix; +} + +void SpotLight::RotateDir(float x, float y, float z) { + DirRot.Rotate(x, y, z); +} + +void SpotLight::RotateDir(const Vector3 &axis, float angle) { + DirRot.Rotate(axis, angle); +} + + +LightType SpotLight::GetType() const { + return LTSpot; +} + +void SpotLight::SetCone(float InnerCone, float OuterCone) { + Theta = InnerCone; + Phi = OuterCone; +} + +float SpotLight::GetInnerCone() const { + return Theta; +} + +float SpotLight::GetOuterCone() const { + return Phi; +} + +void SpotLight::SetFalloff(float falloff) { + Falloff = falloff; +} + +float SpotLight::GetFalloff() const { + return Falloff; +} + + +void SpotLight::SetLight(dword index, GraphicsContext *gc) const { + + Vector3 pos = Position; + pos.Transform(GetTransform()); + + Vector3 dir = Direction; + dir.Transform(DirRot); + + D3DLIGHT8 light; + memset(&light, 0, sizeof(D3DLIGHT8)); + light.Ambient.r = ambient_color.r * intensity; + light.Diffuse.r = diffuse_color.r * intensity; + light.Specular.r = specular_color.r * intensity; + light.Ambient.g = ambient_color.g * intensity; + light.Diffuse.g = diffuse_color.g * intensity; + light.Specular.g = specular_color.g * intensity; + light.Ambient.b = ambient_color.b * intensity; + light.Diffuse.b = diffuse_color.b * intensity; + light.Specular.b = specular_color.b * intensity; + light.Position = pos; + light.Direction = dir; + light.Range = Range; + light.Attenuation0 = Attenuation[0]; + light.Attenuation1 = Attenuation[1]; + light.Attenuation2 = Attenuation[2]; + light.Falloff = Falloff; + light.Theta = Theta; + light.Phi = Phi; + light.Type = (D3DLIGHTTYPE)LTSpot; + + gc->D3DDevice->SetLight(index, &light); + gc->D3DDevice->LightEnable(index, true); +} + +void SpotLight::Draw(GraphicsContext *gc, float size) { + PointLight::Draw(gc, size); +} + +//////////////// Target Spot Light //////////////////// +void TargetSpotLight::SetDirection(const Vector3 &dir) {} +Vector3 TargetSpotLight::GetDirection() const {return Vector3();} +void TargetSpotLight::ResetDirTransform() {} +void TargetSpotLight::ResetDirRotation() {} +void TargetSpotLight::TransformDir(const Matrix4x4 &matrix) {} +void TargetSpotLight::RotateDir(float x, float y, float z) {} +void TargetSpotLight::RotateDir(const Vector3 &axis, float angle) {} + +TargetSpotLight::TargetSpotLight() { + Target = Vector3(0.0f, 0.0f, 0.0f); +} + +TargetSpotLight::TargetSpotLight(const Vector3 &pos, const Vector3 &target, float InnerCone, float OuterCone, float range, float att0, float att1, float att2) { + Position = pos; + Target = target; + SetCone(InnerCone, OuterCone); + Range = range; + Attenuation[0] = att0; + Attenuation[1] = att1; + Attenuation[2] = att2; + Falloff = 1.0f; +} + +Matrix4x4 TargetSpotLight::GetTargetTransform() const { + return TargXForm * TargRot * TargTrans; +} + +void TargetSpotLight::ResetTargetTransform() { + TargRot.ResetIdentity(); + TargTrans.ResetIdentity(); + TargXForm.ResetIdentity(); +} + +void TargetSpotLight::ResetTargetTranslation() { + TargTrans.ResetIdentity(); +} + +void TargetSpotLight::ResetTargetRotation() { + TargRot.ResetIdentity(); +} + +void TargetSpotLight::TargetTransform(const Matrix4x4 &matrix) { + TargXForm *= matrix; +} + +void TargetSpotLight::TargetTranslate(float x, float y, float z) { + TargTrans.Translate(x, y, z); +} + +void TargetSpotLight::TargetRotate(float x, float y, float z) { + TargRot.Rotate(x, y, z); +} + +void TargetSpotLight::TargetRotate(const Vector3 &axis, float angle) { + TargRot.Rotate(axis, angle); +} + + +void TargetSpotLight::SetLight(dword index, GraphicsContext *gc) const { + Vector3 targ = Target; + targ.Transform(GetTargetTransform()); + + Vector3 pos = Position; + pos.Transform(GetTransform()); + + Vector3 *dir = const_cast(&Direction); + *dir = (targ - pos).Normalized(); + + SpotLight::SetLight(index, gc); +} + +void TargetSpotLight::Draw(GraphicsContext *gc, float size) { + Vector3 targ = Target; + targ.Transform(GetTargetTransform()); + + Vector3 pos = Position; + pos.Transform(GetTransform()); + + Direction = (targ - pos).Normalized(); + SpotLight::Draw(gc, size); +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/lights.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/lights.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,296 @@ +#ifndef _LIGHTS_H_ +#define _LIGHTS_H_ + +#include +#include "switches.h" +#include "n3dmath.h" +#include "3dengine.h" + +enum LightType { + LTDir = D3DLIGHT_DIRECTIONAL, + LTSpot = D3DLIGHT_SPOT, + LTPoint = D3DLIGHT_POINT +}; + +///////////////////////////////////////////////////////////////////// +// -- Abstract Base class Light -- // +// pure virtual functions for every possible light parameter, // +// implement non-applicable functions as private in each subclass. // +///////////////////////////////////////////////////////////////////// + +class Light { +protected: + float intensity; + Color ambient_color, diffuse_color, specular_color; + bool CastShadows; + +public: + std::string name; + + Light(); + + // set parameters + virtual void SetPosition(const Vector3 &pos) = 0; + virtual void SetDirection(const Vector3 &dir) = 0; + virtual void SetColor(const Color &color, PhongComponent comp = (PhongComponent)-1); + virtual void SetIntensity(float intensity); + virtual void SetRange(float range) = 0; + virtual void SetAttenuation(float att0, float att1, float att2) = 0; + virtual void SetShadowCasting(bool enable); + + // get parameters + virtual Vector3 GetPosition() const = 0; + virtual Vector3 GetDirection() const = 0; + virtual const Color &GetColor(PhongComponent comp = Diffuse) const; + virtual float GetIntensity() const; + virtual float GetRange() const = 0; + virtual float GetAttenuation(int degree) const = 0; + virtual bool GetShadowCasting() const; + + virtual LightType GetType() const = 0; + + virtual void SetCone(float InnerCone, float OuterCone) = 0; + virtual float GetInnerCone() const = 0; + virtual float GetOuterCone() const = 0; + + virtual void SetFalloff(float falloff) = 0; + virtual float GetFalloff() const = 0; + + // position transformations + virtual void ResetTransform() = 0; + virtual void ResetTranslation() = 0; + virtual void ResetRotation() = 0; + + virtual void Transform(const Matrix4x4 &matrix) = 0; + virtual void Translate(float x, float y, float z) = 0; + virtual void Rotate(float x, float y, float z) = 0; + virtual void Rotate(const Vector3 &axis, float angle) = 0; + + // direction transformations + virtual void ResetDirTransform() = 0; + virtual void ResetDirRotation() = 0; + + virtual void TransformDir(const Matrix4x4 &matrix) = 0; + virtual void RotateDir(float x, float y, float z) = 0; + virtual void RotateDir(const Vector3 &axis, float angle) = 0; + + // target transformations + virtual void ResetTargetTransform() = 0; + virtual void ResetTargetTranslation() = 0; + virtual void ResetTargetRotation() = 0; + virtual void TargetTransform(const Matrix4x4 &matrix) = 0; + virtual void TargetTranslate(float x, float y, float z) = 0; + virtual void TargetRotate(float x, float y, float z) = 0; + virtual void TargetRotate(const Vector3 &axis, float angle) = 0; + + virtual void SetLight(dword index, GraphicsContext *gc) const = 0; + + virtual void Draw(GraphicsContext *gc, float size = 1.0f) = 0; +}; + +// Directional Light +class DirLight : public Light { +private: + // Non-Applicable functions for this type of light + virtual void SetPosition(const Vector3 &pos); + virtual void SetRange(float range); + virtual void SetAttenuation(float att0, float att1, float att2); + virtual Vector3 GetPosition() const; + virtual float GetRange() const; + virtual float GetAttenuation(int degree) const; + virtual void ResetTransform(); + virtual void ResetTranslation(); + virtual void ResetRotation(); + virtual void Transform(const Matrix4x4 &matrix); + virtual void Translate(float x, float y, float z); + virtual void Rotate(float x, float y, float z); + virtual void Rotate(const Vector3 &axis, float angle); + virtual void ResetTargetTransform(); + virtual void ResetTargetTranslation(); + virtual void ResetTargetRotation(); + virtual void TargetTransform(const Matrix4x4 &matrix); + virtual void TargetTranslate(float x, float y, float z); + virtual void TargetRotate(float x, float y, float z); + virtual void TargetRotate(const Vector3 &axis, float angle); + virtual void SetCone(float InnerCone, float OuterCone); + virtual float GetInnerCone() const; + virtual float GetOuterCone() const; + virtual void SetFalloff(float falloff); + virtual float GetFalloff() const; + + +protected: + Vector3 Direction; + Matrix4x4 DirRot; + +public: + DirLight(); + DirLight(const Vector3 &dir); + + // accessors + virtual void SetDirection(const Vector3 &dir); + virtual Vector3 GetDirection() const; + + virtual LightType GetType() const; + + // direction transformations + virtual void ResetDirTransform(); + virtual void ResetDirRotation(); + + virtual void TransformDir(const Matrix4x4 &matrix); + virtual void RotateDir(float x, float y, float z); + virtual void RotateDir(const Vector3 &axis, float angle); + + virtual void SetLight(dword index, GraphicsContext *gc) const; + + virtual void Draw(GraphicsContext *gc, float size = 1.0f); +}; + +// Point Light (omni) +class PointLight : public Light { +private: + // Non-Applicable member functions + virtual void SetDirection(const Vector3 &dir); + virtual Vector3 GetDirection() const; + virtual void ResetDirTransform(); + virtual void ResetDirRotation(); + virtual void TransformDir(const Matrix4x4 &matrix); + virtual void RotateDir(float x, float y, float z); + virtual void RotateDir(const Vector3 &axis, float angle); + virtual void ResetTargetTransform(); + virtual void ResetTargetTranslation(); + virtual void ResetTargetRotation(); + virtual void TargetTransform(const Matrix4x4 &matrix); + virtual void TargetTranslate(float x, float y, float z); + virtual void TargetRotate(float x, float y, float z); + virtual void TargetRotate(const Vector3 &axis, float angle); + virtual void SetCone(float InnerCone, float OuterCone); + virtual float GetInnerCone() const; + virtual float GetOuterCone() const; + virtual void SetFalloff(float falloff); + virtual float GetFalloff() const; + +protected: + Vector3 Position; + float Range; + float Attenuation[3]; + + Matrix4x4 PosRot, PosTrans, PosXForm; + + virtual Matrix4x4 GetTransform() const; + +public: + PointLight(); + PointLight(const Vector3 &pos, float range = 1000.0f, float att0 = 1.0f, float att1 = 0.0f, float att2 = 0.0f); + + // accessors + virtual void SetPosition(const Vector3 &pos); + virtual void SetRange(float range); + virtual void SetAttenuation(float att0, float att1, float att2); + + virtual Vector3 GetPosition() const; + virtual float GetRange() const; + virtual float GetAttenuation(int degree) const; + + virtual LightType GetType() const; + + // position transformations + virtual void ResetTransform(); + virtual void ResetTranslation(); + virtual void ResetRotation(); + + virtual void Transform(const Matrix4x4 &matrix); + virtual void Translate(float x, float y, float z); + virtual void Rotate(float x, float y, float z); + virtual void Rotate(const Vector3 &axis, float angle); + + virtual void SetLight(dword index, GraphicsContext *gc) const; + + virtual void Draw(GraphicsContext *gc, float size = 100.0f); +}; + +// Spotlight +class SpotLight : public PointLight { +private: + virtual void ResetTargetTransform(); + virtual void ResetTargetTranslation(); + virtual void ResetTargetRotation(); + virtual void TargetTransform(const Matrix4x4 &matrix); + virtual void TargetTranslate(float x, float y, float z); + virtual void TargetRotate(float x, float y, float z); + virtual void TargetRotate(const Vector3 &axis, float angle); + +protected: + Vector3 Direction; + Matrix4x4 DirRot; + + float Falloff; + float Theta, Phi; + +public: + SpotLight(); + SpotLight(const Vector3 &pos, const Vector3 &dir, float InnerCone, float OuterCone, float range = 1000.0f, float att0 = 1.0f, float att1 = 0.0f, float att2 = 0.0f); + + // accessors + virtual void SetDirection(const Vector3 &dir); + virtual Vector3 GetDirection() const; + + // direction transformations + virtual void ResetDirTransform(); + virtual void ResetDirRotation(); + + virtual void TransformDir(const Matrix4x4 &matrix); + virtual void RotateDir(float x, float y, float z); + virtual void RotateDir(const Vector3 &axis, float angle); + + virtual LightType GetType() const; + + virtual void SetCone(float InnerCone, float OuterCone); + virtual float GetInnerCone() const; + virtual float GetOuterCone() const; + + virtual void SetFalloff(float falloff); + virtual float GetFalloff() const; + + virtual void SetLight(dword index, GraphicsContext *gc) const; + + virtual void Draw(GraphicsContext *gc, float size = 100.0f); +}; + +class TargetSpotLight : public SpotLight { +private: + // Non-Applicable shit + virtual void SetDirection(const Vector3 &dir); + virtual Vector3 GetDirection() const; + virtual void ResetDirTransform(); + virtual void ResetDirRotation(); + virtual void TransformDir(const Matrix4x4 &matrix); + virtual void RotateDir(float x, float y, float z); + virtual void RotateDir(const Vector3 &axis, float angle); + +protected: + Vector3 Target; + Matrix4x4 TargRot, TargTrans, TargXForm; + + virtual Matrix4x4 GetTargetTransform() const; + +public: + + TargetSpotLight(); + TargetSpotLight(const Vector3 &pos, const Vector3 &target, float InnerCone, float OuterCone, float range = 1000.0f, float att0 = 1.0f, float att1 = 0.0f, float att2 = 0.0f); + + virtual void ResetTargetTransform(); + virtual void ResetTargetTranslation(); + virtual void ResetTargetRotation(); + + virtual void TargetTransform(const Matrix4x4 &matrix); + virtual void TargetTranslate(float x, float y, float z); + virtual void TargetRotate(float x, float y, float z); + virtual void TargetRotate(const Vector3 &axis, float angle); + + virtual void SetLight(dword index, GraphicsContext *gc) const; + + virtual void Draw(GraphicsContext *gc, float size = 100.0f); +}; + +#endif // _LIGHTS_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/material.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/material.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,99 @@ +#include "material.h" + +Material::Material() { + memset(this, 0, sizeof(Material)); + Diffuse.r = Ambient.r = 1.0f; + Diffuse.g = Ambient.g = 1.0f; + Diffuse.b = Ambient.b = 1.0f; + Diffuse.a = Ambient.a = 1.0f; + Specular.r = Specular.g = Specular.b = 1.0f; + EnvBlend = 1.0f; + Alpha = 1.0f; +} + +Material::Material(float r, float g, float b, float a) { + + memset(this, 0, sizeof(Material)); + Diffuse.r = Ambient.r = r; + Diffuse.g = Ambient.g = g; + Diffuse.b = Ambient.b = b; + Diffuse.a = Ambient.a = a; + Specular.r = Specular.g = Specular.b = 1.0f; + EnvBlend = 1.0f; + Alpha = 1.0f; +} + +void Material::SetAmbient(float r, float g, float b) { + Ambient.r = r; + Ambient.g = g; + Ambient.b = b; + Ambient.a = 1.0f; +} + +void Material::SetAmbient(const Color &col) { + Ambient.r = col.r; + Ambient.g = col.g; + Ambient.b = col.b; + Ambient.a = col.a; +} + + +void Material::SetDiffuse(float r, float g, float b) { + Diffuse.r = r; + Diffuse.g = g; + Diffuse.b = b; + Diffuse.a = 1.0f; +} + +void Material::SetDiffuse(const Color &col) { + Diffuse.r = col.r; + Diffuse.g = col.g; + Diffuse.b = col.b; + Diffuse.a = col.a; +} + + +void Material::SetSpecular(float r, float g, float b) { + Specular.r = r; + Specular.g = g; + Specular.b = b; + Specular.a = 1.0f; +} + +void Material::SetSpecular(const Color &col) { + Specular.r = col.r; + Specular.g = col.g; + Specular.b = col.b; + Specular.a = col.a; +} + +void Material::SetEmissive(float r, float g, float b) { + Emissive.r = r; + Emissive.g = g; + Emissive.b = b; + Emissive.a = 1.0f; +} + +void Material::SetEmissive(const Color &col) { + Emissive.r = col.r; + Emissive.g = col.g; + Emissive.b = col.b; + Emissive.a = col.a; +} + +void Material::SetEnvBlend(float value) { + EnvBlend = value; +} + +void Material::SetSpecularPower(float pow) { + Power = pow; + SpecularEnable = pow > 0.0f ? true : false; +} + +void Material::SetAlpha(float alpha) { + Alpha = alpha; +} + +void Material::SetTexture(Texture *texture, TextureType type) { + Maps[type] = texture; +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/material.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/material.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,49 @@ +#ifndef _MATERIAL_H_ +#define _MATERIAL_H_ + +#include +#include +#include "d3d8.h" +#include "3dengtypes.h" +#include "color.h" + +enum TextureType { + TextureMap = 0, + DetailMap, + OpacityMap, + LightMap, + BumpMap, + EnvironmentMap, + SpecularMap +}; + +const int NumberOfTextureTypes = 7; + +class Material : public D3DMATERIAL8 { +public: + std::string name; + Texture *Maps[NumberOfTextureTypes]; + float EnvBlend, BumpIntensity; + float Alpha; + bool SpecularEnable; + + Material(); + Material(float r, float g, float b, float a=1.0f); + + void SetAmbient(float r, float g, float b); + void SetAmbient(const Color &col); + void SetDiffuse(float r, float g, float b); + void SetDiffuse(const Color &col); + void SetSpecular(float r, float g, float b); + void SetSpecular(const Color &col); + void SetEmissive(float r, float g, float b); + void SetEmissive(const Color &col); + void SetSpecularPower(float pow); + void SetAlpha(float alpha); + void SetEnvBlend(float value); + + void SetTexture(Texture *texture, TextureType type); +}; + + +#endif // _MATERIAL_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/motion.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/motion.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,50 @@ +#include "motion.h" + +MotionController::MotionController() { + memset(this, 0, sizeof(MotionController)); +} + +void MotionController::SetTranslation(float (*xtrans)(float), float (*ytrans)(float), float (*ztrans)(float), float ScaleInput) { + XTranslation = xtrans; + YTranslation = ytrans; + ZTranslation = ytrans; + ScaleInputTrans = ScaleInput; +} + +void MotionController::SetRotation(float (*xrot)(float), float (*yrot)(float), float (*zrot)(float), float ScaleInput) { + XRotation = xrot; + YRotation = yrot; + ZRotation = zrot; + ScaleInputRot = ScaleInput; +} + +void MotionController::SetScaling(float (*xscale)(float), float (*yscale)(float), float (*zscale)(float), float ScaleInput) { + XScaling = xscale; + YScaling = yscale; + ZScaling = zscale; + ScaleInputScale = ScaleInput; +} + +void MotionController::SetPath(const Curve &path) { + FollowPath = true; + // TODO +} + +const Matrix4x4 &MotionController::GetTransformation(float t) { + MotionXForm.ResetIdentity(); + + if(FollowPath) { + // TODO + } else { + float tt = t * ScaleInputTrans; + float tr = t * ScaleInputRot; + float ts = t * ScaleInputScale; + MotionXForm.Scale(XScaling ? XScaling(tt) : 0, YScaling ? YScaling(tt) : 0, ZScaling ? ZScaling(tt) : 0); + MotionXForm.Rotate(XRotation ? XRotation(tr) : 0, YRotation ? YRotation(tr) : 0, ZRotation ? ZRotation(tr) : 0); + MotionXForm.Translate(XTranslation ? XTranslation(ts) : 0, YTranslation ? YTranslation(ts) : 0, ZTranslation ? ZTranslation(ts) : 0); + } + + return MotionXForm; +} + + diff -r 000000000000 -r 1cffe3409164 src/3deng/motion.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/motion.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,37 @@ +#ifndef _MOTION_H_ +#define _MOTION_H_ + +#include "n3dmath.h" +#include "curves.h" + +class MotionController { +private: + Matrix4x4 MotionXForm; + bool FollowPath; + float ScaleInputTrans, ScaleInputRot, ScaleInputScale; + + float (*XTranslation)(float); + float (*YTranslation)(float); + float (*ZTranslation)(float); + float (*XRotation)(float); + float (*YRotation)(float); + float (*ZRotation)(float); + float (*XScaling)(float); + float (*YScaling)(float); + float (*ZScaling)(float); + +public: + + MotionController(); + + void SetTranslation(float (*xtrans)(float), float (*ytrans)(float), float (*ztrans)(float), float ScaleInput = 1.0f); + void SetRotation(float (*xrot)(float), float (*yrot)(float), float (*zrot)(float), float ScaleInput = 1.0f); + void SetScaling(float (*xscale)(float), float (*yscale)(float), float (*zscale)(float), float ScaleInput = 1.0f); + void SetPath(const Curve &path); + + const Matrix4x4 &GetTransformation(float t); +}; + + + +#endif // _MOTION_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/objectgen.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/objectgen.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,155 @@ +#include "objectgen.h" +#include "n3dmath.h" + +struct Quad { + Index verts[4]; + Vector3 norm; +}; + +/////////////////////////////////////////////// +// --==( Generate a tesselated plane )==-- // +/////////////////////////////////////////////// + +void ObjGen::CreatePlane(GraphicsContext *gc, float size, dword subdivisions, TriMesh **mesh, byte LODLevels) { + + dword VertexNum = (subdivisions+2) * (subdivisions+2); + dword TriNum = ((subdivisions+1) * (subdivisions+1)) << 1; + int QuadNum = TriNum >> 1; + int QuadsRow = subdivisions+1; // quads per row + int VertsRow = subdivisions+2; // vertices per row + int VertsCol = VertsRow; + + Vertex *varray = new Vertex[VertexNum]; + Triangle *tarray = new Triangle[TriNum]; + + for(int j=0; jSetData(varray, tarray, VertexNum, TriNum); + + delete [] quads; + delete [] varray; + delete [] tarray; +} + + + + +///////////////////////////////////////////////////////// +// --==( Generate Cube without shared vertices )==-- // +///////////////////////////////////////////////////////// + +void ObjGen::CreateCube(GraphicsContext *gc, float size, TriMesh **mesh, byte LODLevels) { + + Vertex verts[36]; + verts[0] = Vertex(Vector3(-1, +1, -1), 0, 0); + verts[1] = Vertex(Vector3(+1, +1, -1), 1, 0); + verts[2] = Vertex(Vector3(+1, -1, -1), 1, 1); + verts[3] = Vertex(Vector3(-1, +1, -1), 0, 0); + verts[4] = Vertex(Vector3(+1, -1, -1), 1, 1); + verts[5] = Vertex(Vector3(-1, -1, -1), 0, 1); + verts[6] = Vertex(Vector3(-1, +1, +1), 0, 0); + verts[7] = Vertex(Vector3(-1, +1, -1), 1, 0); + verts[8] = Vertex(Vector3(-1, -1, -1), 1, 1); + verts[9] = Vertex(Vector3(-1, +1, +1), 0, 0); + verts[10] = Vertex(Vector3(-1, -1, -1), 1, 1); + verts[11] = Vertex(Vector3(-1, -1, +1), 0, 1); + verts[12] = Vertex(Vector3(-1, +1, +1), 1, 0); + verts[13] = Vertex(Vector3(-1, -1, +1), 1, 1); + verts[14] = Vertex(Vector3(+1, +1, +1), 0, 0); + verts[15] = Vertex(Vector3(+1, +1, +1), 0, 0); + verts[16] = Vertex(Vector3(-1, -1, +1), 1, 1); + verts[17] = Vertex(Vector3(+1, -1, +1), 0, 1); + verts[18] = Vertex(Vector3(+1, +1, -1), 0, 0); + verts[19] = Vertex(Vector3(+1, +1, +1), 1, 0); + verts[20] = Vertex(Vector3(+1, -1, +1), 1, 1); + verts[21] = Vertex(Vector3(+1, +1, -1), 0, 0); + verts[22] = Vertex(Vector3(+1, -1, +1), 1, 1); + verts[23] = Vertex(Vector3(+1, -1, -1), 0, 1); + verts[24] = Vertex(Vector3(-1, +1, -1), 0, 1); + verts[25] = Vertex(Vector3(+1, +1, +1), 1, 0); + verts[26] = Vertex(Vector3(+1, +1, -1), 1, 1); + verts[27] = Vertex(Vector3(-1, +1, +1), 0, 0); + verts[28] = Vertex(Vector3(+1, +1, +1), 1, 0); + verts[29] = Vertex(Vector3(-1, +1, -1), 0, 1); + verts[30] = Vertex(Vector3(-1, -1, +1), 0, 1); + verts[31] = Vertex(Vector3(-1, -1, -1), 0, 0); + verts[32] = Vertex(Vector3(+1, -1, +1), 1, 1); + verts[33] = Vertex(Vector3(-1, -1, -1), 0, 0); + verts[34] = Vertex(Vector3(+1, -1, -1), 1, 0); + verts[35] = Vertex(Vector3(+1, -1, +1), 1, 1); + + Triangle tri[12]; + for(int i=0; i<12; i++) { + tri[i].vertices[0] = i*3; + tri[i].vertices[1] = i*3+1; + tri[i].vertices[2] = i*3+2; + } + + for(int i=0; i<36; i++) { + verts[i].pos *= size / 2.0f; + verts[i].color = 0x00ffffff; + } + + TriMesh *tmpmesh = new TriMesh(LODLevels, gc); + tmpmesh->SetData(verts, tri, 36, 12); + + tmpmesh->CalculateNormals(); + + *mesh = tmpmesh; +} + + +///////////////////////////////////// +// --==( Generate Cylinder )==-- // +///////////////////////////////////// +/* +void ObjGen::CreateCylinder(float radius, float height, int sides, int hsegs, bool caps, TriMesh **mesh, byte LODLevels) { + + int slices = hsegs + 1; + unsigned long vertex_count = sides * slices + (caps ? (sides + 1)<<1 : 0); + unsigned long tri_count = (sides << 1) * (slices - 1) + (caps ? sides : 0); + + Vertex *varray = new Vertex[vertex_count]; + Triangle *tarray = new Triangle[tri_count]; + + Vertex *vptr = varray; + Triangle *tptr = tarray; + + // create a circle by rotating a vector around the y axis + Vector3 x_axis(radius, 0, 0); + + float rot_rads = TwoPi / (float)sides; + for(int i=0; igc = gc; + + mesh = new TriMesh(DetailLevels, gc); + + SetShadingMode(GouraudShading); + SetVertexProgram(FixedFunction); + SetPixelProgram(0); + rendp.Billboarded = false; + rendp.SourceBlendFactor = BLEND_SRCALPHA; + rendp.DestBlendFactor = BLEND_INVSRCALPHA; + rendp.ZWrite = true; + ShadowCount = 0; + UseTextureMatrix = false; + + ShadowVolumes = 0; + CastShadows = false; + + AutoSetZWrite = true; +} + +Object::~Object() { + delete mesh; + if(rendp.VertexProgram != FixedFunction) gc->DestroyVertexProgram(rendp.VertexProgram); +} + +TriMesh *Object::GetTriMesh() { + return mesh; +} + + +// Reset Transformation Matrices +void Object::ResetTransform() { + TransMat.ResetIdentity(); + RotMat.ResetIdentity(); + GRotMat.ResetIdentity(); + ScaleMat.ResetIdentity(); +} + +void Object::ResetTranslation() { + TransMat.ResetIdentity(); +} + +void Object::ResetRotation() { + RotMat.ResetIdentity(); +} + +void Object::ResetGlobalRotation() { + GRotMat.ResetIdentity(); +} + +void Object::ResetScaling() { + ScaleMat.ResetIdentity(); +} + +// Concatenate additional transformations +void Object::Translate(float tx, float ty, float tz) { + TransMat.Translate(tx, ty, tz); +} + +void Object::Rotate(float rx, float ry, float rz) { + RotMat.Rotate(rx, ry, rz); +} + +void Object::Rotate(const Vector3 &axis, float angle) { + RotMat.Rotate(axis, angle); +} + +void Object::Rotate(const Matrix4x4 &rot) { + RotMat *= rot; +} + +void Object::GlobalRotate(float rx, float ry, float rz) { + GRotMat.Rotate(rx, ry, rz); +} + +void Object::GlobalRotate(const Vector3 &axis, float angle) { + GRotMat.Rotate(axis, angle); +} + +void Object::GlobalRotate(const Matrix4x4 &rot) { + GRotMat *= rot; +} + +void Object::Scale(float sx, float sy, float sz) { + ScaleMat.Scale(sx, sy, sz); +} + +void Object::SetTranslation(float tx, float ty, float tz) { + TransMat.SetTranslation(tx, ty, tz); +} + +void Object::SetRotation(float rx, float ry, float rz) { + RotMat.Rotate(rx, ry, rz); +} + +void Object::SetRotation(const Vector3 &axis, float angle) { + RotMat.Rotate(axis, angle); +} + +void Object::SetRotation(const Matrix4x4 &rot) { + RotMat = rot; +} + +void Object::SetGlobalRotation(float rx, float ry, float rz) { + GRotMat.Rotate(rx, ry, rz); +} + +void Object::SetGlobalRotation(const Vector3 &axis, float angle) { + GRotMat.Rotate(axis, angle); +} + +void Object::SetGlobalRotation(const Matrix4x4 &rot) { + GRotMat = rot; +} + +void Object::SetScaling(float sx, float sy, float sz) { + ScaleMat.Scale(sx, sy, sz); +} + +const Matrix4x4 Object::GetWorldTransform() const { + return ScaleMat * RotMat * TransMat * GRotMat; +} + +void Object::SetTextureMatrix(Matrix4x4 mat) { + UseTextureMatrix = true; + TextureMatrix = mat; +} + +Matrix4x4 Object::GetTextureMatrix() const { + return TextureMatrix; +} + +void Object::SetVertexProgram(dword VertexProgram) { + rendp.VertexProgram = VertexProgram; +} + +void Object::SetPixelProgram(dword PixelProgram) { + rendp.PixelProgram = PixelProgram; +} + +void Object::SetShadingMode(ShadeMode smode) { + rendp.Shading = smode; +} + +void Object::SetWriteZBuffer(bool enable) { + rendp.ZWrite = enable; + AutoSetZWrite = false; +} + +void Object::SetBlendFunc(BlendingFactor src, BlendingFactor dest) { + rendp.SourceBlendFactor = src; + rendp.DestBlendFactor = dest; +} + +void Object::GetBlendFunc(BlendingFactor *src, BlendingFactor *dest) { + *src = rendp.SourceBlendFactor; + *dest = rendp.DestBlendFactor; +} + +void Object::CalculateShadows(const Light **lights, int LightCount) { + if(ShadowVolumes) { + for(int i=0; i= ShadowCount) return 0; + return ShadowVolumes[light]; +} + +void Object::SetShadowCasting(bool enable) { + CastShadows = enable; +} + +bool Object::GetShadowCasting() const { + return CastShadows; +} + +/////////////////////////// + +void Object::SetRenderStates() { + gc->SetWorldMatrix(GetWorldTransform()); + + gc->SetMaterial(material); + if(AutoSetZWrite && material.Alpha < 0.991f) rendp.ZWrite = false; + gc->SetSpecular(material.SpecularEnable); + + gc->SetVertexProgram(rendp.VertexProgram); + gc->SetPixelProgram(rendp.PixelProgram); + gc->SetShadingMode(rendp.Shading); +} + +void Object::Render() { + int TexUnits = gc->GetTextureStageNumber(); + + if(TexUnits < 4) { + Render2TexUnits(); + } else if(TexUnits < 8) { + Render4TexUnits(); + } else { + Render8TexUnits(); + } +} + +void Object::Render2TexUnits() { + + SetRenderStates(); + + VertexBuffer *vb = const_cast(mesh->GetVertexBuffer()); + IndexBuffer *ib = const_cast(mesh->GetIndexBuffer()); + + Material mat = material; + + int TexCount = 0; + for(int i=0; iSetZWrite(false); + + if(!TexCount) { + // render without any texture + gc->SetTexture(0, 0); + gc->SetTextureStageColor(0, TexBlendSelectArg1, TexArgDiffuseColor, TexArgTexture); + if(mat.Alpha < 1.0f) { + gc->SetTextureFactor(Color(mat.Alpha, mat.Alpha, mat.Alpha, mat.Alpha).GetPacked32()); + gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgFactor, TexArgDiffuseColor); + } else { + gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgCurrent, TexArgTexture); + } + gc->DisableTextureStage(1); + + gc->SetAlphaBlending(true); + gc->SetBlendFunc(rendp.SourceBlendFactor, rendp.DestBlendFactor); + gc->Draw(vb, ib); + gc->SetAlphaBlending(false); + } else { + + ////////// pass 1 (texture & env) /////////// + int stage = 0; + if(mat.Maps[TextureMap]) { + if(UseTextureMatrix) gc->SetTextureMatrix(TextureMatrix, 0); + gc->SetTexture(stage, mat.Maps[TextureMap]); + gc->SetTextureStageColor(stage, TexBlendModulate, TexArgCurrent, TexArgTexture); + if(mat.Alpha < 1.0f) { + gc->SetTextureFactor(Color(mat.Alpha, mat.Alpha, mat.Alpha, mat.Alpha).GetPacked32()); + gc->SetTextureStageAlpha(stage, TexBlendModulate, TexArgTexture, TexArgFactor); + } else { + gc->SetTextureStageAlpha(stage, TexBlendSelectArg2, TexArgCurrent, TexArgTexture); + } + gc->SetTextureCoordIndex(stage, 0); + stage++; + } + + if(mat.Maps[EnvironmentMap]) { + gc->SetTexture(stage, mat.Maps[EnvironmentMap]); + gc->SetTextureStageColor(stage, TexBlendAdd, TexArgCurrent, TexArgTexture); + gc->SetTextureStageAlpha(stage, TexBlendSelectArg1, TexArgCurrent, TexArgTexture); + Matrix4x4 TexMat = Matrix4x4(0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f); + gc->SetTextureMatrix(TexMat, stage); + gc->D3DDevice->SetTextureStageState(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + gc->D3DDevice->SetTextureStageState(stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL); + stage++; + } + + gc->SetTexture(stage, 0); + gc->DisableTextureStage(stage); + + if(stage > 0) { + gc->SetAlphaBlending(true); + gc->SetBlendFunc(rendp.SourceBlendFactor, rendp.DestBlendFactor); + gc->Draw(vb, ib); + gc->SetAlphaBlending(false); + + gc->SetTextureMatrix(Matrix4x4(), 0); + gc->SetTextureMatrix(Matrix4x4(), 1); + } + + ////////// pass 2 (Bump & Lightmap) ////////// + if(stage > 0) { // did a first pass + gc->SetAlphaBlending(true); + gc->SetBlendFunc(BLEND_DESTCOLOR, BLEND_ZERO); // mult blend + mat.Emissive = Color(1.0f); // do not recalculate lighting + } + + stage = 0; + if(mat.Maps[LightMap]) { + gc->SetTexture(stage, mat.Maps[LightMap]); + gc->SetTextureStageColor(stage, TexBlendSelectArg2, TexArgCurrent, TexArgTexture); + gc->SetTextureStageAlpha(stage, TexBlendSelectArg1, TexArgCurrent, TexArgTexture); + gc->SetTextureCoordIndex(stage, 1); + stage++; + } + + if(mat.Maps[BumpMap]) { + // re-implementation due + } + + gc->SetTexture(stage, 0); + gc->DisableTextureStage(stage); + + if(stage > 0) gc->Draw(vb, ib); + + gc->SetAlphaBlending(false); + } + + if(!rendp.ZWrite) gc->SetZWrite(true); +} + + +void Object::Render4TexUnits() { + SetRenderStates(); + + VertexBuffer *vb = const_cast(mesh->GetVertexBuffer()); + IndexBuffer *ib = const_cast(mesh->GetIndexBuffer()); + + Material mat = material; + + int TexCount = 0; + for(int i=0; iSetZWrite(false); + + if(!TexCount) { + // render without any texture + gc->SetTexture(0, 0); + gc->SetTextureStageColor(0, TexBlendSelectArg1, TexArgDiffuseColor, TexArgTexture); + if(mat.Alpha < 1.0f) { + gc->SetTextureFactor(Color(mat.Alpha, mat.Alpha, mat.Alpha, mat.Alpha).GetPacked32()); + gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgFactor, TexArgDiffuseColor); + } else { + gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgCurrent, TexArgTexture); + } + gc->DisableTextureStage(1); + + gc->SetAlphaBlending(true); + gc->SetBlendFunc(rendp.SourceBlendFactor, rendp.DestBlendFactor); + gc->Draw(vb, ib); + gc->SetAlphaBlending(false); + } else { + + ////////// pass 1 (texture, detail, env, bump) /////////// + int stage = 0; + if(mat.Maps[TextureMap]) { + if(UseTextureMatrix) gc->SetTextureMatrix(TextureMatrix, 0); + gc->SetTexture(stage, mat.Maps[TextureMap]); + gc->SetTextureStageColor(stage, TexBlendModulate, TexArgCurrent, TexArgTexture); + if(mat.Alpha < 1.0f) { + gc->SetTextureFactor(Color(mat.Alpha, mat.Alpha, mat.Alpha, mat.Alpha).GetPacked32()); + gc->SetTextureStageAlpha(stage, TexBlendModulate, TexArgTexture, TexArgFactor); + } else { + gc->SetTextureStageAlpha(stage, TexBlendSelectArg2, TexArgCurrent, TexArgTexture); + } + gc->SetTextureCoordIndex(stage, 0); + stage++; + } + + if(mat.Maps[DetailMap]) { + gc->SetTexture(stage, mat.Maps[DetailMap]); + gc->SetTextureStageColor(stage, TexBlendAdd, TexArgCurrent, TexArgTexture); + gc->SetTextureStageAlpha(stage, TexBlendSelectArg1, TexArgCurrent, TexArgTexture); + gc->SetTextureCoordIndex(stage, 1); + stage++; + } + + if(mat.Maps[EnvironmentMap]) { + gc->SetTexture(stage, mat.Maps[EnvironmentMap]); + gc->SetTextureStageColor(stage, TexBlendAdd, TexArgCurrent, TexArgTexture); + gc->SetTextureStageAlpha(stage, TexBlendSelectArg1, TexArgCurrent, TexArgTexture); + Matrix4x4 TexMat = Matrix4x4(0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f); + gc->SetTextureMatrix(TexMat, stage); + gc->D3DDevice->SetTextureStageState(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + gc->D3DDevice->SetTextureStageState(stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL); + stage++; + } + + if(mat.Maps[BumpMap]) { + // re-implementation due + } + + gc->SetTexture(stage, 0); + gc->DisableTextureStage(stage); + + if(stage > 0) { + gc->SetAlphaBlending(true); + gc->SetBlendFunc(rendp.SourceBlendFactor, rendp.DestBlendFactor); + gc->Draw(vb, ib); + gc->SetAlphaBlending(false); + + gc->SetTextureMatrix(Matrix4x4(), 0); + gc->SetTextureMatrix(Matrix4x4(), 1); + gc->SetTextureMatrix(Matrix4x4(), 2); + } + + ////////// pass 2 (Bump & Lightmap) ////////// + if(stage > 0) { // did a first pass + gc->SetAlphaBlending(true); + gc->SetBlendFunc(BLEND_DESTCOLOR, BLEND_ZERO); // mult blend + mat.Emissive = Color(1.0f); // do not recalculate lighting + } + + stage = 0; + if(mat.Maps[LightMap]) { + gc->SetTexture(stage, mat.Maps[LightMap]); + gc->SetTextureStageColor(stage, TexBlendSelectArg2, TexArgCurrent, TexArgTexture); + gc->SetTextureStageAlpha(stage, TexBlendSelectArg1, TexArgCurrent, TexArgTexture); + gc->SetTextureCoordIndex(stage, 1); + stage++; + } + + gc->SetTexture(stage, 0); + gc->DisableTextureStage(stage); + + if(stage > 0) gc->Draw(vb, ib); + + gc->SetAlphaBlending(false); + } + + if(!rendp.ZWrite) gc->SetZWrite(false); +} + + +void Object::Render8TexUnits() {Render4TexUnits();} + + + +/* +void Object::Render() { + + SetRenderStates(); + + VertexBuffer *vb = const_cast(mesh->GetVertexBuffer()); + IndexBuffer *ib = const_cast(mesh->GetIndexBuffer()); + + Material mat = material; + int MapsCount = 0, ActiveTex = 0; + for(int i=0; iSetTexture(0, 0); + gc->DisableTextureStage(0); + gc->Draw(vb, ib); + } else { + int pass = 1; + TextureType PassFirstTexture; + while(MapsCount) { + + if(mat.Maps[BumpMap]) { + gc->SetTexture(ActiveTex, mat.Maps[BumpMap]); + //gc->SetTextureFactor() TODO + gc->SetTextureStageColor(ActiveTex, TexBlendDotProduct, TexArgFactor, TexArgTexture); + mat.Maps[BumpMap] = 0; + if(!ActiveTex) PassFirstTexture = BumpMap; + } else if(mat.Maps[TextureMap]) { + gc->SetTexture(ActiveTex, mat.Maps[TextureMap]); + gc->SetTextureStageColor(ActiveTex, TexBlendModulate, TexArgCurrent, TexArgTexture); + //gc->SetTextureStageColor(ActiveTex, TexBlendSelectArg2, TexArgCurrent, TexArgTexture); + gc->SetTextureCoordIndex(ActiveTex, 0); + mat.Maps[TextureMap] = 0; + if(!ActiveTex) PassFirstTexture = TextureMap; + } else if(mat.Maps[DetailMap]) { + gc->SetTexture(ActiveTex, mat.Maps[DetailMap]); + gc->SetTextureStageColor(ActiveTex, TexBlendAdd, TexArgCurrent, TexArgTexture); + gc->SetTextureCoordIndex(ActiveTex, 1); + mat.Maps[DetailMap] = 0; + if(!ActiveTex) PassFirstTexture = DetailMap; + } else if(mat.Maps[EnvironmentMap]) { + gc->SetTexture(ActiveTex, mat.Maps[EnvironmentMap]); + gc->SetTextureStageColor(ActiveTex, TexBlendAdd, TexArgCurrent, TexArgTexture); + + //gc->SetTextureCoordGenerator(TexGenSpherical); TODO + Matrix4x4 TexMat = Matrix4x4(0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, -0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.0f, 1.0f ); + gc->SetTextureMatrix(TexMat, ActiveTex); + gc->D3DDevice->SetTextureStageState(ActiveTex, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + gc->D3DDevice->SetTextureStageState(ActiveTex, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL); + + mat.Maps[EnvironmentMap] = 0; + if(!ActiveTex) PassFirstTexture = EnvironmentMap; + } else if(mat.Maps[LightMap]) { + gc->SetTexture(ActiveTex, mat.Maps[LightMap]); + gc->SetTextureStageColor(ActiveTex, TexBlendModulate, TexArgCurrent, TexArgTexture); + gc->SetTextureCoordIndex(ActiveTex, 2); + mat.Maps[LightMap] = 0; + if(!ActiveTex) PassFirstTexture = LightMap; + } + + MapsCount--; + ActiveTex++; + + if(!MapsCount) { + gc->SetTextureStageColor(ActiveTex, TexBlendModulate, TexArgCurrent, TexArgDiffuseColor); + } + + if(ActiveTex >= gc->GetTextureStageNumber() || !MapsCount) { + if(pass++ > 1) { + gc->SetAlphaBlending(true); + if(PassFirstTexture == DetailMap || PassFirstTexture == EnvironmentMap) { + gc->SetBlendFunc(BLEND_ONE, BLEND_ONE); + } else { + gc->SetBlendFunc(BLEND_DESTCOLOR, BLEND_ZERO); + } + gc->Draw(vb, ib); + gc->SetAlphaBlending(false); + } else { + gc->Draw(vb, ib); + } + ActiveTex = 0; + for(int i=0; iGetTextureStageNumber(); i++) { + gc->SetTextureMatrix(Matrix4x4(), i); + } + } + } + } + + if(material.SpecularEnable) gc->SetSpecular(false); +} +*/ + + + +void Object::RenderBare() { + VertexBuffer *vb = const_cast(mesh->GetVertexBuffer()); + IndexBuffer *ib = const_cast(mesh->GetIndexBuffer()); + gc->Draw(vb, ib); +} + + +// generate geometry +void Object::CreatePlane(float size, dword subdivisions) { + ObjGen::CreatePlane(gc, size, subdivisions, &mesh, mesh->GetLevelCount()); +} + +void Object::CreateCube(float size) { + ObjGen::CreateCube(gc, size, &mesh, mesh->GetLevelCount()); +} diff -r 000000000000 -r 1cffe3409164 src/3deng/objects.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/objects.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,97 @@ +#ifndef _OBJECTS_H_ +#define _OBJECTS_H_ + +#include +#include "3dengine.h" +#include "n3dmath.h" +#include "3dgeom.h" +#include "material.h" +#include "motion.h" + +class Object { +protected: + GraphicsContext *gc; + RenderParams rendp; + + TriMesh *mesh; + TriMesh **ShadowVolumes; + int ShadowCount; + bool CastShadows; + + Matrix4x4 WorldXForm; +// Matrix4x4 TransMat, RotMat, ScaleMat, GRotMat; + Matrix4x4 TextureMatrix; + bool UseTextureMatrix; + + bool AutoSetZWrite; + + void Render2TexUnits(); + void Render4TexUnits(); + void Render8TexUnits(); + +public: + std::string name; + Material material; + MotionController controller; + + Matrix4x4 TransMat, RotMat, ScaleMat, GRotMat; + + Object(GraphicsContext *gc, byte DetailLevels = 1); + ~Object(); + + TriMesh *GetTriMesh(); + + void ResetTransform(); + void ResetTranslation(); + void ResetRotation(); + void ResetGlobalRotation(); + void ResetScaling(); + + void Translate(float tx, float ty, float tz); + void Rotate(float rx, float ry, float rz); + void Rotate(const Vector3 &axis, float angle); + void Rotate(const Matrix4x4 &rot); + void GlobalRotate(float rx, float ry, float rz); + void GlobalRotate(const Vector3 &axis, float angle); + void GlobalRotate(const Matrix4x4 &rot); + void Scale(float sx, float sy, float sz); + + void SetTranslation(float tx, float ty, float tz); + void SetRotation(float rx, float ry, float rz); + void SetRotation(const Vector3 &axis, float angle); + void SetRotation(const Matrix4x4 &rot); + void SetGlobalRotation(float rx, float ry, float rz); + void SetGlobalRotation(const Vector3 &axis, float angle); + void SetGlobalRotation(const Matrix4x4 &rot); + void SetScaling(float sx, float sy, float sz); + + const Matrix4x4 GetWorldTransform() const; + + void SetTextureMatrix(Matrix4x4 mat); + Matrix4x4 GetTextureMatrix() const; + + // set render parameters + void SetVertexProgram(dword VertexProgram); + void SetPixelProgram(dword PixelProgram); + void SetShadingMode(ShadeMode smode); + void SetWriteZBuffer(bool enable); + void SetBlendFunc(BlendingFactor src, BlendingFactor dest); + void GetBlendFunc(BlendingFactor *src, BlendingFactor *dest); + + // about shadows + void CalculateShadows(const Light **lights, int LightCount); + TriMesh *GetShadowVolume(int light); + void SetShadowCasting(bool enable); + bool GetShadowCasting() const; + + void SetRenderStates(); + void Render(); + void RenderBare(); + + // generate geometry + void CreatePlane(float size, dword subdivisions); + void CreateCube(float size); +}; + + +#endif // _OBJECTS_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/particles.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/particles.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,325 @@ +#include "particles.h" +#include "3deng.h" +#include + +////////////////////////////////////////////////////// +// --==( Particle class implementation )==-- // +////////////////////////////////////////////////////// +using namespace std; + +Particle::Particle(int life) { + pos = Vector3(0, 0, 0); + vel = Vector3(0, 0, 0); + this->life = life; +} + +Particle::Particle(const Vector3 &pos, int life) { + this->pos = pos; + vel = Vector3(0, 0, 0); + this->life = life; +} + +Particle::Particle(const Vector3 &pos, const Vector3 &vel, int life) { + this->pos = pos; + this->vel = vel; + this->life = life; +} + +void Particle::Update(const Vector3 &forces, float friction) { + if(!life) return; + vel *= 1.0f - friction; + pos += vel + forces; + life--; +} + +/////////////////////////////////////////////////////// +// --==( Particle System implementation )==-- // +/////////////////////////////////////////////////////// + +ParticleSystem::ParticleSystem(GraphicsContext *gc) { + this->gc = gc; + pos = prevpos = Vector3(0, 0, 0); + size = 1.0f; + friction = 0.0f; + SpawnRate = 5; + life = 100; + EmmiterAffectsParticleTrajectory = false; + varray = 0; + tarray = 0; + texture = 0; + obj = 0; + + SetShootDirection(Vector3(0, 0, 0)); + SetMaxDispersionAngle(0.01f); + SetInitialColor(1, 1, 1); + SetDeathColor(0, 0, 0); + + // initialize the shape of the particles + pquad[0] = Vertex(Vector3(-0.5f, 0.5f, 0), 0, 0, 0xffffffff); + pquad[1] = Vertex(Vector3(0.5f, 0.5f, 1), 1, 0, 0xffffffff); + pquad[2] = Vertex(Vector3(0.5f, -0.5f, 1), 1, 1, 0xffffffff); + pquad[3] = Vertex(Vector3(-0.5f, -0.5f, 0), 0, 1, 0xffffffff); + + ptris[0] = Triangle(0, 1, 2); + ptris[1] = Triangle(0, 2, 3); + + for(int i=0; i<4; i++) { + pquad[i].normal = Vector3(0, 0, -1); + } + + SetBlendingMode(BLEND_ONE, BLEND_ONE); + SpawnDiffDispersion = 0.0f; + + FixedUpdateRate = true; + UpdateRate = 30.0f; + LastUpdate = -(1.0f / UpdateRate); + + SpawnRateChange = 0; +} + +ParticleSystem::~ParticleSystem() { +} + +void ParticleSystem::SetGraphicsContext(GraphicsContext *gc) { + this->gc = gc; +} + +void ParticleSystem::SetParticleSize(float psize) { + size = psize; +} + +void ParticleSystem::SetParticleLife(int life) { + this->life = life; +} + +void ParticleSystem::SetFriction(float friction) { + this->friction = friction; +} + +void ParticleSystem::SetSpawnRate(float spawnrate) { + SpawnRate = (int)spawnrate; +} + +void ParticleSystem::SetSpawnRadius(float radius) { + SpawnRadius = radius; +} + +void ParticleSystem::SetTexture(Texture *texture) { + this->texture = texture; +} + +void ParticleSystem::SetObject(Object *obj) { + this->obj = obj; +} + +void ParticleSystem::SetPosition(const Vector3 &pos) { + this->pos = pos; +} + +void ParticleSystem::SetShootDirection(const Vector3 &dir) { + ShootDirection = dir; +} + +void ParticleSystem::SetGravitualForce(float grav) { + GravForce = grav; +} + +void ParticleSystem::SetEmmiterDependence(bool dep) { + EmmiterAffectsParticleTrajectory = dep; +} + +void ParticleSystem::SetMaxDispersionAngle(float maxdisp) { + DispRads = maxdisp; +} + +void ParticleSystem::SetInitialColor(float r, float g, float b) { + StartRed = r; + StartGreen = g; + StartBlue = b; +} + +void ParticleSystem::SetDeathColor(float r, float g, float b) { + EndRed = r; + EndGreen = g; + EndBlue = b; +} + +void ParticleSystem::SetBlendingMode(BlendingFactor src, BlendingFactor dest) { + SourceBlend = src; + DestBlend = dest; +} + +void ParticleSystem::SetSpawningDifferenceDispersion(float val) { + SpawnDiffDispersion = val; +} + +void ParticleSystem::SetSpawnRateChange(int change) { + SpawnRateChange = change; +} + +// transformation stuff +void ParticleSystem::Translate(float x, float y, float z) { + Translation.Translate(x, y, z); +} + +void ParticleSystem::Rotate(float x, float y, float z) { + OrbitRot.Rotate(x, y, z); +} + +void ParticleSystem::Rotate(const Vector3 &axis, float angle) { + OrbitRot.Rotate(axis, angle); +} + +void ParticleSystem::ResetRotation() { + OrbitRot.ResetIdentity(); +} + +void ParticleSystem::ResetTranslation() { + Translation.ResetIdentity(); +} + +int ParticleSystem::CountParticles() { + ParticleCount = (int)particles.size(); + TriCount = ParticleCount << 1; + VertexCount = ParticleCount << 2; + IndexCount = TriCount * 3; + + return ParticleCount; +} + +void ParticleSystem::Update(float t) { + + if(FixedUpdateRate && t-LastUpdate < 1.0f/UpdateRate) return; + LastUpdate = t; + + // remove all particles that are dead + list::iterator iter = particles.begin(); + while(iter != particles.end()) { + if(!iter->life) { + iter = particles.erase(iter); + // if we erase the iterator points to the next so no need to advance explicitly + } else { + iter++; + } + } + + + // spawn the new particles according to spawn rate + int LeftToSpawn = SpawnRate; + Vector3 ShootDir = ShootDirection; + Matrix4x4 dispxform; + + Vector3 forces = Vector3(0.0f, -GravForce, 0.0f); + + // find the velocity of the system by differenciating between the + // last and the current position (time interval is considered constant) + Vector3 velocity = (pos - prevpos) * 0.1f; + + // adjust the shoot vector to take under consideration the velocity of the system + if(EmmiterAffectsParticleTrajectory) ShootDir += velocity; + + + while(LeftToSpawn--) { + Vector3 dir = ShootDir; + dispxform.Rotate(frand(DispRads) - DispRads/2.0f, frand(DispRads) - DispRads/2.0f, frand(DispRads) - DispRads/2.0f); + dir.Transform(dispxform); + + Vector3 SpawnOffset(frand(SpawnRadius) - SpawnRadius / 2.0f, frand(SpawnRadius) - SpawnRadius / 2.0f, frand(SpawnRadius) - SpawnRadius / 2.0f); + Vector3 SpawnDisp(0.0f, 0.0f, 0.0f); + if(SpawnDiffDispersion > 0.0f) { + SpawnDisp = Vector3(frand(1.0f) - 0.5f, frand(1.0f) - 0.5f, frand(1.0f) - 0.5f); + SpawnDisp.Normalize(); + SpawnDisp *= SpawnDiffDispersion; + } + particles.insert(particles.end(), Particle(pos + SpawnOffset, dir + SpawnDisp, life)); + } + + + //if(EmmiterAffectsParticleTrajectory) forces += velocity; + + iter = particles.begin(); + while(iter != particles.end()) { + iter->Update(forces, friction); + iter++; + } + + SpawnRate += SpawnRateChange; + if(SpawnRate < 0) SpawnRate = 0; +} + +inline dword FtoDW(float f) { return *((dword*)&f); } + +void ParticleSystem::Render() { + + CountParticles(); + if(!ParticleCount) return; + + list::iterator iter = particles.begin(); + + if(!obj) { + + // ----- Render Billboarded Textured Quads ----- + + VertexBuffer *vb; + gc->CreateVertexBuffer(ParticleCount, UsageStatic, &vb); + Vertex *vbptr; + Lock(vb, &vbptr); + + for(int i=0; ipos; + + float t = 1.0f - (float)iter->life / (float)life; + float red = StartRed + (EndRed - StartRed) * t; + float green = StartGreen + (EndGreen - StartGreen) * t; + float blue = StartBlue + (EndBlue - StartBlue) * t; + + vbptr[i].color = Color(red, green, blue).GetPacked32(); + + iter++; + } + Unlock(vb); + + gc->SetWorldMatrix(Matrix4x4()); + gc->SetLighting(false); + gc->SetZWrite(false); + gc->SetTexture(0, texture); + gc->SetTextureStageColor(0, TexBlendModulate, TexArgCurrent, TexArgTexture); + gc->SetAlphaBlending(true); + gc->SetBlendFunc(SourceBlend, DestBlend); + gc->SetVertexProgram(FixedFunction); + + gc->SetColorVertex(true); + + gc->D3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, true); + gc->D3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, true); + gc->D3DDevice->SetRenderState(D3DRS_POINTSIZE, FtoDW(size)); + gc->D3DDevice->SetRenderState(D3DRS_POINTSCALE_A, FtoDW(0.0f)); + gc->D3DDevice->SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f)); + gc->D3DDevice->SetRenderState(D3DRS_POINTSCALE_C, FtoDW(1.0f)); + + gc->D3DDevice->SetStreamSource(0, vb, sizeof(Vertex)); + gc->D3DDevice->DrawPrimitive(D3DPT_POINTLIST, 0, ParticleCount); + + gc->D3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, false); + gc->D3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, false); + + gc->SetColorVertex(false); + + gc->SetLighting(true); + gc->SetZWrite(true); + gc->SetAlphaBlending(false); + + vb->Release(); + } else { + + // ---- Render Mesh Objects ---- + for(int i=0; iResetTranslation(); + obj->Translate(iter->pos.x, iter->pos.y, iter->pos.z); + obj->Render(); + iter++; + } + } + + +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/particles.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/particles.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,99 @@ +#ifndef _PARTICLES_H_ +#define _PARTICLES_H_ + +#include +#include "n3dmath.h" +#include "3dgeom.h" +#include "objects.h" + +enum BlendingFactor; + +class Particle { +public: + Vector3 pos; + Vector3 vel; + unsigned int life; + + Particle(int life=0); + Particle(const Vector3 &pos, int life=0); + Particle(const Vector3 &pos, const Vector3 &vel, int life=0); + + void Update(const Vector3 &forces, float friction=0); +}; + +class ParticleSystem { +private: + GraphicsContext *gc; + bool FixedUpdateRate; + float UpdateRate; + float LastUpdate; + + BlendingFactor SourceBlend, DestBlend; + + Vector3 pos, prevpos; // position of the emmiter (world space) + Vector3 ShootDirection; // an initial velocity vector for the particles + std::list particles; // a list of particles + Vertex pquad[4]; // the basic particle quad vertices + Triangle ptris[2]; // the basic particle quad triangles + float size; // size of the particles + float friction; // friction impeding particle movement + int SpawnRate; // rate of particle generation + float SpawnRadius; // spawning radius around the emmiter + float GravForce; // Gravitual force + float DispRads; + int life; // particle life + bool EmmiterAffectsParticleTrajectory; // ehm ... yeah + float SpawnDiffDispersion; + int SpawnRateChange; // if 0 then spawn rate constant + + float StartRed, StartGreen, StartBlue; + float EndRed, EndGreen, EndBlue; + + int VertsToRender, TrianglesToRender; + int vbsize, ibsize, maxprimitives; + Texture *texture; // the particles' texture + Object *obj; // the particles' mesh object (if present don't render quads) + Vertex *varray; // secondary vertex array (ease of development) + Triangle *tarray; // the triangles + + int VertexCount, IndexCount, TriCount, ParticleCount; + +public: + Matrix4x4 Translation, OrbitRot; + + ParticleSystem(GraphicsContext *gc); + ~ParticleSystem(); + + void SetGraphicsContext(GraphicsContext *gc); + void SetParticleSize(float psize); + void SetParticleLife(int life); + void SetFriction(float friction); + void SetSpawnRate(float spawnrate); + void SetSpawnRadius(float radius); + void SetTexture(Texture *texture); + void SetObject(Object *obj); + void SetPosition(const Vector3 &pos); + void SetShootDirection(const Vector3 &dir); + void SetGravitualForce(float grav); + void SetEmmiterDependence(bool dep); + void SetMaxDispersionAngle(float maxdisp); + void SetInitialColor(float r, float g, float b); + void SetDeathColor(float r, float g, float b); + void SetBlendingMode(BlendingFactor src, BlendingFactor dest); + void SetSpawningDifferenceDispersion(float val); + void SetSpawnRateChange(int change); + + void Translate(float x, float y, float z); + void Rotate(float x, float y, float z); + void Rotate(const Vector3 &axis, float angle); + void ResetTranslation(); + void ResetRotation(); + + int CountParticles(); + + void Update(float t = 0.0f); + void Render(); +}; + + +#endif // _PARTICLES_H_ diff -r 000000000000 -r 1cffe3409164 src/3deng/sceneloader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/sceneloader.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,923 @@ +//#include +#include +#include +#include +#include "sceneloader.h" +#include "3dschunks.h" +#include "typedefs.h" + +using std::ifstream; +using std::string; + +namespace SceneLoader { + GraphicsContext *gc; + dword ReadCounter; + Material *mat; + dword MatCount; + + bool eof = false; + + string datapath = ""; + + string SceneFileName; + string ObjectName; + + bool SaveNormalFile = false; +} + +using namespace SceneLoader; + +struct ChunkHeader { + ChunkID id; + dword size; +}; + +struct Percent { + int IntPercent; + float FloatPercent; + + Percent(int p = 0) {IntPercent = p; FloatPercent = (float)p / 100.0f; } + Percent(float p) {FloatPercent = p; IntPercent = (int)(p * 100.0f); } +}; + +struct TexMap { + string filename; + TextureType type; + float intensity; + float rotation; + Vector2 offset; + Vector2 scale; +}; + +const dword HeaderSize = 6; + +enum {OBJ_MESH, OBJ_PTLIGHT, OBJ_SPLIGHT, OBJ_CAMERA, OBJ_CURVE}; + +// local function prototypes +byte ReadByte(HANDLE file); +word ReadWord(HANDLE file); +dword ReadDword(HANDLE file); +float ReadFloat(HANDLE file); +Vector3 ReadVector(HANDLE file, bool FlipYZ = true); +string ReadString(HANDLE file); +Color ReadColor(HANDLE file); +Percent ReadPercent(HANDLE file); +ChunkHeader ReadChunkHeader(HANDLE file); +void SkipChunk(HANDLE file, const ChunkHeader &chunk); +void SkipBytes(HANDLE file, dword bytes); + +int ReadObject(HANDLE file, const ChunkHeader &ch, void **obj); +int ReadLight(HANDLE file, const ChunkHeader &ch, Light **lt); +Material ReadMaterial(HANDLE file, const ChunkHeader &ch); +TexMap ReadTextureMap(HANDLE file, const ChunkHeader &ch); + +Material *FindMaterial(string name); + +bool LoadNormalsFromFile(const char *fname, Scene *scene); +void SaveNormalsToFile(const char *fname, Scene *scene); + + +void SceneLoader::SetGraphicsContext(GraphicsContext *gfx) { + gc = gfx; +} + + +void SceneLoader::SetDataPath(const char *path) { + datapath = path; +} + +void SceneLoader::SetNormalFileSaving(bool enable) { + SaveNormalFile = enable; +} + + + +//////////////////////////////////////// +// --==( function LoadScene )==-- // +// ---------------------------------- // +// Creates a Scene instance and loads // +// the data from specified file // +//////////////////////////////////////// + +bool SceneLoader::LoadScene(const char *fname, Scene **scene) { + if(!gc) return false; + + if(!LoadMaterials(fname, &mat)) return false; + + //ifstream file(fname); + //if(!file.is_open()) return false; + HANDLE file = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); + assert(file != NULL); + eof = false; + + SceneFileName = string(fname); + + ChunkHeader chunk; + Scene *scn = new Scene(gc); // new scene instance + + chunk = ReadChunkHeader(file); + if(chunk.id != Chunk_3DSMain) { + CloseHandle(file); + return false; + } + + //while(!file.eof()) { + while(!eof) { + + chunk = ReadChunkHeader(file); + + void *objptr; + int type; + + switch(chunk.id) { + case Chunk_Main_3DEditor: + break; // dont skip + + case Chunk_Edit_AmbientColor: + scn->SetAmbientLight(ReadColor(file)); + break; + + case Chunk_Edit_Fog: + // **TODO** find out chunk structure + break; + + case Chunk_Edit_Object: + type = ReadObject(file, chunk, &objptr); + switch(type) { + case OBJ_MESH: + { + Object *object = (Object*)objptr; + scn->AddObject(object); + } + break; + + case OBJ_CAMERA: + { + Camera *cam = (Camera*)objptr; + scn->AddCamera(cam); + } + break; + + case OBJ_PTLIGHT: + { + PointLight *lt = (PointLight*)objptr; + scn->AddLight(lt); + } + break; + + case OBJ_SPLIGHT: + { + SpotLight *lt = (SpotLight*)objptr; + scn->AddLight(lt); + } + break; + + case OBJ_CURVE: + { + CatmullRomSpline *spline = (CatmullRomSpline*)objptr; + scn->AddCurve(spline); + } + break; + } + + break; + + default: + SkipChunk(file, chunk); + } + } + + CloseHandle(file); + + + // check if there is a normals file in the same dir and load them, or else calculate them + if(!LoadNormalsFromFile((SceneFileName + string(".normals")).c_str(), scn)) { + std::list::iterator objiter = scn->GetObjectsList()->begin(); + while(objiter != scn->GetObjectsList()->end()) { + (*objiter++)->GetTriMesh()->CalculateNormals(); + } + if(SaveNormalFile) SaveNormalsToFile((SceneFileName + string(".normals")).c_str(), scn); + } + + *scene = scn; + return true; +} + + + +bool SceneLoader::LoadObject(const char *fname, const char *ObjectName, Object **obj) { + if(!gc) return false; + + if(!LoadMaterials(fname, &mat)) return false; + + //ifstream file(fname); + //if(!file.is_open()) return false; + HANDLE file = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); + assert(file != NULL); + eof = false; + + ChunkHeader chunk = ReadChunkHeader(file); + if(chunk.id != Chunk_3DSMain) { + CloseHandle(file); + return false; + } + + while(!eof) { + + chunk = ReadChunkHeader(file); + + void *objptr; + int type; + + switch(chunk.id) { + case Chunk_Main_3DEditor: + break; // dont skip + + case Chunk_Edit_Object: + type = ReadObject(file, chunk, &objptr); + if(type == OBJ_MESH) { + Object *object = (Object*)objptr; + if(!strcmp(object->name.c_str(), ObjectName)) { + object->GetTriMesh()->CalculateNormals(); + *obj = object; + CloseHandle(file); + return true; + } + } + break; + + default: + SkipChunk(file, chunk); + } + } + + CloseHandle(file); + return false; +} + + + +bool FindChunk(HANDLE file, word ChunkID) { + + ChunkHeader chunk = ReadChunkHeader(file); + + while(chunk.id != ChunkID) { + SkipChunk(file, chunk); + chunk = ReadChunkHeader(file); + } + + return chunk.id == ChunkID; +} + + + +bool SceneLoader::LoadMaterials(const char *fname, Material **materials) { + if(!materials) return false; + + //ifstream file(fname); + //if(!file.is_open()) return false; + HANDLE file = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); + assert(file != NULL); + eof = false; + + ChunkHeader chunk; + + chunk = ReadChunkHeader(file); + if(chunk.id != Chunk_3DSMain) { + CloseHandle(file); + return false; + } + + if(!FindChunk(file, Chunk_Main_3DEditor)) { + CloseHandle(file); + return false; + } + + std::vector mats; + + while(!eof) { + + chunk = ReadChunkHeader(file); + + if(chunk.id == Chunk_Edit_Material) { + Material mat = ReadMaterial(file, chunk); + mats.push_back(mat); + } else { + SkipChunk(file, chunk); + } + } + + MatCount = (dword)mats.size(); + + if(*materials) delete [] *materials; + Material *m = new Material[MatCount]; + + for(dword i=0; i 0.0f) mat.SpecularEnable = true; + break; + + case Chunk_Mat_SpecularIntensity: + p = ReadPercent(file); + mat.Specular.r *= p.FloatPercent; + mat.Specular.g *= p.FloatPercent; + mat.Specular.b *= p.FloatPercent; + break; + + case Chunk_Mat_Transparency: + p = ReadPercent(file); + mat.Alpha = 1.0f - p.FloatPercent; + break; + + case Chunk_Mat_SelfIllumination: + p = ReadPercent(file); + mat.Emissive = Color(p.FloatPercent); + break; + + case Chunk_Mat_TextureMap: + case Chunk_Mat_TextureMap2: + case Chunk_Mat_OpacityMap: + case Chunk_Mat_SelfIlluminationMap: + map = ReadTextureMap(file, chunk); + mat.SetTexture(gc->texman->LoadTexture((datapath + map.filename).c_str()), map.type); + break; + + case Chunk_Mat_ReflectionMap: + map = ReadTextureMap(file, chunk); + mat.SetTexture(gc->texman->LoadTexture((datapath + map.filename).c_str()), map.type); + mat.EnvBlend = map.intensity; + break; + + case Chunk_Mat_BumpMap: + map = ReadTextureMap(file, chunk); + mat.SetTexture(gc->texman->LoadTexture((datapath + map.filename).c_str()), map.type); + mat.BumpIntensity = map.intensity; + break; + + default: + SkipChunk(file, chunk); + } + } + + return mat; +} + + + + + +//////////////////////////////////////////////////// +byte ReadByte(HANDLE file) { + byte val; + dword numread; + ReadFile(file, &val, sizeof(byte), &numread, NULL); + if(numread < sizeof(byte)) eof = true; + ReadCounter++; + return val; +} + +word ReadWord(HANDLE file) { + word val; + dword numread; + ReadFile(file, &val, sizeof(word), &numread, NULL); + if(numread < sizeof(word)) eof = true; + ReadCounter += sizeof(word); + return val; +} + +dword ReadDword(HANDLE file) { + dword val; + dword numread; + ReadFile(file, &val, sizeof(dword), &numread, NULL); + if(numread < sizeof(dword)) eof = true; + ReadCounter += sizeof(dword); + return val; +} + +float ReadFloat(HANDLE file) { + float val; + dword numread; + ReadFile(file, &val, sizeof(float), &numread, NULL); + if(numread < sizeof(float)) eof = true; + ReadCounter += sizeof(float); + return val; +} +/* +byte ReadByte(HANDLE file) { + byte val; + file.read((char*)&val, 1); + ReadCounter++; + return val; +} + +word ReadWord(HANDLE file) { + word val; + file.read((char*)&val, sizeof(word)); + ReadCounter += sizeof(word); + return val; +} + +dword ReadDword(HANDLE file) { + dword val; + file.read((char*)&val, sizeof(dword)); + ReadCounter += sizeof(dword); + return val; +} + +float ReadFloat(HANDLE file) { + float val; + file.read((char*)&val, sizeof(float)); + ReadCounter += sizeof(float); + return val; +} +*/ +Vector3 ReadVector(HANDLE file, bool FlipYZ) { + Vector3 vector; + vector.x = ReadFloat(file); + if(!FlipYZ) vector.y = ReadFloat(file); + vector.z = ReadFloat(file); + if(FlipYZ) vector.y = ReadFloat(file); + return vector; +} + +string ReadString(HANDLE file) { + string str; + char c; + while(c = (char)ReadByte(file)) { + str.push_back(c); + } + str.push_back('\0'); + ReadCounter++; + + return str; +} +/* +string ReadString(HANDLE file) { + string str; + char c; + while(c = file.get()) { + str.push_back(c); + ReadCounter++; + } + str.push_back('\0'); + ReadCounter++; + + return str; +} +*/ + +Color ReadColor(HANDLE file) { + ChunkHeader chunk = ReadChunkHeader(file); + if(chunk.id < 0x0010 || chunk.id > 0x0013) return Color(-1.0f, -1.0f, -1.0f); + + Color color; + + if(chunk.id == Chunk_Color_Byte3 || chunk.id == Chunk_Color_GammaByte3) { + byte r = ReadByte(file); + byte g = ReadByte(file); + byte b = ReadByte(file); + color = Color(r, g, b); + } else { + color.r = ReadFloat(file); + color.g = ReadFloat(file); + color.b = ReadFloat(file); + } + + return color; +} + +Percent ReadPercent(HANDLE file) { + ChunkHeader chunk = ReadChunkHeader(file); + Percent p; + if(chunk.id != Chunk_PercentInt && chunk.id != Chunk_PercentFloat) return p; + + if(chunk.id == Chunk_PercentInt) { + p = Percent(ReadWord(file)); + } else { + p = Percent(ReadFloat(file)); + } + + return p; +} + + +ChunkHeader ReadChunkHeader(HANDLE file) { + ChunkHeader chunk; + chunk.id = (ChunkID)ReadWord(file); + chunk.size = ReadDword(file); + return chunk; +} + +void SkipChunk(HANDLE file, const ChunkHeader &chunk) { + //file.ignore(chunk.size - HeaderSize); + SetFilePointer(file, chunk.size - HeaderSize, 0, FILE_CURRENT); + ReadCounter += chunk.size - HeaderSize; +} + +void SkipBytes(HANDLE file, dword bytes) { + SetFilePointer(file, bytes, 0, FILE_CURRENT); + ReadCounter += bytes; +} + +Material *FindMaterial(string name) { + dword i=0; + while(i < MatCount) { + if(mat[i].name == name) return &mat[i]; + i++; + } + + return 0; +} + +///////////////////// Read Object Function ////////////////////// +int ReadObject(HANDLE file, const ChunkHeader &ch, void **obj) { + if(!obj || !gc) return -1; + + ReadCounter = HeaderSize; // reset the global read counter + + string name = ReadString(file); + + ChunkHeader chunk; + chunk = ReadChunkHeader(file); + if(chunk.id == Chunk_Obj_TriMesh) { + // object is a trimesh... load it + Vertex *varray; + Triangle *tarray; + dword VertexCount=0, TriCount=0; + Material mat; + Base base; + Vector3 translation; + + bool curve = true; + + dword ObjChunkSize = ch.size; + + while(ReadCounter < ObjChunkSize) { // make sure we only read subchunks of this object chunk + //assert(!file.eof()); + assert(!eof); + chunk = ReadChunkHeader(file); + + switch(chunk.id) { + case Chunk_TriMesh_VertexList: + VertexCount = (dword)ReadWord(file); + varray = new Vertex[VertexCount]; + + for(dword i=0; iname = name; + for(dword i=0; iAddControlPoint(varray[i].pos); + } + + *obj = spline; + return OBJ_CURVE; + } else { + + base.i.Normalize(); + base.j.Normalize(); + base.k.Normalize(); + Matrix3x3 RotXForm = base.CreateRotationMatrix(); + RotXForm.OrthoNormalize(); + + for(dword i=0; iname = name; + object->GetTriMesh()->SetData(varray, tarray, VertexCount, TriCount); + object->material = mat; + object->SetRotation(RotXForm); + object->SetTranslation(translation.x, translation.y, translation.z); + *obj = object; + + return OBJ_MESH; + } + } else { + + if(chunk.id == Chunk_Obj_Light) { + + dword ObjChunkSize = ch.size; + + Vector3 pos = ReadVector(file); + Color color = ReadColor(file); + + Vector3 SpotTarget; + float InnerCone, OuterCone; + bool spot = false; + bool att = false; + bool CastShadows = false; + float AttEnd = 10000.0f; + float Intensity = 1.0f; + + while(ReadCounter < ObjChunkSize) { + + chunk = ReadChunkHeader(file); + + switch(chunk.id) { + case Chunk_Light_SpotLight: + spot = true; + SpotTarget = ReadVector(file); + InnerCone = ReadFloat(file) / 180.0f; + OuterCone = ReadFloat(file) / 180.0f; + break; + + case Chunk_Light_Attenuation: + att = true; + break; + + case Chunk_Light_AttenuationEnd: + AttEnd = ReadFloat(file); + break; + + case Chunk_Light_Intensity: + Intensity = ReadFloat(file); + break; + + case Chunk_Spot_CastShadows: + CastShadows = true; + break; + + default: + SkipChunk(file, chunk); + } + } + + Light *light; + if(spot) { + light = new TargetSpotLight(pos, SpotTarget, InnerCone, OuterCone); + } else { + light = new PointLight(pos); + } + light->SetColor(color); + light->SetShadowCasting(CastShadows); + light->SetIntensity(Intensity); + light->name = name; + + *obj = light; + return spot ? OBJ_SPLIGHT : OBJ_PTLIGHT; + } + + if(chunk.id == Chunk_Obj_Camera) { + Camera *cam = new Camera; + Vector3 pos = ReadVector(file); + Vector3 targ = ReadVector(file); + float roll = ReadFloat(file); + float FOV = ReadFloat(file); + + Vector3 up = VECTOR3_J; + Vector3 view = targ - pos; + up.Rotate(view.Normalized(), roll); + + cam->SetCamera(pos, targ, up); + cam->name = name; + cam->SetFOV(DEGTORAD(FOV) / 1.33333f); + + *obj = cam; + return OBJ_CAMERA; + } + } + + return -1; // should have already left by now, if not something is wrong +} + + +//////////////////////////////////////////////////////////////////////////////// +// functions to save/load normals from file + +void WriteByte(HANDLE file, byte val) { + dword junk; + WriteFile(file, &val, sizeof(byte), &junk, 0); +} + +void WriteDword(HANDLE file, dword val) { + dword junk; + WriteFile(file, &val, sizeof(dword), &junk, 0); + assert(junk == sizeof(dword)); +} + +void WriteFloat(HANDLE file, float val) { + dword junk; + WriteFile(file, &val, sizeof(float), &junk, 0); + assert(junk == sizeof(float)); +} + +void WriteString(HANDLE file, string str) { + dword junk; + for(dword i=0; i<(dword)str.size(); i++) { + WriteFile(file, &str[i], sizeof(char), &junk, 0); + } +} + + +void SaveNormalsToFile(const char *fname, Scene *scene) { + + HANDLE file = CreateFile(fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + assert(file); + + WriteDword(file, (dword)scene->GetObjectsList()->size()); + + std::list::iterator objiter = scene->GetObjectsList()->begin(); + while(objiter != scene->GetObjectsList()->end()) { + WriteString(file, (*objiter)->name); + dword VertexCount = (*objiter)->GetTriMesh()->GetVertexCount(); + WriteDword(file, VertexCount); + + const Vertex *varray = (*objiter)->GetTriMesh()->GetVertexArray(); + for(dword i=0; iGetObjectsList()->size()) { // detect changes + CloseHandle(file); + return false; + } + + while(SceneLoader::ReadCounter < FileSize) { + string name = ReadString(file); + dword VertexCount = ReadDword(file); + + Object *obj = scene->GetObject(name.c_str()); + if(!obj) { + CloseHandle(file); + return false; + } + + if(VertexCount != obj->GetTriMesh()->GetVertexCount()) { // again detect changes + CloseHandle(file); + return false; + } + + Vertex *varray = obj->GetTriMesh()->GetModVertexArray(); + for(dword i=0; i +unsigned int Hash(const KeyType &key, unsigned long size) { + string str = (string)key; + return ((unsigned int)str[0] + (unsigned int)str[1] + (unsigned int)str[2]) % size; +} + +TextureManager::TextureManager(GraphicsContext *gc) { + this->gc = gc; + notfilecount = 0; + + textures.SetHashFunction(Hash); + + CreateStockTextures(); +} + +TextureManager::~TextureManager() {} + +#define STOCKSIZE 256 +#include + +void TextureManager::CreateStockTextures() { + Surface *surf; + + // ----- 1/d^2 blob texture ----- + Texture *tmp = CreateTexture(STOCKSIZE, STOCKSIZE, 0, true, true); + tmp->GetSurfaceLevel(0, &surf); + + dword *ptr, offs; + D3DLOCKED_RECT d3dlock; + assert(surf->LockRect(&d3dlock, 0, 0) == D3D_OK); + ptr = (dword*)d3dlock.pBits; + offs = (d3dlock.Pitch >> 2) - STOCKSIZE; + + Vector2 Center((float)(STOCKSIZE>>1), (float)(STOCKSIZE>>1)); + + for(int y=0; yUnlockRect(); + + Texture *Blob = CreateTexture(STOCKSIZE, STOCKSIZE, 0, true); + gc->D3DDevice->UpdateTexture(tmp, Blob); + + UpdateMipmapChain(Blob); + + AddTexture(Blob, "STOCKTEX_BLOB"); + tmp->Release(); + + // ----- chessboard texture ----- + + tmp = CreateTexture(STOCKSIZE, STOCKSIZE, 0, true, true); + tmp->GetSurfaceLevel(0, &surf); + + assert(surf->LockRect(&d3dlock, 0, 0) == D3D_OK); + ptr = (dword*)d3dlock.pBits; + offs = (d3dlock.Pitch >> 2) - STOCKSIZE; + + for(int y=0; y>1); + int dy = y - (STOCKSIZE>>1); + if((dx > 0 && dy > 0) || (dx < 0 && dy < 0)) { + *ptr++ = 0xffffffff; + } else { + *ptr++ = 0xff000000; + } + } + ptr += offs; + } + + surf->UnlockRect(); + + Texture *ChessBoard = CreateTexture(STOCKSIZE, STOCKSIZE, 0, true); + gc->D3DDevice->UpdateTexture(tmp, ChessBoard); + + UpdateMipmapChain(ChessBoard); + + AddTexture(ChessBoard, "STOCKTEX_CHESSBOARD"); + tmp->Release(); + + // ----- grid texture ----- + + tmp = CreateTexture(STOCKSIZE, STOCKSIZE, 0, true, true); + tmp->GetSurfaceLevel(0, &surf); + + assert(surf->LockRect(&d3dlock, 0, 0) == D3D_OK); + ptr = (dword*)d3dlock.pBits; + offs = (d3dlock.Pitch >> 2) - STOCKSIZE; + + for(int y=0; yUnlockRect(); + + Texture *Grid = CreateTexture(STOCKSIZE, STOCKSIZE, 0, true); + gc->D3DDevice->UpdateTexture(tmp, Grid); + + UpdateMipmapChain(Grid); + + AddTexture(Grid, "STOCKTEX_GRID"); + tmp->Release(); + + + // ---------- biased linear falloff --------- + tmp = CreateTexture(STOCKSIZE, STOCKSIZE, 0, true, true); + tmp->GetSurfaceLevel(0, &surf); + + assert(surf->LockRect(&d3dlock, 0, 0) == D3D_OK); + ptr = (dword*)d3dlock.pBits; + offs = (d3dlock.Pitch >> 2) - STOCKSIZE; + + Center = Vector2((float)(STOCKSIZE>>1), (float)(STOCKSIZE>>1)); + + for(int y=0; yUnlockRect(); + + Texture *Blofm = CreateTexture(STOCKSIZE, STOCKSIZE, 0, true); + gc->D3DDevice->UpdateTexture(tmp, Blofm); + + UpdateMipmapChain(Blofm); + + AddTexture(Blofm, "STOCKTEX_BLOFM"); + tmp->Release(); +} + +void TextureManager::SetGraphicsContext(GraphicsContext *gc) { + this->gc = gc; +} + +Texture *TextureManager::LoadTexture(const char *fname) { + if(!gc || !fname) return 0; + + Texture *tex; + + Pair *p; + if(!(p = textures.Find(fname))) { + if(D3DXCreateTextureFromFile(gc->D3DDevice, fname, &tex) != D3D_OK) return 0; + textures.Insert(fname, tex); + } else { + tex = p->val; + } + + return tex; +} + +Texture *TextureManager::CreateTexture(dword x, dword y, dword usage, bool mipmaps, bool local) { + if(!gc) return 0; + Texture *tex; + D3DPOOL pool = local ? D3DPOOL_SYSTEMMEM : D3DPOOL_DEFAULT; + D3DFORMAT fmt = usage == UsageDepthStencil ? gc->ZFormat : D3DFMT_A8R8G8B8; + if(usage == UsageDepthStencil) pool = D3DPOOL_MANAGED; + if(gc->D3DDevice->CreateTexture(x, y, (int)(!mipmaps), usage, fmt, pool, &tex) != D3D_OK) return 0; + return tex; +} + +Texture *TextureManager::AddTexture(Texture *tex, const char *name) { + string fname = name ? name : "not_a_file_" + notfilecount; + textures.Insert(fname, tex); + return tex; +} + +Texture *TextureManager::AddTexture(const char *fname) { + return LoadTexture(fname); +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/3deng/textureman.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/3deng/textureman.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,39 @@ +#ifndef _TEXTUREMAN_H_ +#define _TEXTUREMAN_H_ + +#include +#include "hashtable.h" +#include "typedefs.h" +#include "d3d8.h" +#include "3dengtypes.h" + +class GraphicsContext; + +const dword UsageRenderTarget = D3DUSAGE_RENDERTARGET; +const dword UsageDepthStencil = D3DUSAGE_DEPTHSTENCIL; + +class TextureManager { +private: + GraphicsContext *gc; + HashTable textures; + int notfilecount; + + // private copy constructor and assignment op, to prohibit copying + TextureManager(const TextureManager &tm) {} + void operator =(const TextureManager &tm) {} + + void CreateStockTextures(); + +public: + TextureManager(GraphicsContext *gc = 0); + ~TextureManager(); + + void SetGraphicsContext(GraphicsContext *gc); + + Texture *LoadTexture(const char *fname); + Texture *CreateTexture(dword x, dword y, dword usage, bool mipmaps, bool local=false); + Texture *AddTexture(Texture *tex, const char *name=0); + Texture *AddTexture(const char *fname); +}; + +#endif // _TEXTUREMAN_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/beginpart.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/beginpart.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,135 @@ +#include "beginpart.h" + +BeginPart::BeginPart(GraphicsContext *gc) { + this->gc = gc; + + this->gc = gc; + + SceneLoader::SetNormalFileSaving(true); + SceneLoader::SetDataPath("data/textures/"); + SceneLoader::LoadScene("data/geometry/begin.3ds", &scene); + + light = new DirLight(Vector3(0.0f, 0.0f, 1.0f)); + light->SetIntensity(1.5f); + scene->AddLight(light); + + // get stuff + Logo1 = scene->GetObject("LogoT"); + scene->RemoveObject(Logo1); + + Logo2 = scene->GetObject("LogoB"); + scene->RemoveObject(Logo2); + + VolumeLogo = scene->GetObject("VolumeLogo"); + scene->RemoveObject(VolumeLogo); + + Latin1 = scene->GetObject("Latin1"); + Latin2 = scene->GetObject("Latin2"); + Lines[0] = scene->GetObject("Lines1"); + Lines[1] = scene->GetObject("Lines2"); + TheLabText[0] = scene->GetObject("LabText1"); + TheLabText[1] = scene->GetObject("LabText2"); + + scene->RemoveObject(scene->GetObject("Plane01")); + + gc->SetTextureTransformState(0, TexTransform2D); +} + +BeginPart::~BeginPart() { + delete scene; +} + +#define psin(x) (sinf(x) / 2.0f + 0.5f) +#define pcos(x) (cosf(x) / 2.0f + 0.5f) + +void BeginPart::MainLoop() { + dword msec = timer.GetMilliSec(); + float t = (float)msec / 1000.0f; + + const float StartCycle = 2.5f; + const float EndCycle = 5.0f; + const float StartFade = 9.0f; + + + Latin1->SetTextureMatrix(Matrix3x3(1,0,0, 0,1,0, 0,t/4,1)); + Latin2->SetTextureMatrix(Matrix3x3(1,0,0, 0,1,0, 0,t/2,1)); + Lines[0]->SetTextureMatrix(Matrix3x3(1,0,0, 0,1,0, t*2.0f,0,1)); + Lines[1]->SetTextureMatrix(Matrix3x3(1,0,0, 0,1,0, t/2.0f,0,1)); + TheLabText[0]->SetTextureMatrix(Matrix3x3(1,0,0, 0,1,0, t,0,1)); + TheLabText[1]->SetTextureMatrix(Matrix3x3(1,0,0, 0,1,0, t/3,0,1)); + + gc->Clear(0); + gc->ClearZBufferStencil(1.0f, 0); + + gc->SetZBuffering(false); + + scene->Render(); + + gc->SetAlphaBlending(true); + gc->SetTextureStageColor(0, TexBlendModulate, TexArgCurrent, TexArgTexture); + gc->SetTextureStageAlpha(0, TexBlendModulate, TexArgCurrent, TexArgTexture); + gc->SetBlendFunc(BLEND_ONE, BLEND_ONE); + + Matrix3x3 TexMat; + + // render shit + Logo1->SetTranslation(0.0f, max(0.8f - t, 0) * 50.0f, 0.0f); + Logo2->SetTranslation(0.0f, -max(0.8f - t, 0) * 50.0f, 0.0f); + + if(t > StartCycle) { + Logo1->material.Diffuse.r += (t-StartCycle) * 0.005f; + Logo1->material.Diffuse.g -= (t-StartCycle) * 0.005f; + Logo1->material.Diffuse.b -= (t-StartCycle) * 0.005f; + if(Logo1->material.Diffuse.r > 0.5f) Logo1->material.Diffuse.r = 0.5f; + if(Logo1->material.Diffuse.g < 0.0f) Logo1->material.Diffuse.g = 0.0f; + if(Logo1->material.Diffuse.b < 0.0f) Logo1->material.Diffuse.b = 0.0f; + + Logo2->material.Diffuse.r += (t-StartCycle) * 0.005f; + Logo2->material.Diffuse.g -= (t-StartCycle) * 0.005f; + Logo2->material.Diffuse.b -= (t-StartCycle) * 0.005f; + if(Logo2->material.Diffuse.r > 0.5f) Logo2->material.Diffuse.r = 0.5f; + if(Logo2->material.Diffuse.g < 0.0f) Logo2->material.Diffuse.g = 0.0f; + if(Logo2->material.Diffuse.b < 0.0f) Logo2->material.Diffuse.b = 0.0f; + } + + gc->SetMaterial(Logo1->material); + gc->SetTexture(0, Logo1->material.Maps[TextureMap]); + + gc->SetWorldMatrix(Logo1->GetWorldTransform()); + Logo1->RenderBare(); + + gc->SetWorldMatrix(Logo2->GetWorldTransform()); + Logo2->RenderBare(); + + if(t > EndCycle) { + Color color(Logo1->material.Diffuse.r, Logo1->material.Diffuse.g, Logo1->material.Diffuse.b); + VolumeLogo->material.SetDiffuse(color); + gc->SetTexture(0, VolumeLogo->material.Maps[TextureMap]); + + float xoffs = sinf(t/2.0f) * 4.0f; + float yoffs = sinf(t) * 1.5f;//-(t - 2.0f*EndCycle); + for(int i=0; imaterial.Diffuse.r -= 0.08f; + VolumeLogo->material.Diffuse.g -= 0.08f; + VolumeLogo->material.Diffuse.b -= 0.08f; + + gc->SetWorldMatrix(VolumeLogo->GetWorldTransform() * mat * ScaleMat); + VolumeLogo->RenderBare(); + } + } + + Material OrigMat = VolumeLogo->material; + VolumeLogo->material = Material(0.0f, 0.0f, 0.0f, max((t - StartFade) / 2.0f, 0.0f)); + VolumeLogo->Render(); + VolumeLogo->material = OrigMat; + + gc->SetZBuffering(true); + gc->SetAlphaBlending(false); +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/beginpart.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/beginpart.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,23 @@ +#ifndef _BEGINPART_H_ +#define _BEGINPART_H_ + +#include "demosystem/demosys.h" + +class BeginPart : public Part { +private: + //Scene *scene; + + Object *Logo1, *Logo2, *Latin1, *Latin2, *Lines[2], *TheLabText[2], *VolumeLogo; + DirLight *light; + Camera *cam; + +public: + + BeginPart(GraphicsContext *gc); + ~BeginPart(); + + void MainLoop(); +}; + + +#endif // _BEGINPART_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/common/color.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/color.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,125 @@ +#include +#include "color.h" + +template +const T &clamp(const T &val, const T &low, const T &high) { + if(val > high) return high; + if(val < low) return low; + return val; +} + +Color::Color(float_t intensity) { + r = g = b = clamp(intensity, 0.0f, 1.0f); + a = 1.0f; +} + +Color::Color(float_t r, float_t g, float_t b, float_t a) { + this->r = clamp(r, 0.0f, 1.0f); + this->g = clamp(g, 0.0f, 1.0f); + this->b = clamp(b, 0.0f, 1.0f); + this->a = clamp(a, 0.0f, 1.0f); +} + +Color::Color(unsigned int r, unsigned int g, unsigned int b, unsigned int a) { + this->r = (float_t)clamp(r, 0, 255) / 255.0f; + this->g = (float_t)clamp(g, 0, 255) / 255.0f; + this->b = (float_t)clamp(b, 0, 255) / 255.0f; + this->a = (float_t)clamp(a, 0, 255) / 255.0f; +} + +Color::Color(int r, int g, int b, int a) { + this->r = (float_t)clamp(r, 0, 255) / 255.0f; + this->g = (float_t)clamp(g, 0, 255) / 255.0f; + this->b = (float_t)clamp(b, 0, 255) / 255.0f; + this->a = (float_t)clamp(a, 0, 255) / 255.0f; +} + +Color::Color(long pcol) { + a = (float_t)(((dword)pcol >> 24) & 0xff) / 255.0f; + r = (float_t)(((dword)pcol >> 16) & 0xff) / 255.0f; + g = (float_t)(((dword)pcol >> 8) & 0xff) / 255.0f; + b = (float_t)((dword)pcol & 0xff) / 255.0f; +} + +Color::Color(dword pcol) { + a = (float_t)((pcol >> 24) & 0xff) / 255.0f; + r = (float_t)((pcol >> 16) & 0xff) / 255.0f; + g = (float_t)((pcol >> 8) & 0xff) / 255.0f; + b = (float_t)(pcol & 0xff) / 255.0f; +} + +dword Color::GetPacked32() const { + return (((dword)(a * 255.0f) << 24) & 0xff000000) | + (((dword)(r * 255.0f) << 16) & 0x00ff0000) | + (((dword)(g * 255.0f) << 8) & 0x0000ff00) | + ((dword)(b * 255.0f) & 0x000000ff); +} + +word Color::GetPacked16() const { + return (word)(r * 32.0f) << 11 | (word)(g * 64.0f) << 5 | (word)(b * 32.0f); +} + +word Color::GetPacked15() const { + return (word)a << 15 | (word)(r * 32.0f) << 10 | (word)(g * 32.0f) << 5 | (word)(b * 32.0f); +} + +#ifndef HalfPi +const float_t HalfPi = 1.5707963268f; +#endif // HalfPi + +byte Color::GetNearest8(const byte **pal) const { + float_t Score[256]; + for(int i=0; i<256; i++) { + Color palcol = Color(pal[i][0], pal[i][1], pal[i][2]); + float_t NearR = (float_t)cos(fabs(r - palcol.r) * HalfPi); + float_t NearG = (float_t)cos(fabs(g - palcol.g) * HalfPi); + float_t NearB = (float_t)cos(fabs(b - palcol.b) * HalfPi); + Score[i] = NearR + NearG + NearB; + } + + int nearest = 0; + for(int i=0; i<256; i++) { + if(Score[i] > Score[nearest]) nearest = i; + } + return nearest; +} + +Color Color::operator +(const Color &col) const { + return Color(r + col.r, g + col.g, b + col.b, a + col.a); +} + +Color Color::operator -(const Color &col) const { + return Color(r - col.r, g - col.g, b - col.b, a - col.a); +} + +Color Color::operator *(const Color &col) const { + return Color(r * col.r, g * col.g, b * col.b, a * col.a); +} + +Color Color::operator *(float_t scalar) const { + return Color(r * scalar, g * scalar, b * scalar, a); +} + + +void Color::operator +=(const Color &col) { + *this = Color(r + col.r, g + col.g, b + col.b, a + col.a); +} + +void Color::operator -=(const Color &col) { + *this = Color(r - col.r, g - col.g, b - col.b, a - col.a); +} + +void Color::operator *=(const Color &col) { + *this = Color(r * col.r, g * col.g, b * col.b, a * col.a); +} + +void Color::operator *=(float_t scalar) { + *this = Color(r * scalar, g * scalar, b * scalar, a); +} + +Color BlendColors(const Color &c1, const Color &c2, float_t t) { + float_t r = c1.r + (c2.r - c1.r) * t; + float_t g = c1.g + (c2.g - c1.g) * t; + float_t b = c1.b + (c2.b - c1.b) * t; + return Color(r, g, b); +} diff -r 000000000000 -r 1cffe3409164 src/common/color.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/color.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,55 @@ +#ifndef _COLORS_H_ +#define _COLORS_H_ + +#include +#include "typedefs.h" + +#ifdef _MSC_VER +#ifdef DOUBLE_PRECISION_MATH +typedef double float_t; +#else +typedef float float_t; +#endif // DOUBLE_PRECISION_MATH +#endif // _MSC_VER + +#ifdef NUC3D_VER_DIRECT3D + +#include "d3d8.h" + +class Color : public D3DCOLORVALUE { +public: + +#else + +class Color { +public: + float_t r, g, b, a; + +#endif // NUC3D_VER_DIRECT3D + + Color(float_t intensity = 1.0f); + Color(float_t r, float_t g, float_t b, float_t a = 1.0f); + Color(unsigned int r, unsigned int g, unsigned int b, unsigned int a = 255); + Color(int r, int g, int b, int a = 255); + Color(dword pcol); + Color(long pcol); + + Color operator +(const Color &col) const; + Color operator -(const Color &col) const; + Color operator *(const Color &col) const; + Color operator *(float_t scalar) const; + + void operator +=(const Color &col); + void operator -=(const Color &col); + void operator *=(const Color &col); + void operator *=(float_t scalar); + + dword GetPacked32() const; + word GetPacked16() const; + word GetPacked15() const; + byte GetNearest8(const byte **pal) const; +}; + +Color BlendColors(const Color &c1, const Color &c2, float_t t); + +#endif // _COLORS_H_ diff -r 000000000000 -r 1cffe3409164 src/common/curves.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/curves.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,240 @@ +#include +#include "curves.h" + +Curve::Curve() { + ArcParametrize = false; + ease_curve = 0; + Samples = 0; + + SetEaseSampleCount(100); +} + +Curve::~Curve() { + delete [] Samples; + +} + +void Curve::SetArcParametrization(bool state) { + ArcParametrize = state; +} + +#define Param 0 +#define ArcLen 1 + +void Curve::SampleArcLengths() { + const int SamplesPerSegment = 30; + SampleCount = GetSegmentCount() * SamplesPerSegment; + + ArcParametrize = false; // to be able to interpolate with the original values + + Samples = new Vector2[SampleCount]; + Vector3 prevpos; + float step = 1.0f / (float)(SampleCount-1); + for(int i=0; i>1); + + if(array[middle][ArcLen] == key) return middle; + if(end == begin) return middle; + + if(key < array[middle][ArcLen]) return BinarySearch(array, key, begin, middle); + if(key > array[middle][ArcLen]) return BinarySearch(array, key, middle+1, end); + return -1; // just to make the compiler shut the fuck up +} + +float Curve::Parametrize(float t) { + if(!Samples) SampleArcLengths(); + + int samplepos = BinarySearch(Samples, t, 0, SampleCount); + float par = Samples[samplepos][Param]; + float len = Samples[samplepos][ArcLen]; + if((len - t) < XSmallNumber) return par; + + if(len < t) { + if(!samplepos) return par; + float prevlen = Samples[samplepos-1][ArcLen]; + float prevpar = Samples[samplepos-1][Param]; + float p = (t - prevlen) / (len - prevlen); + return prevpar + (par - prevpar) * p; + } else { + if(samplepos >= SampleCount) return par; + float nextlen = Samples[samplepos+1][ArcLen]; + float nextpar = Samples[samplepos+1][Param]; + float p = (t - len) / (nextlen - len); + return par + (nextpar - par) * p; + } + + return par; // not gonna happen +} + + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +float Curve::Ease(float t) { + if(!ease_curve) return t; + + ease_curve->SetArcParametrization(true); + float et = ease_curve->Interpolate(t).y; + + return MIN(MAX(et, 0.0f), 1.0f); +} + + +void Curve::AddControlPoint(const Vector3 &cp) { + ControlPoints.PushBack(cp); + delete [] Samples; + Samples = 0; +} + +void Curve::SetEaseCurve(Curve *curve) { + ease_curve = curve; +} + +void Curve::SetEaseSampleCount(int count) { + ease_sample_count = count; + ease_step = 1.0f / ease_sample_count; +} + + +///////////////// B-Spline implementation //////////////////// + +int BSpline::GetSegmentCount() const { + return ControlPoints.Size() - 3; +} + +Vector3 BSpline::Interpolate(float t) { + + if(ControlPoints.Size() < 4) return Vector3(0, 0, 0); + + if(ArcParametrize) { + t = Ease(Parametrize(t)); + } + + // find the appropriate segment of the spline that t lies and calculate the piecewise parameter + t = (float)(ControlPoints.Size() - 3) * t; + int seg = (int)t; + t -= (float)floor(t); + if(seg >= GetSegmentCount()) { + seg = GetSegmentCount() - 1; + t = 1.0f; + } + + ListNode *iter = ControlPoints.Begin(); + for(int i=0; inext; + + Vector3 Cp[4]; + for(int i=0; i<4; i++) { + Cp[i] = iter->data; + iter = iter->next; + } + + Matrix4x4 BSplineMat(-1, 3, -3, 1, 3, -6, 3, 0, -3, 0, 3, 0, 1, 4, 1, 0); + BSplineMat.Transpose(); + Vector4 Params(t*t*t, t*t, t, 1); + Vector4 CpX(Cp[0].x, Cp[1].x, Cp[2].x, Cp[3].x); + Vector4 CpY(Cp[0].y, Cp[1].y, Cp[2].y, Cp[3].y); + Vector4 CpZ(Cp[0].z, Cp[1].z, Cp[2].z, Cp[3].z); + + CpX.Transform(BSplineMat); + CpY.Transform(BSplineMat); + CpZ.Transform(BSplineMat); + + CpX /= 6.0f; + CpY /= 6.0f; + CpZ /= 6.0f; + + Vector3 res; + + res.x = Params.DotProduct(CpX); + res.y = Params.DotProduct(CpY); + res.z = Params.DotProduct(CpZ); + + return res; +} + +//////////////// Catmull-Rom Spline implementation ////////////////// + +int CatmullRomSpline::GetSegmentCount() const { + return ControlPoints.Size() - 1; +} + +Vector3 CatmullRomSpline::Interpolate(float t) { + + if(ControlPoints.Size() < 2) return Vector3(0, 0, 0); + + if(ArcParametrize) { + t = Ease(Parametrize(t)); + } + + // find the appropriate segment of the spline that t lies and calculate the piecewise parameter + t = (float)(ControlPoints.Size() - 1) * t; + int seg = (int)t; + t -= (float)floor(t); + if(seg >= GetSegmentCount()) { + seg = GetSegmentCount() - 1; + t = 1.0f; + } + + Vector3 Cp[4]; + ListNode *iter = ControlPoints.Begin(); + for(int i=0; inext; + + Cp[1] = iter->data; + Cp[2] = iter->next->data; + + if(!seg) { + Cp[0] = Cp[1]; + } else { + Cp[0] = iter->prev->data; + } + + if(seg == ControlPoints.Size() - 2) { + Cp[3] = Cp[2]; + } else { + Cp[3] = iter->next->next->data; + } + + Matrix4x4 BSplineMat(-1, 3, -3, 1, 2, -5, 4, -1, -1, 0, 1, 0, 0, 2, 0, 0); + BSplineMat.Transpose(); + Vector4 Params(t*t*t, t*t, t, 1); + Vector4 CpX(Cp[0].x, Cp[1].x, Cp[2].x, Cp[3].x); + Vector4 CpY(Cp[0].y, Cp[1].y, Cp[2].y, Cp[3].y); + Vector4 CpZ(Cp[0].z, Cp[1].z, Cp[2].z, Cp[3].z); + + CpX.Transform(BSplineMat); + CpY.Transform(BSplineMat); + CpZ.Transform(BSplineMat); + + CpX /= 2.0f; + CpY /= 2.0f; + CpZ /= 2.0f; + + Vector3 res; + + res.x = Params.DotProduct(CpX); + res.y = Params.DotProduct(CpY); + res.z = Params.DotProduct(CpZ); + + return res; +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/common/curves.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/curves.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,50 @@ +#ifndef _CURVES_H_ +#define _CURVES_H_ + +#include +#include "n3dmath.h" +#include "linkedlist.h" + +class Curve { +protected: + LinkedList ControlPoints; + Vector2 *Samples; // used for parametrizing by arc length + int SampleCount; + bool ArcParametrize; + + Curve *ease_curve; // ease in/out curve (1D, x&z discarded) + int ease_sample_count, ease_step; + + void SampleArcLengths(); + float Parametrize(float t); + float Ease(float t); + +public: + std::string name; + + Curve(); + ~Curve(); + virtual void AddControlPoint(const Vector3 &cp); + + virtual int GetSegmentCount() const = 0; + virtual void SetArcParametrization(bool state); + virtual void SetEaseCurve(Curve *curve); + virtual void SetEaseSampleCount(int count); + + virtual Vector3 Interpolate(float t) = 0; +}; + +class BSpline : public Curve { +public: + virtual int GetSegmentCount() const; + virtual Vector3 Interpolate(float t); +}; + +class CatmullRomSpline : public Curve { +public: + virtual int GetSegmentCount() const; + virtual Vector3 Interpolate(float t); +}; + + +#endif // _CURVES_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/common/hashtable.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/hashtable.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,103 @@ +#ifndef HASHTABLE_H_ +#define HASHTABLE_H_ + +#include +#include + +template +struct Pair { + KeyT key; + ValT val; +}; + +template +class HashTable { +private: + + size_t size; + std::vector > > table; + //std::list > table[100]; + + unsigned int (*HashFunc)(const KeyType &key, unsigned long size); + unsigned int Hash(const KeyType &key) {return (unsigned int)HashFunc(key, (unsigned long)size);} + +public: + + HashTable(unsigned long size = 101); + ~HashTable(); + + void SetHashFunction(unsigned int (*HashFunc)(const KeyType&, unsigned long)); + + void Insert(KeyType key, ValType value); + void Remove(KeyType key); + + Pair *Find(KeyType key); +}; + +//// std hash function +//template +//unsigned int _HashFunction(const KeyType &key, unsigned long size) { +// return (size_t)key % size; +//} + +// hash table member functions +template +HashTable::HashTable(unsigned long size) { + this->size = size; + //HashFunc = _HashFunction; + table.resize(size); +} + +template +HashTable::~HashTable() { + for(unsigned long i=0; i +void HashTable::SetHashFunction(unsigned int (*HashFunc)(const KeyType&, unsigned long)) { + this->HashFunc = HashFunc; +} + +template +void HashTable::Insert(KeyType key, ValType value) { + Pair newpair; + newpair.key = key; + newpair.val = value; + + table[Hash(key)].push_back(newpair); +} + +template +void HashTable::Remove(KeyType key) { + + unsigned int pos = Hash(key); + + std::list >::iterator iter = table[pos].begin(); + while(iter != table[pos].end()) { + if(iter->key == key) { + table[pos].erase(iter); + return; + } + iter++; + } +} + +template +Pair *HashTable::Find(KeyType key) { + + unsigned int pos = Hash(key); + + std::list >::iterator iter = table[pos].begin(); + while(iter != table[pos].end()) { + if(iter->key == key) { + return &(*iter); + } + iter++; + } + + return 0; +} + +#endif // HASHTABLE_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/common/linkedlist.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/linkedlist.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,229 @@ +#ifndef _LINKEDLIST_H_ +#define _LINKEDLIST_H_ + +template +struct ListNode { + T data; + ListNode *next, *prev; +}; + + +template +class LinkedList { +private: + ListNode *head, *tail; + int size; + +public: + + LinkedList(); + ~LinkedList(); + + inline ListNode *Begin(); + inline ListNode *End(); + + void PushBack(ListNode *node); + void PushBack(T data); + + void Insert(ListNode *pos, ListNode *node); + void Insert(ListNode *pos, T data); + + void Remove(ListNode *node); + ListNode *Erase(ListNode *node); + + ListNode *Find(T key); + + int CountNodes(); + inline int Size() const; + + void operator =(LinkedList &rhs); +}; + + +/////////// implementation ////////// +template +LinkedList::LinkedList() { + head = tail = 0; + size = 0; +} + + +template +LinkedList::~LinkedList() { + + while(head) { + Erase(head); + } +} + +template +ListNode *LinkedList::Begin() { + return head; +} + +template +ListNode *LinkedList::End() { + return tail; +} + +template +void LinkedList::PushBack(ListNode *node) { + + if(!head) { // empty list + head = tail = node; + node->next = node->prev = 0; + } else { + tail->next = node; + node->prev = tail; + tail = node; + node->next = 0; + } + + size++; +} + +template +void LinkedList::PushBack(T data) { + + ListNode *node = new ListNode; + node->data = data; + + if(!head) { // empty list + head = tail = node; + node->next = node->prev = 0; + } else { + tail->next = node; + node->prev = tail; + tail = node; + node->next = 0; + } + + size++; +} + +template +void LinkedList::Insert(ListNode *pos, ListNode *node) { + + if(!head) { + head = tail = node; + node->next = node->prev = 0; + } else { + node->prev = pos->prev; + pos->prev = node; + node->next = pos; + if(head == pos) head = node; else node->prev->next = node; + } + + size++; +} + +template +void LinkedList::Insert(ListNode *pos, T data) { + + ListNode *node = new ListNode; + node->data = data; + + if(!head) { + head = tail = node; + node->next = node->prev = 0; + } else { + node->prev = pos->prev; + pos->prev = node; + node->next = pos; + if(head == pos) head = node; else node->prev->next = node; + } + + size++; +} + +template +void LinkedList::Remove(ListNode *node) { + + if(!node) return; // e.g. Remove(head) on an empty list + + if(node->prev) { + node->prev->next = node->next; + } else { + head = node->next; + } + + if(node->next) { + node->next->prev = node->prev; + } else { + tail = node->prev; + } + + size--; +} + +template +ListNode *LinkedList::Erase(ListNode *node) { + + if(!node) return 0; // e.g. Erase(head) on an empty list + + if(node->prev) { + node->prev->next = node->next; + } else { + head = node->next; + } + + if(node->next) { + node->next->prev = node->prev; + } else { + tail = node->prev; + } + + ListNode *destr = node; + node = node->next; + + delete destr; + + size--; + + return node; +} + +template +ListNode *LinkedList::Find(T key) { + + ListNode *iter = head; + while(iter) { + if(iter->data == key) return iter; + iter = iter->next; + } + + return 0; // null pointer if not found +} + +template +int LinkedList::CountNodes() { + + size = 0; + + ListNode *iter = head; + while(iter) { + size++; + iter = iter->next; + } + + return size; +} + +template +int LinkedList::Size() const { + return size; +} + + +template +void LinkedList::operator =(LinkedList &rhs) { + + ListNode *src = rhs.Begin(); + while(src) { + PushBack(src->data); + src = src->next; + } +} + + +#endif // _LINKEDLIST_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/common/n3dmath.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/n3dmath.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,1370 @@ +#include "n3dmath.h" + +#define fsin (float)sin +#define fcos (float)cos + +float frand(float range) { + return ((float)rand() / (float)RAND_MAX) * range; +} + +Vector3::Vector3() { + x = y = z = 0.0f; +} + +Vector3::Vector3(float x, float y, float z) { + this->x = x; + this->y = y; + this->z = z; +} +/* inlined +float Vector3::DotProduct(const Vector3 &vec) const { + return x * vec.x + y * vec.y + z * vec.z; +} + +float DotProduct(const Vector3 &vec1, const Vector3 &vec2) { + return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z; +} + +Vector3 Vector3::CrossProduct(const Vector3 &vec) const { + return Vector3(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x); +} + +Vector3 CrossProduct(const Vector3 &vec1, const Vector3 &vec2) { + return Vector3(vec1.y * vec2.z - vec1.z * vec2.y, vec1.z * vec2.x - vec1.x * vec2.z, vec1.x * vec2.y - vec1.y * vec2.x); +} + +Vector3 Vector3::operator +(const Vector3 &vec) const { + return Vector3(x + vec.x, y + vec.y, z + vec.z); +} + +Vector3 Vector3::operator -(const Vector3 &vec) const { + return Vector3(x - vec.x, y - vec.y, z - vec.z); +} + +Vector3 Vector3::operator *(float scalar) const { + return Vector3(x * scalar, y * scalar, z * scalar); +} + +Vector3 Vector3::operator /(float scalar) const { + return Vector3(x / scalar, y / scalar, z / scalar); +} + +void Vector3::operator +=(const Vector3 &vec) { + x += vec.x; + y += vec.y; + z += vec.z; +} + +void Vector3::operator -=(const Vector3 &vec) { + x -= vec.x; + y -= vec.y; + z -= vec.z; +} + +void Vector3::operator *=(float scalar) { + x *= scalar; + y *= scalar; + z *= scalar; +} + +void Vector3::operator /=(float scalar) { + x /= scalar; + y /= scalar; + z /= scalar; +} + +Vector3 Vector3::operator -() const { + return Vector3(-x, -y, -z); +} + +bool Vector3::operator >(const Vector3 &vec) const { + return LengthSq() > vec.LengthSq(); +} + +bool Vector3::operator <(const Vector3 &vec) const { + return LengthSq() < vec.LengthSq(); +} + +bool Vector3::operator >(float len) const { + return LengthSq() > len; +} + +bool Vector3::operator <(float len) const { + return LengthSq() < len; +} + +bool Vector3::operator ==(const Vector3 &vec) const { + return ((*this - vec).Length() < XSmallNumber); +} + +bool Vector3::operator ==(float len) const { + return ((this->Length() - len) < XSmallNumber); +} + +Vector3::operator Vector2() const { + return Vector2(x, y); +} + +Vector3::operator Vector4() const { + return Vector4(x, y, z, 1.0f); +} + + +float Vector3::Length() const { + return (float)sqrt(x*x + y*y + z*z); +} + +float Vector3::LengthSq() const { + return x*x + y*y + z*z; +} + +void Vector3::Normalize() { + float len = (float)sqrt(x*x + y*y + z*z); + x /= len; + y /= len; + z /= len; +} + +Vector3 Vector3::Normalized() const { + float len = (float)sqrt(x*x + y*y + z*z); + return Vector3(x / len, y / len, z / len); +} + +Vector3 Vector3::Reflection(const Vector3 &normal) const { + return normal * this->DotProduct(normal) * 2.0f - *this; +} +*/ +Vector3 Vector3::Refraction(const Vector3 &normal, float FromIOR, float ToIOR) const { + float m = FromIOR / ToIOR; + Vector3 dir = *this; + dir.Normalize(); + float CosAngleIncoming = dir.DotProduct(normal); + float CosAngleRefr = (1.0f / (m*m)) * (float)sqrt(1.0f - m*m * (1 - CosAngleIncoming * CosAngleIncoming)); + + return dir * m - normal * (CosAngleRefr + m * CosAngleIncoming); +} + +void Vector3::Transform(const Matrix4x4 &mat) { + // assume row vectors + float nx = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + mat.m[3][0]; + float ny = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + mat.m[3][1]; + z = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + mat.m[3][2]; + x = nx; + y = ny; +} + +void Vector3::Transform(const Quaternion &quat) { + Quaternion vq(0.0f, *this); + vq = quat * vq * quat.Inverse(); + *this = vq.v; +} + +// direct transformations + +void Vector3::Translate(float x, float y, float z) { + this->x += x; + this->y += y; + this->z += z; +} + +void Vector3::Rotate(float x, float y, float z) { + + Matrix4x4 xform; + xform.SetRotation(x, y, z); + + Transform(xform); +} + +void Vector3::Rotate(const Vector3 &axis, float angle) { + + Matrix4x4 xform; + xform.SetRotation(axis, angle); + + Transform(xform); +} + +void Vector3::Scale(float x, float y, float z) { + this->x *= x; + this->y *= y; + this->z *= z; +} + +float &Vector3::operator [](int index) { + return !index ? x : index == 1 ? y : z; +} + +std::ostream &operator <<(std::ostream &out, const Vector3 &vec) { + out << vec.x << ", " << vec.y << ", " << vec.z; + return out; +} + +// ------------- Vector4 implementation --------------- + +Vector4::Vector4() { + x = y = z = 0.0f; +} + +Vector4::Vector4(const Vector4 &vec) { + x = vec.x; + y = vec.y; + z = vec.z; + w = vec.w; +} + +Vector4::Vector4(const Vector3 &vec) { + x = vec.x; + y = vec.y; + z = vec.z; + w = 1.0f; +} + +Vector4::Vector4(float x, float y, float z, float w) { + this->x = x; + this->y = y; + this->z = z; + this->w = w; +} + +float Vector4::DotProduct(const Vector4 &vec) const { + return x * vec.x + y * vec.y + z * vec.z + w * vec.w; +} + +float DotProduct(const Vector4 &vec1, const Vector4 &vec2) { + return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z + vec1.w * vec2.w; +} + +Vector4 Vector4::CrossProduct(const Vector4 &vec1, const Vector4 &vec2) const { + float A, B, C, D, E, F; // Intermediate Values + Vector4 result; + + // Calculate intermediate values. + A = (vec1.x * vec2.y) - (vec1.y * vec2.x); + B = (vec1.x * vec2.z) - (vec1.z * vec2.x); + C = (vec1.x * vec2.w) - (vec1.w * vec2.x); + D = (vec1.y * vec2.z) - (vec1.z * vec2.y); + E = (vec1.y * vec2.w) - (vec1.w * vec2.y); + F = (vec1.z * vec2.w) - (vec1.w * vec2.z); + + // Calculate the result-vector components. + result.x = (y * F) - (z * E) + (w * D); + result.y = - (x * F) + (z * C) - (w * B); + result.z = (x * E) - (y * C) + (w * A); + result.w = - (x * D) + (y * B) - (z * A); + return result; +} + +Vector4 CrossProduct(const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3) { + float A, B, C, D, E, F; // Intermediate Values + Vector4 result; + + // Calculate intermediate values. + A = (vec2.x * vec3.y) - (vec2.y * vec3.x); + B = (vec2.x * vec3.z) - (vec2.z * vec3.x); + C = (vec2.x * vec3.w) - (vec2.w * vec3.x); + D = (vec2.y * vec3.z) - (vec2.z * vec3.y); + E = (vec2.y * vec3.w) - (vec2.w * vec3.y); + F = (vec2.z * vec3.w) - (vec2.w * vec3.z); + + // Calculate the result-vector components. + result.x = (vec1.y * F) - (vec1.z * E) + (vec1.w * D); + result.y = - (vec1.x * F) + (vec1.z * C) - (vec1.w * B); + result.z = (vec1.x * E) - (vec1.y * C) + (vec1.w * A); + result.w = - (vec1.x * D) + (vec1.y * B) - (vec1.z * A); + return result; +} + +Vector4 Vector4::operator +(const Vector4 &vec) const { + return Vector4(x + vec.x, y + vec.y, z + vec.z, w + vec.w); +} + +Vector4 Vector4::operator -(const Vector4 &vec) const { + return Vector4(x - vec.x, y - vec.y, z - vec.z, w - vec.w); +} + +Vector4 Vector4::operator *(float scalar) const { + return Vector4(x * scalar, y * scalar, z * scalar, w * scalar); +} + +Vector4 Vector4::operator /(float scalar) const { + return Vector4(x / scalar, y / scalar, z / scalar, w / scalar); +} + +void Vector4::operator +=(const Vector4 &vec) { + x += vec.x; + y += vec.y; + z += vec.z; + w += vec.w; +} + +void Vector4::operator -=(const Vector4 &vec) { + x -= vec.x; + y -= vec.y; + z -= vec.z; + w -= vec.w; +} + +void Vector4::operator *=(float scalar) { + x *= scalar; + y *= scalar; + z *= scalar; + w *= scalar; +} + +void Vector4::operator /=(float scalar) { + x /= scalar; + y /= scalar; + z /= scalar; + w /= scalar; +} + +Vector4 Vector4::operator -() const { + return Vector4(-x, -y, -z, -w); +} + + +bool Vector4::operator >(const Vector4 &vec) const { + return LengthSq() > vec.LengthSq(); +} + +bool Vector4::operator <(const Vector4 &vec) const { + return LengthSq() < vec.LengthSq(); +} + +bool Vector4::operator >(float len) const { + return LengthSq() > len; +} + +bool Vector4::operator <(float len) const { + return LengthSq() < len; +} + +bool Vector4::operator ==(const Vector4 &vec) const { + return ((*this - vec).Length() < XSmallNumber); +} + +bool Vector4::operator ==(float len) const { + return ((this->Length() - len) < XSmallNumber); +} + +Vector4::operator Vector3() const { + return Vector3(x, y, z); +} + + +float Vector4::Length() const { + return (float)sqrt(x*x + y*y + z*z + w*w); +} + +float Vector4::LengthSq() const { + return x*x + y*y + z*z + w*w; +} + +void Vector4::Normalize() { + float len = (float)sqrt(x*x + y*y + z*z + w*w); + x /= len; + y /= len; + z /= len; + w /= len; +} + +Vector4 Vector4::Normalized() const { + float len = (float)sqrt(x*x + y*y + z*z + w*w); + return Vector4(x / len, y / len, z / len, w / len); +} + +void Vector4::Transform(const Matrix4x4 &mat) { + // assume row vectors + float nx = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0]; + float ny = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1]; + float nz = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2]; + w = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]; + x = nx; + y = ny; + z = nz; +} + + +// Direct transformations on the vector +void Vector4::Translate(float x, float y, float z, float w) { + x += x; + y += y; + z += z; + w += w; +} + +void Vector4::Rotate(float x, float y, float z) { + Matrix4x4 xform; + xform.SetRotation(x, y, z); + Transform(xform); +} + +void Vector4::Rotate(const Vector3 &axis, float angle) { + Matrix4x4 xform; + xform.SetRotation(axis, angle); + Transform(xform); +} + +void Vector4::Scale(float x, float y, float z, float w) { + this->x *= x; + this->y *= y; + this->z *= z; + this->w *= w; +} + +float &Vector4::operator [](int index) { + return !index ? x : index == 1 ? y : index == 2 ? z : w; +} + +std::ostream &operator <<(std::ostream &out, const Vector4 &vec) { + out << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w; + return out; +} + +// ------------- Vector2 implementation --------------- + +Vector2::Vector2() { + x = y = 0.0f; +} + +Vector2::Vector2(const Vector2 &vec) { + x = vec.x; + y = vec.y; +} + +Vector2::Vector2(float x, float y) { + this->x = x; + this->y = y; +} + +float Vector2::DotProduct(const Vector2 &vec) const { + return x * vec.x + y * vec.y; +} + +float DotProduct(const Vector2 &vec1, const Vector2 &vec2) { + return vec1.x * vec2.x + vec1.y + vec2.y; +} + +Vector2 Vector2::operator +(const Vector2 &vec) const { + return Vector2(x + vec.x, y + vec.y); +} + +Vector2 Vector2::operator -(const Vector2 &vec) const { + return Vector2(x - vec.x, y - vec.y); +} + +Vector2 Vector2::operator *(float scalar) const { + return Vector2(x * scalar, y * scalar); +} + +Vector2 Vector2::operator /(float scalar) const { + return Vector2(x / scalar, y / scalar); +} + +void Vector2::operator +=(const Vector2 &vec) { + x += vec.x; + y += vec.y; +} + +void Vector2::operator -=(const Vector2 &vec) { + x -= vec.x; + y -= vec.y; +} + +void Vector2::operator *=(float scalar) { + x *= scalar; + y *= scalar; +} + +void Vector2::operator /=(float scalar) { + x /= scalar; + y /= scalar; +} + +Vector2 Vector2::operator -() const { + return Vector2(-x, -y); +} + +bool Vector2::operator >(const Vector2 &vec) const { + return LengthSq() > vec.LengthSq(); +} + +bool Vector2::operator <(const Vector2 &vec) const { + return LengthSq() < vec.LengthSq(); +} + +bool Vector2::operator >(float len) const { + return LengthSq() > len; +} + +bool Vector2::operator <(float len) const { + return LengthSq() < len; +} + +bool Vector2::operator ==(const Vector2 &vec) const { + return ((*this - vec).Length() < XSmallNumber); +} + +bool Vector2::operator ==(float len) const { + return ((this->Length() - len) < XSmallNumber); +} + +Vector2::operator Vector3() const { + return Vector3(x, y, 1.0f); +} + +float Vector2::Length() const { + return (float)sqrt(x * x + y * y); +} + +float Vector2::LengthSq() const { + return x * x + y * y; +} + +void Vector2::Normalize() { + float len = (float)sqrt(x * x + y * y); + x /= len; + y /= len; +} + +Vector2 Vector2::Normalized() const { + float len = (float)sqrt(x * x + y * y); + return Vector2(x / len, y / len); +} + +//Vector2 Vector2::Reflection(const Vector2 &normal) const; +//Vector2 Vector2::Refraction(const Vector2 &normal, float FromIOR, float ToIOR) const; + +void Vector2::Transform(const Matrix3x3 &mat) { + float nx = x * mat.m[0][0] + y * mat.m[1][0] + mat.m[2][0]; + y = x * mat.m[0][1] + y * mat.m[1][1] + mat.m[2][1]; + x = nx; +} + +void Vector2::Translate(float x, float y) { + this->x += x; + this->y += y; +} + +void Vector2::Rotate(float angle) { + Matrix3x3 xform; + xform.SetRotation(angle); + + Transform(xform); +} + +void Vector2::Scale(float x, float y) { + this->x *= x; + this->y *= y; +} + +float &Vector2::operator [](int index) { + return !index ? x : y; +} + +std::ostream &operator <<(std::ostream &out, const Vector2 &vec) { + out << vec.x << ", " << vec.y; + return out; +} + + +// --------------- Quaternion implementation --------------- + +Quaternion::Quaternion() { + s = 1.0f; + v.x = v.y = v.z = 0.0f; +} + +Quaternion::Quaternion(float s, float x, float y, float z) { + v.x = x; + v.y = y; + v.z = z; + this->s = s; +} + +Quaternion::Quaternion(float s, const Vector3 &v) { + this->s = s; + this->v = v; +} + +Quaternion Quaternion::operator +(const Quaternion &quat) const { + return Quaternion(s + quat.s, v + quat.v); +} + +Quaternion Quaternion::operator -(const Quaternion &quat) const { + return Quaternion(s - quat.s, v - quat.v); +} + +Quaternion Quaternion::operator -() const { + return Quaternion(-s, -v); +} + +// Quaternion Multiplication: +// Q1*Q2 = [s1*s2 - v1.v2, s1*v2 + s2*v1 + v1(x)v2] +Quaternion Quaternion::operator *(const Quaternion &quat) const { + Quaternion newq; + newq.s = s * quat.s - DotProduct(v, quat.v); + newq.v = quat.v * s + v * quat.s + CrossProduct(v, quat.v); + return newq; +} + +void Quaternion::operator +=(const Quaternion &quat) { + *this = Quaternion(s + quat.s, v + quat.v); +} + +void Quaternion::operator -=(const Quaternion &quat) { + *this = Quaternion(s - quat.s, v - quat.v); +} + +void Quaternion::operator *=(const Quaternion &quat) { + *this = *this * quat; +} + +void Quaternion::ResetIdentity() { + s = 1.0f; + v.x = v.y = v.z = 0.0f; +} + +Quaternion Quaternion::Conjugate() const { + return Quaternion(s, -v); +} + +float Quaternion::Length() const { + return (float)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s); +} + +// Q * ~Q = ||Q||^2 +float Quaternion::LengthSq() const { + return v.x*v.x + v.y*v.y + v.z*v.z + s*s; +} + +void Quaternion::Normalize() { + float len = (float)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s); + v.x /= len; + v.y /= len; + v.z /= len; + s /= len; +} + +Quaternion Quaternion::Normalized() const { + Quaternion nq = *this; + float len = (float)sqrt(v.x*v.x + v.y*v.y + v.z*v.z + s*s); + nq.v.x /= len; + nq.v.y /= len; + nq.v.z /= len; + nq.s /= len; + return nq; +} + +// Quaternion Inversion: Q^-1 = ~Q / ||Q||^2 +Quaternion Quaternion::Inverse() const { + Quaternion inv = Conjugate(); + float lensq = LengthSq(); + inv.v /= lensq; + inv.s /= lensq; + + return inv; +} + + +void Quaternion::SetRotation(const Vector3 &axis, float angle) { + float HalfAngle = angle / 2.0f; + s = cosf(HalfAngle); + v = axis * sinf(HalfAngle); +} + +void Quaternion::Rotate(const Vector3 &axis, float angle) { + Quaternion q; + float HalfAngle = angle / 2.0f; + q.s = cosf(HalfAngle); + q.v = axis * sinf(HalfAngle); + + *this *= q; +} + + +Matrix3x3 Quaternion::GetRotationMatrix() const { + return Matrix3x3(1.0f - 2.0f * v.y*v.y - 2.0f * v.z*v.z, 2.0f * v.x * v.y + 2.0f * s * v.z, 2.0f * v.z * v.x - 2.0f * s * v.y, + 2.0f * v.x * v.y - 2.0f * s * v.z, 1.0f - 2.0f * v.x*v.x - 2.0f * v.z*v.z, 2.0f * v.y * v.z + 2.0f * s * v.x, + 2.0f * v.z * v.x + 2.0f * s * v.y, 2.0f * v.y * v.z - 2.0f * s * v.x, 1.0f - 2.0f * v.x*v.x - 2.0f * v.y*v.y); +} + + +// ------------- Matrix implementation --------------- + +Matrix4x4::Matrix4x4() { + memset(m, 0, 16*sizeof(float)); + m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; +} + +Matrix4x4::Matrix4x4(const Matrix4x4 &mat) { + memcpy(m, mat.m, 16*sizeof(float)); +} + +Matrix4x4::Matrix4x4(const Matrix3x3 &mat) { + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + m[i][j] = mat.m[i][j]; + } + } + m[3][0] = m[3][1] = m[3][2] = m[0][3] = m[1][3] = m[2][3] = 0.0f; + m[3][3] = 1.0f; +} + +Matrix4x4::Matrix4x4( float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33 ) { + + memcpy(m, &m00, 16*sizeof(float)); // arguments are adjacent in stack +} + +Matrix4x4 Matrix4x4::operator +(const Matrix4x4 &mat) const { + + Matrix4x4 tmp; + + const float *op1 = (float*)m; + const float *op2 = (float*)mat.m; + float *dst = (float*)tmp.m; + + for(int i=0; i<16; i++) *dst++ = *op1++ + *op2++; + + return tmp; +} + +Matrix4x4 Matrix4x4::operator -(const Matrix4x4 &mat) const { + + Matrix4x4 tmp; + + const float *op1 = (float*)m; + const float *op2 = (float*)mat.m; + float *dst = (float*)tmp.m; + + for(int i=0; i<16; i++) *dst++ = *op1++ - *op2++; + + return tmp; +} + +Matrix4x4 Matrix4x4::operator *(float scalar) const { + + Matrix4x4 tmp; + + const float *op1 = (float*)m; + float *dst = (float*)tmp.m; + + for(int i=0; i<16; i++) *dst++ = *op1++ * scalar; + + return tmp; +} + +Matrix4x4 Matrix4x4::operator *(const Matrix4x4 &mat) const { + Matrix4x4 tmp; + + for(int i=0; i<4; i++) { + for(int j=0; j<4; j++) { + tmp.m[i][j] = m[i][0]*mat.m[0][j] + m[i][1]*mat.m[1][j] + m[i][2]*mat.m[2][j] + m[i][3]*mat.m[3][j]; + } + } + + return tmp; +} + +void Matrix4x4::operator +=(const Matrix4x4 &mat) { + + const float *op2 = (float*)mat.m; + float *dst = (float*)m; + + for(int i=0; i<16; i++) *dst++ += *op2++; +} + +void Matrix4x4::operator -=(const Matrix4x4 &mat) { + + const float *op2 = (float*)mat.m; + float *dst = (float*)m; + + for(int i=0; i<16; i++) *dst++ -= *op2++; +} + +void Matrix4x4::operator *=(float scalar) { + + float *dst = (float*)m; + + for(int i=0; i<16; i++) *dst++ *= scalar; +} + +void Matrix4x4::operator *=(const Matrix4x4 &mat) { + Matrix4x4 tmp; + + for(int i=0; i<4; i++) { + for(int j=0; j<4; j++) { + tmp.m[i][j] = m[i][0]*mat.m[0][j] + m[i][1]*mat.m[1][j] + m[i][2]*mat.m[2][j] + m[i][3]*mat.m[3][j]; + } + } + + memcpy(m, tmp.m, 16*sizeof(float)); +} + + +void Matrix4x4::ResetIdentity() { + memset(m, 0, 16*sizeof(float)); + m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; +} + + +// Transformations (assuming column vectors) + +void Matrix4x4::Translate(float x, float y, float z) { + + Matrix4x4 tmp( 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, y, z, 1 ); + *this *= tmp; +} + +void Matrix4x4::Rotate(float x, float y, float z) { + + *this *= Matrix4x4( 1, 0, 0, 0, + 0, fcos(x), fsin(x), 0, + 0, -fsin(x), fcos(x), 0, + 0, 0, 0, 1 ); + + *this *= Matrix4x4( fcos(y), 0, -fsin(y), 0, + 0, 1, 0, 0, + fsin(y), 0, fcos(y), 0, + 0, 0, 0, 1 ); + + *this *= Matrix4x4( fcos(z), fsin(z), 0, 0, + -fsin(z), fcos(z), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 ); +} + +void Matrix4x4::Rotate(const Vector3 &axis, float angle) { + + float sina = fsin(angle); + float cosa = fcos(angle); + float invcosa = 1-cosa; + float nxsq = axis.x * axis.x; + float nysq = axis.y * axis.y; + float nzsq = axis.z * axis.z; + + Matrix4x4 xform; + xform.m[0][0] = nxsq + (1-nxsq) * cosa; + xform.m[0][1] = axis.x * axis.y * invcosa - axis.z * sina; + xform.m[0][2] = axis.x * axis.z * invcosa + axis.y * sina; + xform.m[1][0] = axis.x * axis.y * invcosa + axis.z * sina; + xform.m[1][1] = nysq + (1-nysq) * cosa; + xform.m[1][2] = axis.y * axis.z * invcosa - axis.x * sina; + xform.m[2][0] = axis.x * axis.z * invcosa - axis.y * sina; + xform.m[2][1] = axis.y * axis.z * invcosa + axis.x * sina; + xform.m[2][2] = nzsq + (1-nzsq) * cosa; + + *this *= xform; +} + +void Matrix4x4::Scale(float x, float y, float z) { + + Matrix4x4 xform(x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1 ); + *this *= xform; +} + + +////////////////////////////// + +void Matrix4x4::SetTranslation(float x, float y, float z) { + + *this = Matrix4x4( 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + x, y, z, 1 ); +} + +void Matrix4x4::SetRotation(float x, float y, float z) { + + *this = Matrix4x4( 1, 0, 0, 0, + 0, fcos(x), fsin(x), 0, + 0, -fsin(x), fcos(x), 0, + 0, 0, 0, 1 ); + + *this *= Matrix4x4( fcos(y), 0, -fsin(y), 0, + 0, 1, 0, 0, + fsin(y), 0, fcos(y), 0, + 0, 0, 0, 1 ); + + *this *= Matrix4x4( fcos(z), fsin(z), 0, 0, + -fsin(z), fcos(z), 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 ); +} + +void Matrix4x4::SetRotation(const Vector3 &axis, float angle) { + + // caching of multiply used function results (opt) + float sina = fsin(angle); + float cosa = fcos(angle); + float invcosa = 1-cosa; + float nxsq = axis.x * axis.x; + float nysq = axis.y * axis.y; + float nzsq = axis.z * axis.z; + + Matrix4x4 xform; + xform.m[0][0] = nxsq + (1-nxsq) * cosa; + xform.m[0][1] = axis.x * axis.y * invcosa - axis.z * sina; + xform.m[0][2] = axis.x * axis.z * invcosa + axis.y * sina; + xform.m[1][0] = axis.x * axis.y * invcosa + axis.z * sina; + xform.m[1][1] = nysq + (1-nysq) * cosa; + xform.m[1][2] = axis.y * axis.z * invcosa - axis.x * sina; + xform.m[2][0] = axis.x * axis.z * invcosa - axis.y * sina; + xform.m[2][1] = axis.y * axis.z * invcosa + axis.x * sina; + xform.m[2][2] = nzsq + (1-nzsq) * cosa; + + *this = xform; +} + +void Matrix4x4::SetScaling(float x, float y, float z) { + + Matrix4x4 xform(x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1 ); + *this = xform; +} + +void Matrix4x4::SetColumnVector(const Vector4 &vec, int columnindex) { + + m[0][columnindex] = vec.x; + m[1][columnindex] = vec.y; + m[2][columnindex] = vec.z; + m[3][columnindex] = vec.w; +} + +void Matrix4x4::SetRowVector(const Vector4 &vec, int rowindex) { + + m[rowindex][0] = vec.x; + m[rowindex][1] = vec.y; + m[rowindex][2] = vec.z; + m[rowindex][3] = vec.w; +} + +Vector4 Matrix4x4::GetColumnVector(int columnindex) const { + + return Vector4(m[0][columnindex], m[1][columnindex], m[2][columnindex], m[3][columnindex]); +} + +Vector4 Matrix4x4::GetRowVector(int rowindex) const { + + return Vector4(m[rowindex][0], m[rowindex][1], m[rowindex][2], m[rowindex][3]); +} + +// other operations on matrices + +void Matrix4x4::Transpose() { + Matrix4x4 mat = *this; + + for(int i=0; i<4; i++) { + for(int j=0; j<4; j++) { + m[i][j] = mat.m[j][i]; + } + } +} + +Matrix4x4 Matrix4x4::Transposed() const { + Matrix4x4 mat = *this; + + for(int i=0; i<4; i++) { + for(int j=0; j<4; j++) { + mat.m[i][j] = m[j][i]; + } + } + + return mat; +} + + +float Matrix4x4::Determinant() const { + + float det11 = (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) + + (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])); + + float det12 = (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])); + + float det13 = (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) - + (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + float det14 = (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) - + (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) + + (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + return m[0][0] * det11 - m[0][1] * det12 + m[0][2] * det13 - m[0][3] * det14; +} + + +Matrix4x4 Matrix4x4::Adjoint() const { + + Matrix4x4 coef; + + coef.m[0][0] = (m[1][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) + + (m[1][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])); + coef.m[0][1] = (m[1][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[1][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])); + coef.m[0][2] = (m[1][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) - + (m[1][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[1][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + coef.m[0][3] = (m[1][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) - + (m[1][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) + + (m[1][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + coef.m[1][0] = (m[0][1] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[0][2] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) + + (m[0][3] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])); + coef.m[1][1] = (m[0][0] * (m[2][2] * m[3][3] - m[3][2] * m[2][3])) - + (m[0][2] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[0][3] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])); + coef.m[1][2] = (m[0][0] * (m[2][1] * m[3][3] - m[3][1] * m[2][3])) - + (m[0][1] * (m[2][0] * m[3][3] - m[3][0] * m[2][3])) + + (m[0][3] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + coef.m[1][3] = (m[0][0] * (m[2][1] * m[3][2] - m[3][1] * m[2][2])) - + (m[0][1] * (m[2][0] * m[3][2] - m[3][0] * m[2][2])) + + (m[0][2] * (m[2][0] * m[3][1] - m[3][0] * m[2][1])); + + coef.m[2][0] = (m[0][1] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) - + (m[0][2] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) + + (m[0][3] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])); + coef.m[2][1] = (m[0][0] * (m[1][2] * m[3][3] - m[3][2] * m[1][3])) - + (m[0][2] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])); + coef.m[2][2] = (m[0][0] * (m[1][1] * m[3][3] - m[3][1] * m[1][3])) - + (m[0][1] * (m[1][0] * m[3][3] - m[3][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[3][1] - m[3][0] * m[1][1])); + coef.m[2][3] = (m[0][0] * (m[1][1] * m[3][2] - m[3][1] * m[1][2])) - + (m[0][1] * (m[1][0] * m[3][2] - m[3][0] * m[1][2])) + + (m[0][2] * (m[1][0] * m[3][1] - m[3][0] * m[1][1])); + + coef.m[3][0] = (m[0][1] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) - + (m[0][2] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) + + (m[0][3] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])); + coef.m[3][1] = (m[0][0] * (m[1][2] * m[2][3] - m[2][2] * m[1][3])) - + (m[0][2] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])); + coef.m[3][2] = (m[0][0] * (m[1][1] * m[2][3] - m[2][1] * m[1][3])) - + (m[0][1] * (m[1][0] * m[2][3] - m[2][0] * m[1][3])) + + (m[0][3] * (m[1][0] * m[2][1] - m[2][0] * m[1][1])); + coef.m[3][3] = (m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])) - + (m[0][1] * (m[1][0] * m[2][2] - m[2][0] * m[1][2])) + + (m[0][2] * (m[1][0] * m[2][1] - m[2][0] * m[1][1])); + + coef.Transpose(); + + float *elem = (float*)coef.m; + for(int i=0; i<4; i++) { + for(int j=0; j<4; j++) { + coef.m[i][j] = j%2 ? -coef.m[i][j] : coef.m[i][j]; + if(i%2) coef.m[i][j] = -coef.m[i][j]; + } + } + + return coef; +} + +Matrix4x4 Matrix4x4::Inverse() const { + + Matrix4x4 AdjMat = Adjoint(); + + return AdjMat * (1.0f / Determinant()); +} + + +// --------- 3 by 3 matrices implementation -------------- + +Matrix3x3::Matrix3x3() { + memset(m, 0, 9 * sizeof(float)); + m[0][0] = m[1][1] = m[2][2] = 1.0f; +} + +Matrix3x3::Matrix3x3(const Matrix3x3 &mat) { + memcpy(m, mat.m, 9 * sizeof(float)); +} + +Matrix3x3::Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) { + memcpy(m, &m00, 9*sizeof(float)); // arguments are adjacent in stack +} + +Matrix3x3 Matrix3x3::operator +(const Matrix3x3 &mat) const { + Matrix3x3 tmp; + + const float *op1 = (float*)m; + const float *op2 = (float*)mat.m; + float *dst = (float*)tmp.m; + + for(int i=0; i<9; i++) *dst++ = *op1++ + *op2++; + + return tmp; +} + +Matrix3x3 Matrix3x3::operator -(const Matrix3x3 &mat) const { + Matrix3x3 tmp; + + const float *op1 = (float*)m; + const float *op2 = (float*)mat.m; + float *dst = (float*)tmp.m; + + for(int i=0; i<9; i++) *dst++ = *op1++ - *op2++; + + return tmp; +} + +Matrix3x3 Matrix3x3::operator *(const Matrix3x3 &mat) const { + Matrix3x3 tmp; + + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + tmp.m[i][j] = m[i][0]*mat.m[0][j] + m[i][1]*mat.m[1][j] + m[i][2]*mat.m[2][j]; + } + } + + return tmp; +} + +Matrix3x3 Matrix3x3::operator *(float scalar) const { + Matrix3x3 tmp; + + const float *op1 = (float*)m; + float *dst = (float*)tmp.m; + + for(int i=0; i<9; i++) *dst++ = *op1++ * scalar; + + return tmp; +} + +void Matrix3x3::operator +=(const Matrix3x3 &mat) { + const float *op = (float*)mat.m; + float *dst = (float*)m; + + for(int i=0; i<9; i++) *dst++ += *op++; +} + +void Matrix3x3::operator -=(const Matrix3x3 &mat) { + const float *op = (float*)mat.m; + float *dst = (float*)m; + + for(int i=0; i<9; i++) *dst++ -= *op++; +} + +void Matrix3x3::operator *=(const Matrix3x3 &mat) { + Matrix4x4 tmp; + + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + tmp.m[i][j] = m[i][0]*mat.m[0][j] + m[i][1]*mat.m[1][j] + m[i][2]*mat.m[2][j]; + } + } + + memcpy(m, tmp.m, 9*sizeof(float)); +} + +void Matrix3x3::operator *=(float scalar) { + float *dst = (float*)m; + + for(int i=0; i<9; i++) *dst++ *= scalar; +} + + +void Matrix3x3::ResetIdentity() { + memset(m, 0, 9 * sizeof(float)); + m[0][0] = m[1][1] = m[2][2] = 1.0f; +} + +void Matrix3x3::Translate(float x, float y) { + Matrix3x3 tmp( 1, 0, 0, + 0, 1, 0, + x, y, 1 ); + *this *= tmp; +} + +void Matrix3x3::Rotate(float angle) { + Matrix3x3 tmp( fcos(angle), fsin(angle), 0, + -fsin(angle), fcos(angle), 0, + 0, 0, 1 ); + *this *= tmp; +} + +void Matrix3x3::Scale(float x, float y) { + Matrix3x3 tmp( x, 0, 0, + 0, y, 0, + 0, 0, 1); + + *this *= tmp; +} + +void Matrix3x3::SetTranslation(float x, float y) { + Matrix3x3( 1, 0, 0, + 0, 1, 0, + x, y, 1 ); +} + +void Matrix3x3::SetRotation(float angle) { + Matrix3x3( fcos(angle), fsin(angle), 0, + -fsin(angle), fcos(angle), 0, + 0, 0, 1 ); +} + +void Matrix3x3::SetScaling(float x, float y) { + Matrix3x3( x, 0, 0, + 0, y, 0, + 0, 0, 1 ); +} + +void Matrix3x3::SetColumnVector(const Vector3 &vec, int columnindex) { + m[columnindex][0] = vec.x; + m[columnindex][1] = vec.y; + m[columnindex][2] = vec.z; +} + +void Matrix3x3::SetRowVector(const Vector3 &vec, int rowindex) { + m[0][rowindex] = vec.x; + m[1][rowindex] = vec.y; + m[2][rowindex] = vec.z; +} + +Vector3 Matrix3x3::GetColumnVector(int columnindex) const { + return Vector3(m[columnindex][0], m[columnindex][1], m[columnindex][2]); +} + +Vector3 Matrix3x3::GetRowVector(int rowindex) const { + return Vector3(m[0][rowindex], m[1][rowindex], m[2][rowindex]); +} + +void Matrix3x3::Transpose() { + Matrix3x3 mat = *this; + + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + m[i][j] = mat.m[j][i]; + } + } +} + +Matrix3x3 Matrix3x3::Transposed() const { + Matrix3x3 mat; + + for(int i=0; i<3; i++) { + for(int j=0; j<3; j++) { + mat.m[i][j] = m[j][i]; + } + } + + return mat; +} + + +void Matrix3x3::OrthoNormalize() { + Vector3 i, j, k; + i = GetRowVector(0); + j = GetRowVector(1); + k = GetRowVector(2); + + i = CrossProduct(j, k); + j = CrossProduct(k, i); + k = CrossProduct(i, j); + + SetRowVector(i, 0); + SetRowVector(j, 1); + SetRowVector(k, 2); +} + +Matrix3x3 Matrix3x3::OrthoNormalized() { + Vector3 i, j, k; + i = GetRowVector(0); + j = GetRowVector(1); + k = GetRowVector(2); + + i = CrossProduct(j, k); + j = CrossProduct(k, i); + k = CrossProduct(i, j); + + Matrix3x3 newmat; + newmat.SetRowVector(i, 0); + newmat.SetRowVector(j, 1); + newmat.SetRowVector(k, 2); + + return newmat; +} + + + +// ----------- Ray implementation -------------- +Ray::Ray() { + Origin = Vector3(0.0f, 0.0f, 0.0f); + Direction = Vector3(0.0f, 0.0f, 1.0f); + Energy = 1.0f; + CurrentIOR = 1.0f; +} + +Ray::Ray(const Vector3 &origin, const Vector3 &direction) { + Origin = origin; + Direction = direction; +} + +// ----------- Base implementation -------------- +Base::Base() { + i = Vector3(1, 0, 0); + j = Vector3(0, 1, 0); + k = Vector3(0, 0, 1); +} + +Base::Base(const Vector3 &i, const Vector3 &j, const Vector3 &k) { + this->i = i; + this->j = j; + this->k = k; +} + +Base::Base(const Vector3 &dir, bool LeftHanded) { + k = dir; + j = VECTOR3_J; + i = CrossProduct(j, k); + j = CrossProduct(k, i); +} + + +void Base::Rotate(float x, float y, float z) { + Matrix4x4 RotMat; + RotMat.SetRotation(x, y, z); + i.Transform(RotMat); + j.Transform(RotMat); + k.Transform(RotMat); +} + +void Base::Rotate(const Vector3 &axis, float angle) { + Quaternion q; + q.SetRotation(axis, angle); + i.Transform(q); + j.Transform(q); + k.Transform(q); +} + +void Base::Rotate(const Matrix4x4 &mat) { + i.Transform(mat); + j.Transform(mat); + k.Transform(mat); +} + +void Base::Rotate(const Quaternion &quat) { + i.Transform(quat); + j.Transform(quat); + k.Transform(quat); +} + +Matrix3x3 Base::CreateRotationMatrix() const { + return Matrix3x3( i.x, i.y, i.z, + j.x, j.y, j.z, + k.x, k.y, k.z); +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/common/n3dmath.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/n3dmath.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,425 @@ +#ifndef _N3DMATH_H_ +#define _N3DMATH_H_ + +// - n3dmath.h - +// Nuc3D 2 Header File +// written by: John Tsiombikas (10 Sep 2002) +// Last Modification: 14 April 2002 +// --------------------------- +// Mathematical stuff + +#include +#include + +#ifdef NUC3D_VER_DIRECT3D +#include "d3d8.h" // Direct3D type definitions (D3DMATRIX) +#endif //NUC3D_VER_DIRECT3D + +// forward declarations +class Matrix4x4; +class Matrix3x3; +class Vector3; +class Vector2; +class Vector4; +class Quaternion; + +// mathematical constants +const float Pi = 3.1415926535897932f; +const float TwoPi = 6.2831853071795865f;// Pi * 2.0f; +const float HalfPi = 1.5707963267948965f; //Pi * 0.5f; +const float QuarterPi = 0.7853981633974483f; //Pi * 0.25f; +const float ThreeQuartersPi = 2.3561944901923450f; //QuarterPi * 3.0f; + +const float XSmallNumber = 1.e-8f; +const float SmallNumber = 1.e-4f; + +// basis vectors +#define VECTOR3_I (Vector3(1.0f, 0.0f, 0.0f)) +#define VECTOR3_J (Vector3(0.0f, 1.0f, 0.0f)) +#define VECTOR3_K (Vector3(0.0f, 0.0f, 1.0f)) + +#define VECTOR2_I (Vector2(1.0f, 0.0f)) +#define VECTOR2_J (Vector2(0.0f, 1.0f)) + +// angle conversion +#define DEGTORAD(a) (Pi * (a) / 180) +#define RADTODEG(a) ((a) * 180 / Pi) + + + +// ------------- Vector3 class ------------- + +#ifdef NUC3D_VER_DIRECT3D // if we are using Direct3D version + +class Vector3 : public D3DVECTOR { +public: + +#else // not D3D + +class Vector3 { +public: + float x, y, z; + +#endif //NUC3D_VER_DIRECT3D + + Vector3(); + Vector3(float x, float y, float z); + + inline float DotProduct(const Vector3 &vec) const; + inline Vector3 CrossProduct(const Vector3 &vec) const; + + inline Vector3 operator +(const Vector3 &vec) const; + inline Vector3 operator -(const Vector3 &vec) const; + inline Vector3 operator *(float scalar) const; + inline Vector3 operator /(float scalar) const; + inline void operator +=(const Vector3 &vec); + inline void operator -=(const Vector3 &vec); + inline void operator *=(float scalar); + inline void operator /=(float scalar); + inline Vector3 operator -() const; // unary minus for inversion + + inline bool operator >(const Vector3 &vec) const; + inline bool operator <(const Vector3 &vec) const; + inline bool operator >(float len) const; + inline bool operator <(float len) const; + inline bool operator ==(const Vector3 &vec) const; + inline bool operator ==(float len) const; + + inline operator Vector2() const; + inline operator Vector4() const; + + inline float Length() const; + inline float LengthSq() const; + + inline void Normalize(); + inline Vector3 Normalized() const; + + inline Vector3 Reflection(const Vector3 &normal) const; + Vector3 Refraction(const Vector3 &normal, float FromIOR, float ToIOR) const; + + void Transform(const Matrix4x4 &mat); // transform a vector using a transformation matrix + void Transform(const Quaternion &quat); // transform by a quaternion + + // Direct transformations on the vector + void Translate(float x, float y, float z); + void Rotate(float x, float y, float z); + void Rotate(const Vector3 &axis, float angle); + void Scale(float x, float y, float z); + + float &operator [](int index); + + friend std::ostream &operator <<(std::ostream &out, const Vector3 &vec); +}; + +inline float DotProduct(const Vector3 &vec1, const Vector3 &vec2); +inline Vector3 CrossProduct(const Vector3 &vec1, const Vector3 &vec2); + +////////////////////// 4-dimensional vectors //////////////////////////// +class Vector4 { +public: + float x, y, z, w; + + Vector4(); + Vector4(const Vector4 &vec); + Vector4(const Vector3 &vec); // create from a 3 dimensional vector setting w=1 + Vector4(float x, float y, float z, float w); + + float DotProduct(const Vector4 &vec) const; + Vector4 CrossProduct(const Vector4 &vec1, const Vector4 &vec2) const; + + Vector4 operator +(const Vector4 &vec) const; + Vector4 operator -(const Vector4 &vec) const; + Vector4 operator *(float scalar) const; + Vector4 operator /(float scalar) const; + void operator +=(const Vector4 &vec); + void operator -=(const Vector4 &vec); + void operator *=(float scalar); + void operator /=(float scalar); + Vector4 operator -() const; // unary minus for inversion + + bool operator >(const Vector4 &vec) const; + bool operator <(const Vector4 &vec) const; + bool operator >(float len) const; + bool operator <(float len) const; + bool operator ==(const Vector4 &vec) const; + bool operator ==(float len) const; + + operator Vector3() const; + + float Length() const; + float LengthSq() const; + + void Normalize(); + Vector4 Normalized() const; + + void Transform(const Matrix4x4 &mat); // transform a vector using a transformation matrix + + // Direct transformations on the vector + void Translate(float x, float y, float z, float w); + void Rotate(float x, float y, float z); + void Rotate(const Vector3 &axis, float angle); + void Scale(float x, float y, float z, float w); + + float &operator [](int index); + + friend std::ostream &operator <<(std::ostream &out, const Vector3 &vec); +}; + +float DotProduct(const Vector4 &vec1, const Vector4 &vec2); +Vector4 CrossProduct(const Vector4 &vec1, const Vector4 &vec2, const Vector4 &vec3); + +/////////////////////////// + +class Vector2 { +public: + float x, y; + + Vector2(); + Vector2(const Vector2 &vec); + Vector2(float x, float y); + + float DotProduct(const Vector2 &vec) const; + //Vector2 CrossProduct(const Vector2 &vec) const; + + Vector2 operator +(const Vector2 &vec) const; + Vector2 operator -(const Vector2 &vec) const; + Vector2 operator *(float scalar) const; + Vector2 operator /(float scalar) const; + void operator +=(const Vector2 &vec); + void operator -=(const Vector2 &vec); + void operator *=(float scalar); + void operator /=(float scalar); + Vector2 operator -() const; // unary minus for inversion + + bool operator >(const Vector2 &vec) const; + bool operator <(const Vector2 &vec) const; + bool operator >(float len) const; + bool operator <(float len) const; + bool operator ==(const Vector2 &vec) const; + bool operator ==(float len) const; + + operator Vector3() const; + + float Length() const; + float LengthSq() const; + + void Normalize(); + Vector2 Normalized() const; + + Vector2 Reflection(const Vector2 &normal) const; + Vector2 Refraction(const Vector2 &normal, float FromIOR, float ToIOR) const; + + void Transform(const Matrix3x3 &mat); // transform a vector using a transformation matrix + + // Direct transformations on the vector + void Translate(float x, float y); + void Rotate(float angle); + void Scale(float x, float y); + + float &operator [](int index); + + friend std::ostream &operator <<(std::ostream &out, const Vector2 &vec); +}; + +float DotProduct(const Vector3 &vec1, const Vector3 &vec2); + + +struct Vector2i { + int x, y; + + Vector2i(int x=0, int y=0) {this->x = x; this->y = y;} +}; + + +////////////////// Quaternion /////////////////////// + +class Quaternion { +public: + float s; + Vector3 v; + + Quaternion(); + Quaternion(float s, const Vector3 &v); + Quaternion(float s, float x, float y, float z); + + Quaternion operator +(const Quaternion &quat) const; + Quaternion operator -(const Quaternion &quat) const; + Quaternion operator -() const; + Quaternion operator *(const Quaternion &quat) const; + + void operator +=(const Quaternion &quat); + void operator -=(const Quaternion &quat); + void operator *=(const Quaternion &quat); + + void ResetIdentity(); + + Quaternion Conjugate() const; + + float Length() const; + float LengthSq() const; + + void Normalize(); + Quaternion Normalized() const; + + Quaternion Inverse() const; + + void SetRotation(const Vector3 &axis, float angle); + void Rotate(const Vector3 &axis, float angle); + + Matrix3x3 GetRotationMatrix() const; +}; + + + +////////////////////////// Matrices ////////////////////////////// + +#ifdef NUC3D_VER_DIRECT3D // if we are using Direct3D version + +class Matrix4x4 : public D3DMATRIX { +public: + +#else // Software or OpenGL version + +class Matrix4x4 { +public: + float m[4][4]; + +#endif //NUC3D_VER_DIRECT3D + + Matrix4x4(); + Matrix4x4(const Matrix4x4 &mat); + Matrix4x4(const Matrix3x3 &mat); + Matrix4x4( float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33 ); + + // basic operations on matrices + Matrix4x4 operator +(const Matrix4x4 &mat) const; + Matrix4x4 operator -(const Matrix4x4 &mat) const; + Matrix4x4 operator *(const Matrix4x4 &mat) const; + Matrix4x4 operator *(float scalar) const; + void operator +=(const Matrix4x4 &mat); + void operator -=(const Matrix4x4 &mat); + void operator *=(const Matrix4x4 &mat); + void operator *=(float scalar); + + void ResetIdentity(); + + // concatenate various transformation matrices with our current matrix + void Translate(float x, float y, float z); + void Rotate(float x, float y, float z); + void Rotate(const Vector3 &axis, float rads); + void Scale(float x, float y, float z); + + // set the matrix to a specific transformation matrix + void SetTranslation(float x, float y, float z); + void SetRotation(float x, float y, float z); + void SetRotation(const Vector3 &axis, float angle); + void SetScaling(float x, float y, float z); + + // row and column accessors + void SetColumnVector(const Vector4 &vec, int columnindex); + void SetRowVector(const Vector4 &vec, int rowindex); + Vector4 GetColumnVector(int columnindex) const; + Vector4 GetRowVector(int rowindex) const; + + // other operations on matrices + void Transpose(); + Matrix4x4 Transposed() const; + + float Determinant() const; + Matrix4x4 Adjoint() const; + Matrix4x4 Inverse() const; +}; + + +////////////////// Matrix3x3 ////////////////// +class Matrix3x3 { +public: + float m[3][3]; + + Matrix3x3(); + Matrix3x3(const Matrix3x3 &mat); + Matrix3x3( float m00, float m01, float m02, + float m10, float m11, float m12, + float m20, float m21, float m22 ); + + // basic operations on matrices + Matrix3x3 operator +(const Matrix3x3 &mat) const; + Matrix3x3 operator -(const Matrix3x3 &mat) const; + Matrix3x3 operator *(const Matrix3x3 &mat) const; + Matrix3x3 operator *(float scalar) const; + void operator +=(const Matrix3x3 &mat); + void operator -=(const Matrix3x3 &mat); + void operator *=(const Matrix3x3 &mat); + void operator *=(float scalar); + + void ResetIdentity(); + + // concatenate various transformation matrices with our current matrix + void Translate(float x, float y); + void Rotate(float angle); + void Scale(float x, float y); + + // set the matrix to a specific transformation matrix + void SetTranslation(float x, float y); + void SetRotation(float angle); + void SetScaling(float x, float y); + + // row and column accessors + void SetColumnVector(const Vector3 &vec, int columnindex); + void SetRowVector(const Vector3 &vec, int rowindex); + Vector3 GetColumnVector(int columnindex) const; + Vector3 GetRowVector(int rowindex) const; + + // other operations on matrices + void Transpose(); + Matrix3x3 Transposed() const; + + void OrthoNormalize(); + Matrix3x3 OrthoNormalized(); + + //float Determinant() const; // NYI + //Matrix3x3 Adjoint() const; + //Matrix3x3 Inverse() const; +}; + +///////////////// ray ///////////////// + +class Ray { +public: + Vector3 Origin; + Vector3 Direction; + float Energy; + float CurrentIOR; + + Ray(); + Ray(const Vector3 &origin, const Vector3 &direction); +}; + +// a coordinate system basis +class Base { +public: + Vector3 i, j, k; + + Base(); + Base(const Vector3 &i, const Vector3 &j, const Vector3 &k); + Base(const Vector3 &dir, bool LeftHanded=true); + + void Rotate(float x, float y, float z); + void Rotate(const Vector3 &axis, float angle); + void Rotate(const Matrix4x4 &mat); + void Rotate(const Quaternion &quat); + + Matrix3x3 CreateRotationMatrix() const; +}; + + + +float frand(float range); + + +#include "n3dmath.inl" + +#endif // _N3DMATH_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/common/n3dmath.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/n3dmath.inl Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,116 @@ +float Vector3::DotProduct(const Vector3 &vec) const { + return x * vec.x + y * vec.y + z * vec.z; +} + +float DotProduct(const Vector3 &vec1, const Vector3 &vec2) { + return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z; +} + +Vector3 Vector3::CrossProduct(const Vector3 &vec) const { + return Vector3(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x); +} + +Vector3 CrossProduct(const Vector3 &vec1, const Vector3 &vec2) { + return Vector3(vec1.y * vec2.z - vec1.z * vec2.y, vec1.z * vec2.x - vec1.x * vec2.z, vec1.x * vec2.y - vec1.y * vec2.x); +} + +Vector3 Vector3::operator +(const Vector3 &vec) const { + return Vector3(x + vec.x, y + vec.y, z + vec.z); +} + +Vector3 Vector3::operator -(const Vector3 &vec) const { + return Vector3(x - vec.x, y - vec.y, z - vec.z); +} + +Vector3 Vector3::operator *(float scalar) const { + return Vector3(x * scalar, y * scalar, z * scalar); +} + +Vector3 Vector3::operator /(float scalar) const { + return Vector3(x / scalar, y / scalar, z / scalar); +} + +void Vector3::operator +=(const Vector3 &vec) { + x += vec.x; + y += vec.y; + z += vec.z; +} + +void Vector3::operator -=(const Vector3 &vec) { + x -= vec.x; + y -= vec.y; + z -= vec.z; +} + +void Vector3::operator *=(float scalar) { + x *= scalar; + y *= scalar; + z *= scalar; +} + +void Vector3::operator /=(float scalar) { + x /= scalar; + y /= scalar; + z /= scalar; +} + +Vector3 Vector3::operator -() const { + return Vector3(-x, -y, -z); +} + +bool Vector3::operator >(const Vector3 &vec) const { + return LengthSq() > vec.LengthSq(); +} + +bool Vector3::operator <(const Vector3 &vec) const { + return LengthSq() < vec.LengthSq(); +} + +bool Vector3::operator >(float len) const { + return LengthSq() > len; +} + +bool Vector3::operator <(float len) const { + return LengthSq() < len; +} + +bool Vector3::operator ==(const Vector3 &vec) const { + return ((*this - vec).Length() < XSmallNumber); +} + +bool Vector3::operator ==(float len) const { + return ((this->Length() - len) < XSmallNumber); +} + +Vector3::operator Vector2() const { + return Vector2(x, y); +} + +Vector3::operator Vector4() const { + return Vector4(x, y, z, 1.0f); +} + + +float Vector3::Length() const { + return (float)sqrt(x*x + y*y + z*z); +} + +float Vector3::LengthSq() const { + return x*x + y*y + z*z; +} + +void Vector3::Normalize() { + float len = (float)sqrt(x*x + y*y + z*z); + x /= len; + y /= len; + z /= len; +} + +Vector3 Vector3::Normalized() const { + float len = (float)sqrt(x*x + y*y + z*z); + return Vector3(x / len, y / len, z / len); +} + +Vector3 Vector3::Reflection(const Vector3 &normal) const { + return normal * this->DotProduct(normal) * 2.0f - *this; +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/common/timing.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/timing.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,46 @@ +#include "timing.h" + +Timer::Timer() { + QueryPerformanceFrequency(&freq); + PauseTime.QuadPart = 0; + paused = false; +} + +void Timer::Start() { + PauseTime.QuadPart = 0; + QueryPerformanceCounter(&start); +} + +void Timer::Stop() { + QueryPerformanceCounter(&LastStop); +} + +void Timer::Resume() { + LARGE_INTEGER resume; + + QueryPerformanceCounter(&resume); + + PauseTime.QuadPart += resume.QuadPart - LastStop.QuadPart; +} + + +unsigned long Timer::GetTicks() const { + LARGE_INTEGER ticks; + + QueryPerformanceCounter(&ticks); + return (unsigned long)(ticks.QuadPart - start.QuadPart - PauseTime.QuadPart); +} + +unsigned long Timer::GetSec() const { + LARGE_INTEGER ticks; + + QueryPerformanceCounter(&ticks); + return (unsigned long)((ticks.QuadPart - start.QuadPart - PauseTime.QuadPart)/freq.QuadPart); +} + +unsigned long Timer::GetMilliSec() const { + LARGE_INTEGER ticks; + + QueryPerformanceCounter(&ticks); + return (unsigned long)((ticks.QuadPart - start.QuadPart - PauseTime.QuadPart)/(freq.QuadPart/1000)); +} diff -r 000000000000 -r 1cffe3409164 src/common/timing.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/timing.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,24 @@ +#ifndef _TIMING_H_ +#define _TIMING_H_ + +#include + +class Timer { +private: + LARGE_INTEGER start, freq; + LARGE_INTEGER PauseTime, LastStop; + bool paused; + +public: + + Timer(); + + void Start(); + void Stop(); + void Resume(); + unsigned long GetTicks() const; + unsigned long GetMilliSec() const; + unsigned long GetSec() const; +}; + +#endif //_TIMING_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/common/typedefs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/typedefs.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,38 @@ +#ifndef _TYPEDEFS_H_ +#define _TYPEDEFS_H_ + +typedef char int8; +typedef short int16; +typedef long int32; + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned long uint32; + +#ifdef _MSC_VER +typedef __int64 int64; +typedef unsigned __int64 uint64; +#else +typedef unsigned long long uint64; +typedef long long int64; +#endif // _MSC_VER + +typedef uint8 BYTE; +typedef uint16 WORD; +typedef uint32 DWORD; + +typedef uint8 byte; +typedef uint16 word; +typedef uint32 dword; +typedef uint64 qword; + +// Define NULL pointer value +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif //__cplusplus +#endif //NULL + +#endif //_TYPEDEFS_H_ diff -r 000000000000 -r 1cffe3409164 src/demo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/demo.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,242 @@ +#include "nwt/startup.h" +#include "nwt/nucwin.h" +#include "3deng/3deng.h" +#include "demosystem/demosys.h" +#include "fmod.h" + +// parts +#include "beginpart.h" +#include "dungeonpart.h" +#include "treepart.h" +#include "tunnelpart.h" +#include "hellpart.h" +#include "greetspart.h" +#include "demonpart.h" + +int ScreenX; +int ScreenY; + +Widget *win; +Engine3D eng3d; +GraphicsContext *gc; +DemoSystem *demo; +FMUSIC_MODULE *mod; + + +// parts +DungeonPart *dungeonpart; +BeginPart *beginpart; +TreePart *treepart; +TunnelPart *tunnelpart; +HellPart *hellpart; +GreetsPart *greetspart; +DemonPart *demonpart; + +bool Init(); +void MainLoop(); +void CleanUp(); +int KeyHandler(Widget *win, int key); +int CloseHandler(Widget *win, int arg); +int MouseHandler(Widget *win, int x, int y, bool left, bool middle, bool right); +int WheelHandler(Widget *win, int x, int y, int rot); + + +int main() { + + win = NWCreateWindow("The Lab Demos", NWT_CENTERX, NWT_CENTERY, 100, 50, 0); + SetMainLoopFunc(MainLoop); + SetHandler(HANDLER_KEY, KeyHandler); + SetHandler(HANDLER_CLOSE, CloseHandler); + + SetHandler(HANDLER_MOUSE, (HandlerFunctionPtr)MouseHandler); + SetHandler(HANDLER_WHEEL, (HandlerFunctionPtr)WheelHandler); + + + if(!Init()) return 0; + + return NWMainLoop(RealTimeLoop); +} + +bool Init() { + + ContextInitParameters cip; + try { + cip = eng3d.LoadContextParamsConfigFile("n3dinit.conf"); + gc = eng3d.CreateGraphicsContext(win, 0, &cip); + } + catch(EngineInitException except) { + MessageBox(win, except.GetReason().c_str(), "Fatal Error", MB_OK | MB_ICONSTOP); + return false; + } + ScreenX = cip.x; + ScreenY = cip.y; + NWResize(win, ScreenX, ScreenY); + NWResizeClientArea(win, WS_OVERLAPPEDWINDOW); + + ShowCursor(false); + + // Loading pics.... + Texture *loading[9]; + loading[0] = gc->texman->AddTexture("data/textures/Loading/loading0.jpg"); + loading[1] = gc->texman->AddTexture("data/textures/Loading/loading1.jpg"); + loading[2] = gc->texman->AddTexture("data/textures/Loading/loading2.jpg"); + loading[3] = gc->texman->AddTexture("data/textures/Loading/loading3.jpg"); + loading[4] = gc->texman->AddTexture("data/textures/Loading/loading4.jpg"); + loading[5] = gc->texman->AddTexture("data/textures/Loading/loading5.jpg"); + loading[6] = gc->texman->AddTexture("data/textures/Loading/loading6.jpg"); + loading[7] = gc->texman->AddTexture("data/textures/Loading/loading7.jpg"); + loading[8] = gc->texman->AddTexture("data/textures/Loading/loading8.jpg"); + + demo = new DemoSystem(gc); + SceneLoader::SetGraphicsContext(gc); + + Object *quad = new Object(gc); + quad->CreatePlane(4.0f, 0); + quad->Scale(1.3333f, 1.0f, 1.0f); + quad->material = Material(1.0f, 1.0f, 1.0f); + + Matrix4x4 ViewMat; + ViewMat.Translate(0.0f, 0.0f, 3.6f); + gc->SetViewMatrix(ViewMat); + + gc->SetZBuffering(false); + gc->SetLighting(false); + + quad->material.SetTexture(loading[0], TextureMap); + quad->Render(); + gc->Flip(); + beginpart = new BeginPart(gc); + beginpart->SetTimingRel(0, 11000); + demo->AddPart(beginpart); + + quad->material.SetTexture(loading[1], TextureMap); + quad->Render(); + gc->Flip(); + dungeonpart = new DungeonPart(gc); + dungeonpart->SetTimingRel(11000, 75000); + demo->AddPart(dungeonpart); + + quad->material.SetTexture(loading[2], TextureMap); + quad->Render(); + gc->Flip(); + treepart = new TreePart(gc); + treepart->SetTimingRel(85900, 40000); + demo->AddPart(treepart); + + quad->material.SetTexture(loading[3], TextureMap); + quad->Render(); + gc->Flip(); + tunnelpart = new TunnelPart(gc); + tunnelpart->SetTimingRel(125900, 30000); + demo->AddPart(tunnelpart); + + quad->material.SetTexture(loading[4], TextureMap); + quad->Render(); + gc->Flip(); + hellpart = new HellPart(gc); + hellpart->SetTimingRel(155900, 40000); + demo->AddPart(hellpart); + + quad->material.SetTexture(loading[5], TextureMap); + quad->Render(); + gc->Flip(); + greetspart = new GreetsPart(gc); + greetspart->SetTimingRel(196000, 12000); + demo->AddPart(greetspart); + + quad->material.SetTexture(loading[6], TextureMap); + quad->Render(); + gc->Flip(); + demonpart = new DemonPart(gc); + demonpart->SetTimingRel(208000, 2000); + demo->AddPart(demonpart); + + quad->material.SetTexture(loading[7], TextureMap); + quad->Render(); + gc->Flip(); + FSOUND_SetHWND(win); + FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND); + FSOUND_SetBufferSize(200); + FSOUND_Init(44100, 32, FSOUND_INIT_GLOBALFOCUS); + mod = FMUSIC_LoadSong("data/GOTH03.XM"); + FMUSIC_SetMasterVolume(mod, 250); + + quad->material.SetTexture(loading[8], TextureMap); + quad->Render(); + gc->Flip(); + gc->SetBackfaceCulling(true); + gc->SetZBuffering(true); + gc->SetLighting(true); + + Sleep(800); + + demo->Run(); + + FMUSIC_PlaySong(mod); + + return true; +} + +void MainLoop() { + demo->Update(); + gc->Flip(); +} + +void CleanUp() { + ShowCursor(true); + FMUSIC_FreeSong(mod); + FSOUND_Close(); + delete demo; +} + +///////// handlers ///////// +int KeyHandler(Widget *win, int key) { + switch(key) { + case VK_ESCAPE: + NWCloseWindow(win); + break; + + } + return 0; +} + +int CloseHandler(Widget *win, int arg) { + CleanUp(); + return 0; +} + +int WheelHandler(Widget *win, int x, int y, int rot) { +/* float tr = rot > 0 ? 0.05f : -0.05f; + + Camera *cam = const_cast(demo->GetActivePath()->GetScene()->GetActiveCamera()); + cam->SetCameraPath(0, 0, 0, 0); + + cam->Zoom(tr); +*/ + return 0; +} + + +int MouseHandler(Widget *win, int x, int y, bool left, bool middle, bool right) { +/* static POINT PrevPos; + POINT MoveDiff; + + if(right) { + MoveDiff.x = x - PrevPos.x; + MoveDiff.y = y - PrevPos.y; + float xangle = (float)MoveDiff.x / 50.0f; + float dy = (float)MoveDiff.y; + + Camera *cam = const_cast(demo->GetActivePath()->GetScene()->GetActiveCamera()); + cam->SetCameraPath(0, 0, 0, 0); + + cam->Rotate(0.0f, xangle, 0.0f); + cam->SetPosition(cam->GetPosition() + Vector3(0.0f, dy, 0.0f)); + } + + + PrevPos.x = x; + PrevPos.y = y; +*/ + return 0; +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/demonpart.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/demonpart.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,40 @@ +#include "demonpart.h" +#include "nwt/widget.h" +#include "fmod.h" + +extern Widget *win; +extern FMUSIC_MODULE *mod; + +DemonPart::DemonPart(GraphicsContext *gc) { + this->gc = gc; + + //SceneLoader::SetNormalFileSaving(true); + SceneLoader::SetDataPath("data/textures/"); + SceneLoader::LoadScene("data/geometry/demon.3ds", &scene); + + curve = scene->GetCurve("Line01"); + curve->SetArcParametrization(true); + cam = scene->GetCamera("Camera01"); + cam->SetCameraPath(curve, 0, 0, 1500); +} + +DemonPart::~DemonPart() { + delete scene; +} + +void DemonPart::MainLoop() { + dword msec = timer.GetMilliSec(); + float t = msec / 1000.0f; + + FMUSIC_SetMasterVolume(mod, (1500 - msec) / 6); + + gc->Clear(0); + gc->ClearZBufferStencil(1.0f, 0); + + if(t > 1.5f) { + PostMessage(win, WM_CLOSE, 0, 0); + } + + cam->FollowPath(msec); + scene->Render(); +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/demonpart.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/demonpart.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,18 @@ +#ifndef _DEMONPART_H_ +#define _DEMONPART_H_ + +#include "demosystem/demosys.h" + +class DemonPart : public Part { +private: + Camera *cam; + Curve *curve; + +public: + DemonPart(GraphicsContext *gc); + ~DemonPart(); + + void MainLoop(); +}; + +#endif // _DEMONPART_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/demosystem/demosys.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/demosystem/demosys.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,212 @@ +#include "demosys.h" + +/////////////// Part base class implementation /////////////// + +Part::Part() { + gc = 0; + + rmode = RenderModeNormal; + RenderTexture = 0; + + SetTimingAbs(0, 0); + paused = false; +} + +void Part::SetGraphicsContext(GraphicsContext *gc) { + this->gc = gc; +} + +GraphicsContext *Part::GetGraphicsContext() { + return gc; +} + +void Part::SetTimingAbs(dword start, dword end) { + StartTime = start; + EndTime = end; + Duration = EndTime - StartTime; +} + +void Part::SetTimingRel(dword start, dword dur) { + StartTime = start; + Duration = dur; + EndTime = StartTime + Duration; +} + +void Part::Pause() { + if(paused) return; + timer.Stop(); + paused = true; +} + +void Part::Resume() { + if(!paused) return; + timer.Resume(); + paused = false; +} + +dword Part::GetStartTime() const { + return StartTime; +} + +dword Part::GetEndTime() const { + return EndTime; +} + +dword Part::GetDuration() const { + return Duration; +} + +dword Part::GetTimePosition() const { + return timer.GetMilliSec(); +} + +float Part::GetParametricPosition() const { + return (float)timer.GetMilliSec() / (float)Duration; +} + +void Part::SetRenderMode(RenderMode rmode) { + this->rmode = rmode; +} + +void Part::SetRenderTexture(Texture *tex) { + RenderTexture = tex; +} + +RenderMode Part::GetRenderMode() const { + return rmode; +} + +Texture *Part::GetRenderTexture() const { + return RenderTexture; +} + + +void Part::Launch() { + timer.Start(); +} + +void Part::ShutDown() { + // do nothing +} + +Scene *Part::GetScene() { + return scene; +} + + +/////////////// main Demo System class implementation /////////////// + +DemoSystem::DemoSystem(GraphicsContext *gc) { + this->gc = gc; + state = DemoStateStopped; +} + +void DemoSystem::AddPart(Part *part) { + + if(state != DemoStateStopped) return; + + if(!part->GetGraphicsContext()) part->SetGraphicsContext(gc); + + parts.push_back(part); + inactive.push_back(part); +} + +Part *DemoSystem::GetActivePart() { + return *active.begin(); +} + +//// demo flow control //// + +// Run demo from the beggining +void DemoSystem::Run() { + + if(state != DemoStateStopped) return; + + state = DemoStateRunning; + timer.Start(); +} + +// Stop the execution of the demo, discard any sequencing information +void DemoSystem::Stop() { + + if(state == DemoStateStopped) return; + + while(active.size()) { + active.erase(active.begin()); + } + + inactive = parts; + + state = DemoStateStopped; +} + +// Pause the demo (freeze the timers) +void DemoSystem::Pause() { + + if(state != DemoStateRunning) return; + + std::list::iterator iter = active.begin(); + while(iter != active.end()) { + (*iter++)->Pause(); + } + timer.Stop(); + + state = DemoStatePaused; +} + +void DemoSystem::Resume() { + + if(state != DemoStatePaused) return; + + std::list::iterator iter = active.begin(); + while(iter != active.end()) { + (*iter++)->Resume(); + } + timer.Resume(); + + state = DemoStateRunning; +} + + +void DemoSystem::Update() { + + if(state != DemoStateRunning) return; + + dword time = timer.GetMilliSec(); + + // Check if there are any inactive parts to launch + std::list::iterator iter = inactive.begin(); + while(iter != inactive.end()) { + if(time >= (*iter)->GetStartTime()) { + (*iter)->Launch(); + active.push_back(*iter); + iter = inactive.erase(iter); + } else { + iter++; + } + } + + // check if there are any parts to close and close them, and run the valid ones + iter = active.begin(); + while(iter != active.end()) { + if(time >= (*iter)->GetEndTime()) { + (*iter)->ShutDown(); + iter = active.erase(iter); + } else { + // run the part + if((*iter)->GetRenderMode() == RenderModeTexture) { + gc->SetRenderTarget((*iter)->GetRenderTexture(), (Texture*)0); + gc->Clear(0); + gc->ClearZBufferStencil(1.0f, 0); + } + + (*iter)->MainLoop(); + + if((*iter)->GetRenderMode() == RenderModeTexture) { + gc->ResetRenderTarget(); + } + + iter++; + } + } +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/demosystem/demosys.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/demosystem/demosys.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,97 @@ +#ifndef _DEMOSYS_H_ +#define _DEMOSYS_H_ + +#include +#include "typedefs.h" +#include "timing.h" + +#ifdef NUC3D_API_OPENGL +#include "n3dgl/nuc3dhw.h" +#else +#include "3deng/3deng.h" +#endif + +enum {TIMETYPE_ABSOLUTE, TIMETYPE_RELATIVE}; +enum RenderMode {RenderModeNormal, RenderModeTexture}; + +// ----- Abstract Base Class Part ----- +class Part { +protected: + GraphicsContext *gc; + Scene *scene; // REMOVE + + dword StartTime, EndTime, Duration; // in milliseconds + Timer timer; // local part timer + + Texture *RenderTexture; + RenderMode rmode; + + bool paused; + +public: + + Part(); + + virtual void SetGraphicsContext(GraphicsContext *gc); + virtual GraphicsContext *GetGraphicsContext(); + + virtual void SetTimingAbs(dword start, dword end); + virtual void SetTimingRel(dword start, dword dur); + virtual void Pause(); + virtual void Resume(); + + virtual dword GetStartTime() const; + virtual dword GetEndTime() const; + virtual dword GetDuration() const; + virtual dword GetTimePosition() const; + virtual float GetParametricPosition() const; + + virtual void SetRenderMode(RenderMode rmode); + virtual void SetRenderTexture(Texture *tex); + + virtual RenderMode GetRenderMode() const; + virtual Texture *GetRenderTexture() const; + + virtual void Launch(); + virtual void ShutDown(); + virtual void MainLoop() = 0; + + virtual Scene *GetScene(); +}; + +enum DemoState {DemoStateRunning, DemoStateStopped, DemoStatePaused}; + +class DemoSystem { +private: + GraphicsContext *gc; + + std::list parts; // list of all parts + std::list active; // currently running + std::list inactive; // waiting to run + + Timer timer; // global demo timer + DemoState state; + +public: + + DemoSystem(GraphicsContext *gc); + + void AddPart(Part *part); + Part *GetActivePart(); + + void Run(); + void Pause(); + void Resume(); + void Stop(); + + void Update(); + + int LoadTiming(const char *filename); +}; + + +/////////////// exceptions ////////////// +class InvalidParam{}; + + +#endif //_DEMOSYS_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/dungeonpart.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dungeonpart.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,321 @@ +#include "dungeonpart.h" +#include "d3dx8.h" + +DungeonPart::DungeonPart(GraphicsContext *gc) { + + this->gc = gc; + + SceneLoader::SetNormalFileSaving(true); + SceneLoader::SetDataPath("data/textures/"); + SceneLoader::LoadScene("data/geometry/scene2.3ds", &scene); + + // setup camera paths + CamPath[0] = scene->GetCurve("cpath01"); + CamPath[1] = scene->GetCurve("cpath02"); + CamPath[2] = scene->GetCurve("cpath03"); + TargPath[0] = scene->GetCurve("ctarget01"); + TargPath[1] = scene->GetCurve("ctarget03"); + + CamPath[0]->SetArcParametrization(true); + CamPath[1]->SetArcParametrization(true); + CamPath[2]->SetArcParametrization(true); + TargPath[0]->SetArcParametrization(true); + TargPath[1]->SetArcParametrization(true); + + + cam[0] = scene->GetCamera("Camera01"); + cam[1] = scene->GetCamera("Camera02"); + cam[2] = scene->GetCamera("Camera03"); + cam[3] = scene->GetCamera("FreeCam"); + + cam[0]->SetCameraPath(CamPath[0], TargPath[0], 0, 40000); + cam[1]->SetCameraPath(CamPath[1], 0, 40000, 45000); + cam[2]->SetCameraPath(CamPath[2], TargPath[1], 45000, 75000); + + // get the lava crust under control + LavaCrust = scene->GetObject("Plane02"); + scene->RemoveObject(LavaCrust); + + // get the shadow-map walls under control + ShadowObj[0] = scene->GetObject("TunnelLigh"); + scene->RemoveObject(ShadowObj[0]); + ShadowObj[1] = scene->GetObject("TunnelLig0"); + scene->RemoveObject(ShadowObj[1]); + + // load the flame textures + for(int i=0; itexman->AddTexture(fname.c_str()); + } + + // get the flame objects and remove them from the scene (to take over the rendering) + for(int i=0; i<16; i++) { + char num[3]; + itoa(i, num, 10); + string name = string("Fire") + (i < 10 ? string("0") : string("")) + string(num); + + Flame[i] = scene->GetObject(name.c_str()); + scene->RemoveObject(Flame[i]); + } + + LightRays = scene->GetObject("LightRays"); + scene->RemoveObject(LightRays); + + Floor[0] = scene->GetObject("floor1"); + Floor[1] = scene->GetObject("floor2"); + Floor[2] = scene->GetObject("floor3"); + for(int i=0; i<3; i++) scene->RemoveObject(Floor[i]); + + Obj = scene->GetObject("DefSphere"); + scene->RemoveObject(Obj); + + mobj = new Object(gc); + mobj->GetTriMesh()->SetData(Obj->GetTriMesh()->GetVertexArray(), Obj->GetTriMesh()->GetTriangleArray(), Obj->GetTriMesh()->GetVertexCount(), Obj->GetTriMesh()->GetTriangleCount()); + + Obj->material.SetTexture(gc->texman->AddTexture("data/textures/rusty01.jpg"), TextureMap); + Obj->material.SetTexture(gc->texman->AddTexture("data/textures/refmap1.jpg"), EnvironmentMap); + + Obj->material.SetAmbient(Color(0.5f)); + Obj->material.SetDiffuse(Color(0.5f)); + Obj->material.SetSpecular(Color(175.0f / 256.0f, 95.0f / 256.0f, 17.0f / 256.0f)); + Obj->material.SetSpecularPower(90.0f); + Obj->material.SpecularEnable = true; + mobj->material = Obj->material; + + Obj->GetTriMesh()->ChangeMode(TriMeshDynamic); + mobj->GetTriMesh()->ChangeMode(TriMeshDynamic); + + Crystals[0] = scene->GetObject("Box114"); + Crystals[1] = scene->GetObject("Box115"); + Crystals[2] = scene->GetObject("Box116"); + Crystals[3] = scene->GetObject("Box117"); + Crystals[4] = scene->GetObject("Box118"); + + for(int i=0; i<5; i++) { + scene->RemoveObject(Crystals[i]); + } + + Name = new Object(gc); + Name->CreatePlane(1.7f, 0); + Name->Scale(1.0f, 0.3f, 1.0f); + + Fade = new Object(gc); + Fade->CreatePlane(3.0f, 0); + Fade->material = Material(0.0f, 0.0f, 0.0f); + + // load name textures + for(int i=0; i<8; i++) { + char fname[] = "data/textures/Absence/abx.jpg"; + fname[24] = '1' + i; + NameTex[i] = gc->texman->AddTexture(fname); + } + + cam[3]->Zoom(-1.0f); +} + +DungeonPart::~DungeonPart() { + delete scene; +} + +#define INRANGE(a, b) (msec >= a && msec < b) + +void DungeonPart::MainLoop() { + dword msec = timer.GetMilliSec(); + float t = (float)msec / 1000.0f; + + // set the active camera + for(int i=0; i<3; i++) { + cam[i]->FollowPath(msec); + } + Vector3 Cam3Pos = cam[3]->GetPosition(); + + if(msec >= 0 && msec < 40000) { + scene->SetActiveCamera(cam[0]); + } + if(msec >= 39990 && msec < 45000) { + scene->SetActiveCamera(cam[1]); + } + if(msec >= 45000 && msec < 75000) { + scene->SetActiveCamera(cam[2]); + } + + if(INRANGE(17000, 18000) || INRANGE(22000, 23000)) { + if(INRANGE(22000, 23000)) { + cam[3]->Rotate(0.0f, t, 0.0f); + } else { + cam[3]->Rotate(0.0f, -t, 0.0f); + } + scene->SetActiveCamera(cam[3]); + } + + gc->Clear(0); + gc->ClearZBufferStencil(1.0f, 0); + + + scene->Render(); + + // Render flames + gc->SetLighting(false); + gc->SetZWrite(false); + int ftexnum = (int)((float)msec / 33.35f) % FLAME_TEXTURES; + gc->SetAlphaBlending(true); + gc->SetBackfaceCulling(false); + gc->SetBlendFunc(BLEND_ONE, BLEND_ONE); + gc->SetTextureStageColor(0, TexBlendModulate, TexArgTexture, TexArgCurrent); + gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgTexture, TexArgTexture); + gc->SetMaterial(Flame[0]->material); + gc->SetTexture(1, 0); + for(int i=0; i<16; i++) { + gc->SetTexture(0, FlameTex[ftexnum]); + gc->SetWorldMatrix(Flame[i]->GetWorldTransform()); + Flame[i]->RenderBare(); + } + gc->SetBackfaceCulling(true); + gc->SetAlphaBlending(false); + gc->SetZWrite(true); + gc->SetLighting(true); + + // render the shadow walls + gc->SetAlphaBlending(true); + gc->SetBlendFunc(BLEND_DESTCOLOR, BLEND_ZERO); + gc->SetTexture(0, ShadowObj[0]->material.Maps[0]); + gc->SetTextureStageColor(0, TexBlendModulate, TexArgTexture, TexArgDiffuseColor); + gc->SetMaterial(ShadowObj[0]->material); + gc->SetWorldMatrix(ShadowObj[0]->GetWorldTransform()); + ShadowObj[0]->RenderBare(); + gc->SetWorldMatrix(ShadowObj[1]->GetWorldTransform()); + ShadowObj[1]->RenderBare(); + gc->SetAlphaBlending(false); + + // render volumetric light + gc->SetAlphaBlending(true); + gc->SetZWrite(false); + + + LightRays->ResetScaling(); + + LightRays->material.Alpha = 0.02f; + LightRays->material.SetEmissive(1.0f, 1.0f, 1.0f); + for(int i=0; i<14; i++) { + LightRays->Scale(0.975f, 1.0f, 0.975f); + LightRays->Render(); + } + gc->SetZWrite(true); + gc->SetAlphaBlending(false); + + + // The Morphing Object + + Obj->GetTriMesh()->SetData(mobj->GetTriMesh()->GetVertexArray(), mobj->GetTriMesh()->GetTriangleArray(), mobj->GetTriMesh()->GetVertexCount(), mobj->GetTriMesh()->GetTriangleCount()); + + dword VertCount = Obj->GetTriMesh()->GetVertexCount(); + Vertex *verts = Obj->GetTriMesh()->GetModVertexArray(); + for(dword i=0; iGetTriMesh()->CalculateNormals(); + Obj->Render(); + + + // make the lava move + Matrix3x3 TexMat; + TexMat.m[2][0] = t/50.0f; + TexMat.m[2][1] = t/70.0f; + gc->SetTextureMatrix(TexMat); + LavaCrust->Render(); + gc->SetTextureMatrix(Matrix4x4()); + + /////// Render the Crystals /////////// +/* + float StartRise = 4;//53.0f; + float EndRise = 8;//57.0f; + float yoffset = -355.0f; + + if(t >= StartRise && t < EndRise) { + for(int i=0; i<5; i++) Crystals[i]->SetTranslation(0.0f, (t - StartRise) / (EndRise - StartRise), 0.0f); + } +*/ + gc->SetShadingMode(FlatShading); + for(int i=0; i<5; i++) { + Crystals[i]->Render(); + } + gc->SetShadingMode(GouraudShading); + + + //////////////// render the mirroring marble floor /////////////// + + // burn the stencil baby + gc->SetZWrite(false); + gc->SetColorWrite(false, false, false, false); + gc->SetStencilBuffering(true); + gc->SetStencilFunc(CMP_ALWAYS); + gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_INC); + + for(int i=0; i<3; i++) Floor[i]->Render(); + gc->SetZWrite(true); + gc->SetColorWrite(true, true, true, true); + gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_KEEP); + + // render the rest of the floor normally + Floor[0]->ResetRotation(); + Floor[0]->Rotate(0.0f, t/2.0f, 0.0f); + Floor[1]->ResetRotation(); + Floor[1]->Rotate(0.0f, -t/4.0f, 0.0f); + + for(int i=0; i<3; i++) Floor[i]->Render(); + + // render the reflection where stencil > 0 + gc->SetStencilFunc(CMP_EQUAL); + gc->SetStencilReference(1); + gc->ClearZBuffer(1.0f); + + gc->SetFrontFace(CounterClockwise); + + std::list *objlist = scene->GetObjectsList(); + std::list::iterator iter = objlist->begin(); + while(iter != objlist->end()) { + (*iter)->Scale(1.0f, -1.0f, 1.0f); + float alpha = (*iter)->material.Alpha; + (*iter)->material.Alpha = 0.25f; + (*iter)->Render(); + (*iter)->material.Alpha = alpha; + (*iter++)->Scale(1.0f, -1.0f, 1.0f); + } + + gc->SetFrontFace(Clockwise); + gc->SetStencilBuffering(false); + + if(t < 6.0f) { + gc->SetAlphaBlending(true); + gc->SetLighting(false); + gc->SetZBuffering(false); + gc->SetBlendFunc(BLEND_ONE, BLEND_ONE); + gc->SetMaterial(Material(1.0f, 1.0f, 1.0f)); + gc->SetTexture(0, NameTex[(msec >> 6) % 8]); + gc->SetTextureStageColor(0, TexBlendSelectArg1, TexArgTexture, TexArgTexture); + gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgTexture, TexArgTexture); + gc->SetWorldMatrix(Name->GetWorldTransform()); + Matrix4x4 ViewMat; + ViewMat.Translate(0.0f, 0.0f, 1.0f); + gc->SetViewMatrix(ViewMat); + Name->RenderBare(); + gc->SetLighting(true); + + // fade in + Fade->material.Alpha = min(max(0.0f, (2.0f - t)), 1.0f); + Fade->Render(); + + gc->SetZBuffering(true); + gc->SetAlphaBlending(false); + } + + cam[3]->SetPosition(Cam3Pos); +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/dungeonpart.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dungeonpart.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,32 @@ +#ifndef _DUNGEONPART_H_ +#define _DUNGEONPART_H_ + +#include "demosystem/demosys.h" + +#define FLAME_TEXTURES 52 + +class DungeonPart : public Part { +private: + //Scene *scene; + Texture *FlameTex[FLAME_TEXTURES]; + + Curve *CamPath[4], *TargPath[2]; + Camera *cam[4]; + + Object *Flame[16], *LavaCrust, *ShadowObj[2], *LightRays; + Object *Floor[3], *Obj, *mobj, *Crystals[5]; + + Object *Name, *Fade; + Texture *NameTex[8]; + + dword CamTimeSeg[3][2]; + +public: + + DungeonPart(GraphicsContext *gc); + ~DungeonPart(); + + virtual void MainLoop(); +}; + +#endif // _DUNGEONPART_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/greetspart.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/greetspart.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,97 @@ +#include "greetspart.h" +#include "nwt/widget.h" + +extern Widget *win; + +GreetsPart::GreetsPart(GraphicsContext *gc) { + this->gc = gc; + + gc->Clear(0); + gc->ClearZBufferStencil(1.0f, 0); + + + SceneLoader::SetNormalFileSaving(false); + SceneLoader::SetDataPath("data/textures/"); + SceneLoader::LoadScene("data/geometry/greets.3ds", &scene); + SceneLoader::SetNormalFileSaving(true); + + Parchment = scene->GetObject("Plane01"); + //Scroll1 = scene->GetObject("Object01"); + //Scroll2 = scene->GetObject("Object02"); + + // load the flame textures + for(int i=0; i<52; i++) { + char num[3]; + itoa(i, num, 10); + string fname = string("data/textures/flame/flame") + (i < 10 ? string("0") : string("")) + string(num) + string(".jpg"); + FlameTex[i] = gc->texman->LoadTexture(fname.c_str()); + } + + flame = scene->GetObject("Plane02"); + scene->RemoveObject(flame); + + Parchment->SetScaling(9.0f, 1.0f, 1.0f); + + Bottle = scene->GetObject("Bottle"); + scene->RemoveObject(Bottle); + + light = scene->GetLight("Omni01"); + + scene->SetShadows(true); + light->SetShadowCasting(true); + //scene->GetObject("CHolder")->SetShadowCasting(true); + scene->GetObject("Candle")->SetShadowCasting(true); + //scene->GetObject("Bottle01")->SetShadowCasting(true); + + const Light *l[] = {light}; + scene->GetObject("Cylinder01")->CalculateShadows(l, 1); + scene->GetObject("Cylinder02")->CalculateShadows(l, 1); + scene->GetObject("Bottle01")->CalculateShadows(l, 1); + scene->GetObject("Plane01")->CalculateShadows(l, 1); + + scene->SetAmbientLight(Color(0.58f, 0.3f, 0.3f)); + + LightPos = light->GetPosition(); + light->SetIntensity(0.5f); + light->SetAttenuation(0.0f, 0.1f, 0.0f); + +} + +GreetsPart::~GreetsPart() { + delete scene; +} + +void GreetsPart::MainLoop() { + + gc->Clear(0); + gc->ClearZBufferStencil(1.0f, 0); + + Vector3 LightPosDiff(frand(0.005f) - 0.0025f, frand(0.005f) - 0.0025f, frand(0.005f) - 0.0025f); + light->SetPosition(LightPos + LightPosDiff); + + light->SetIntensity(0.5f + (frand(0.1f) - 0.05f)); + + dword msec = timer.GetMilliSec(); + float t = msec / 1000.0f; + + scene->Render(); + + Bottle->Render(); + + gc->SetLighting(false); + int ftexnum = (int)((float)msec / 33.35f) % 52; + gc->SetAlphaBlending(true); + gc->SetBackfaceCulling(false); + gc->SetBlendFunc(BLEND_ONE, BLEND_ONE); + gc->SetTextureStageColor(0, TexBlendSelectArg1, TexArgTexture, TexArgCurrent); + gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgTexture, TexArgTexture); + gc->SetMaterial(Material(1.0f, 1.0f, 1.0f)); + gc->SetTextureCoordIndex(0, 0); + gc->SetTexture(1, 0); + gc->SetTexture(0, FlameTex[ftexnum]); + gc->SetWorldMatrix(flame->GetWorldTransform()); + flame->RenderBare(); + gc->SetBackfaceCulling(true); + gc->SetAlphaBlending(false); + gc->SetLighting(true); +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/greetspart.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/greetspart.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,24 @@ +#ifndef _GREETSPART_H_ +#define _GREETSPART_H_ + +#include "demosystem/demosys.h" + +class GreetsPart : public Part { +private: + Camera *cam; + Object *Parchment, *Scroll1, *Scroll2; + Texture *FlameTex[52]; + Object *flame, *Bottle; + + Light *light; + Vector3 LightPos; + + +public: + GreetsPart(GraphicsContext *gc); + ~GreetsPart(); + + void MainLoop(); +}; + +#endif // _GREETSPART_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/hellpart.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hellpart.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,225 @@ +#include +#include "hellpart.h" + +HellPart::HellPart(GraphicsContext *gc) { + this->gc = gc; + + SceneLoader::SetNormalFileSaving(true); + SceneLoader::SetDataPath("data/textures/"); + SceneLoader::LoadScene("data/geometry/hell.3ds", &scene); + + CamPath = scene->GetCurve("CamPath"); + cam = const_cast(scene->GetActiveCamera()); + cam->SetCameraPath(CamPath, 0, 0, 30000); + cam->SetClippingPlanes(1.0f, 100000.0f); + + cam2 = scene->GetCamera("Camera02"); + cam3 = scene->GetCamera("Camera03"); + cam2->SetClippingPlanes(1.0f, 100000.0f); + cam3->SetClippingPlanes(1.0f, 100000.0f); + + Thunder = scene->GetLight("Omni01"); + Thunder->SetIntensity(0.0f); + + ThundEnv[0] = scene->GetObject("b1"); + ThundEnv[1] = scene->GetObject("b2"); + ThundEnv[2] = scene->GetObject("b3"); + ThundEnv[3] = scene->GetObject("b4"); + ThundEnv[4] = scene->GetObject("b5"); + for(int i=0; i<5; i++) { + scene->RemoveObject(ThundEnv[i]); + } + + Stones[0] = scene->GetObject("Box01"); + Stones[1] = scene->GetObject("Box02"); + Stones[2] = scene->GetObject("Box03"); + Stones[3] = scene->GetObject("Box04"); + Stones[4] = scene->GetObject("Box05"); + for(int i=0; i<5; i++) { + scene->RemoveObject(Stones[i]); + Stones[i]->SetShadingMode(FlatShading); + } + + Rings[0] = scene->GetObject("Tube01"); + Rings[1] = scene->GetObject("Tube02"); + Rings[2] = scene->GetObject("Tube03"); + Rings[3] = scene->GetObject("Tube04"); + Rings[4] = scene->GetObject("Tube05"); + for(int i=0; i<5; i++) { + scene->RemoveObject(Rings[i]); + } + + // Load Credits + dbgtex = gc->texman->AddTexture("data/textures/psys02.jpg"); + CredNuc[0] = gc->texman->AddTexture("data/textures/credits/nuc1.jpg"); + CredNuc[1] = gc->texman->AddTexture("data/textures/credits/nuc2.jpg"); + CredNuc[2] = gc->texman->AddTexture("data/textures/credits/nuc3.jpg"); + CredNuc[3] = gc->texman->AddTexture("data/textures/credits/nuc4.jpg"); + CredNuc[4] = gc->texman->AddTexture("data/textures/credits/nuc5.jpg"); + CredNuc[5] = gc->texman->AddTexture("data/textures/credits/nuc6.jpg"); + CredNuc[6] = gc->texman->AddTexture("data/textures/credits/nuc7.jpg"); + + CredRaw[0] = gc->texman->AddTexture("data/textures/credits/raw1.jpg"); + CredRaw[1] = gc->texman->AddTexture("data/textures/credits/raw2.jpg"); + CredRaw[2] = gc->texman->AddTexture("data/textures/credits/raw3.jpg"); + CredRaw[3] = gc->texman->AddTexture("data/textures/credits/raw4.jpg"); + CredRaw[4] = gc->texman->AddTexture("data/textures/credits/raw5.jpg"); + CredRaw[5] = gc->texman->AddTexture("data/textures/credits/raw6.jpg"); + CredRaw[6] = gc->texman->AddTexture("data/textures/credits/raw7.jpg"); + + CredAmi[0] = gc->texman->AddTexture("data/textures/credits/am1.jpg"); + CredAmi[1] = gc->texman->AddTexture("data/textures/credits/am2.jpg"); + CredAmi[2] = gc->texman->AddTexture("data/textures/credits/am3.jpg"); + CredAmi[3] = gc->texman->AddTexture("data/textures/credits/am4.jpg"); + CredAmi[4] = gc->texman->AddTexture("data/textures/credits/am5.jpg"); + CredAmi[5] = gc->texman->AddTexture("data/textures/credits/am6.jpg"); + CredAmi[6] = gc->texman->AddTexture("data/textures/credits/am7.jpg"); + + CredAmv[0] = gc->texman->AddTexture("data/textures/credits/amv1.jpg"); + CredAmv[1] = gc->texman->AddTexture("data/textures/credits/amv2.jpg"); + CredAmv[2] = gc->texman->AddTexture("data/textures/credits/amv3.jpg"); + CredAmv[3] = gc->texman->AddTexture("data/textures/credits/amv4.jpg"); + CredAmv[4] = gc->texman->AddTexture("data/textures/credits/amv5.jpg"); + CredAmv[5] = gc->texman->AddTexture("data/textures/credits/amv6.jpg"); + CredAmv[6] = gc->texman->AddTexture("data/textures/credits/amv7.jpg"); + + Credits = new Object(gc); + Credits->CreatePlane(1.7f, 0); + Credits->Scale(1.0f, 0.3f, 1.0f); + + Blood = scene->GetObject("Blood"); + scene->RemoveObject(Blood); + Grail = scene->GetObject("Object13"); + //scene->RemoveObject(Grail); +} + +HellPart::~HellPart() { + delete scene; +} + +void HellPart::MainLoop() { + dword msec = timer.GetMilliSec(); + float t = msec / 1000.0f; + + // deform blood surface + Vertex *BloodVerts = Blood->GetTriMesh()->GetModVertexArray(); + dword VertexCount = Blood->GetTriMesh()->GetVertexCount(); + + for(dword i=0; i 0.0f ? (1.0f / (dist*1.5f)) : 1.0f); + } + Blood->GetTriMesh()->CalculateNormals(); + + + //////////////////////// + + gc->Clear(0); + gc->ClearZBufferStencil(1.0f, 0); + + scene->SetActiveCamera(cam); + + if(t >= 18.0f && t < 22.0f) { + scene->SetActiveCamera(cam2); + Credits->material.SetTexture(CredNuc[(int)(t * 20.0f) % 7], TextureMap); + } + if(t >= 24.0f && t < 28.0f) { + scene->SetActiveCamera(cam3); + Credits->material.SetTexture(CredRaw[(int)(t * 20.0f) % 7], TextureMap); + } + if(t >= 30.0f && t < 34.0f) { + scene->SetActiveCamera(cam2); + Credits->material.SetTexture(CredAmi[(int)(t * 20.0f) % 7], TextureMap); + } + if(t >= 36.0f && t < 40.0f) { + scene->SetActiveCamera(cam3); + Credits->material.SetTexture(CredAmv[(int)(t * 20.0f) % 7], TextureMap); + } + + cam->FollowPath(msec); + + gc->SetAmbientLight(Color(0.5f)); + + scene->Render(); + + for(int i=0; i<5; i++) { + Matrix4x4 tmat = Stones[i]->TransMat, rmat = Stones[i]->GRotMat; + Stones[i]->Translate(0.0f, sinf(t) * 54.0f, 0.0f); + Stones[i]->GlobalRotate(0.0f, t/4.0f, 0.0f); + + Stones[i]->Render(); + + Stones[i]->TransMat = tmat; + Stones[i]->GRotMat = rmat; + } + + float Rot = t / 2.0f; + + for(int i=0; i<5; i++) { + Rings[i]->ResetRotation(); + } + + Rings[0]->Rotate(Rot, 0.0f, 0.0f); + + Rings[1]->Rotate(0.0f, 0.0f, Rot); + + Vector3 axis(1.0f, 0.0f, 0.0f); + axis.Rotate(0.0f, 0.0f, QuarterPi); + Rings[2]->Rotate(0.0f, 0.0f, QuarterPi); + Rings[2]->Rotate(axis, Rot); + + axis = Vector3(0.0f, 0.0f, 1.0f); + axis.Rotate(QuarterPi, 0.0f, 0.0f); + Rings[3]->Rotate(QuarterPi, 0.0f, 0.0f); + Rings[3]->Rotate(axis, Rot); + + Rings[4]->Rotate(Rot, 0.0f, Rot); + + gc->SetZWrite(false); + for(int i=0; i<5; i++) { + Rings[i]->Render(); + } + gc->SetZWrite(true); + + Light *light = scene->GetLight("Spot01"); + light->SetRange(100000.0f); + light->SetIntensity(0.5f); + light->SetLight(0, gc); + Blood->Render(); + light->SetRange(100.0f); + light->SetLight(0, gc); + + gc->SetAmbientLight(Color(0.0f)); + + if((t >= 18.0f && t < 22.0f) || (t >= 24.0f && t < 28.0f) || (t >= 30.0f && t < 34.0f) || (t >= 36.0f && t < 40.0f)) { + gc->SetAlphaBlending(true); + gc->SetLighting(false); + gc->SetZBuffering(false); + gc->SetBlendFunc(BLEND_ONE, BLEND_ONE); + gc->SetMaterial(Material(1.0f, 1.0f, 1.0f)); + gc->SetTexture(0, Credits->material.Maps[TextureMap]); + gc->SetTexture(1, 0); + gc->SetTextureCoordIndex(0, 0); + + gc->SetTextureStageColor(0, TexBlendSelectArg1, TexArgTexture, TexArgCurrent); + gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgTexture, TexArgCurrent); + Matrix4x4 WorldMat; + WorldMat.Scale(1.0f, 0.3f, 1.0f); + gc->SetWorldMatrix(WorldMat); + Matrix4x4 ViewMat; + ViewMat.Translate(0.0f, 0.0f, 2.0f); + gc->SetViewMatrix(ViewMat); + Matrix4x4 ProjMat, OldProj; + OldProj = gc->GetProjectionMatrix(); + CreateProjectionMatrix(&ProjMat, QuarterPi, 1.333333f, 1.0f, 10.0f); + gc->SetProjectionMatrix(ProjMat); + + Credits->RenderBare(); + + gc->SetProjectionMatrix(OldProj); + gc->SetLighting(true); + gc->SetZBuffering(true); + gc->SetAlphaBlending(false); + } +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/hellpart.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hellpart.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,31 @@ +#ifndef _HELLPART_H_ +#define _HELLPART_H_ + +#include "demosystem/demosys.h" + +class HellPart : public Part { +private: + Curve *CamPath; + Camera *cam, *cam2, *cam3; + Object *Stones[5]; + Object *Rings[5]; + Light *Thunder; + Object *ThundEnv[5]; + Object *Credits; + Object *Blood, *Grail; + Texture *dbgtex; + Texture *CredNuc[7]; + Texture *CredAmi[7]; + Texture *CredRaw[7]; + Texture *CredAmv[7]; + + + +public: + HellPart(GraphicsContext *gc); + ~HellPart(); + + void MainLoop(); +}; + +#endif // _HELLPART_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/nwt/nucwin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nwt/nucwin.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,174 @@ +#include "nucwin.h" +#include +#include + +#ifndef WM_MOUSEWHEEL +#define WM_MOUSEWHEEL 0x020A +#endif // WM_MOUSEWHEEL + +MainLoopMode loopmode; +char *Arguments; + +int (*KeyHandlerFunc)(Widget*, int) = 0; +int (*CloseHandlerFunc)(Widget*, int) = 0; +int (*MouseHandlerFunc)(Widget*, int, int, bool, bool, bool) = 0; +int (*MouseUpHandlerFunc)(Widget*, int, int, bool, bool, bool) = 0; +int (*MouseWheelHandlerFunc)(Widget*, int, int, int) = 0; +int (*WinMoveHandlerFunc)(Widget*, int, int) = 0; +int (*PaintHandlerFunc)(Widget*) = 0; + +void (*RealTimeLoopFunc)() = 0; + +void SetHandler(HandlerType htype, int (*Handler)(Widget*, int)) { + switch(htype) { + case HANDLER_KEY: + KeyHandlerFunc = Handler; + break; + + case HANDLER_CLOSE: + CloseHandlerFunc = Handler; + break; + + case HANDLER_MOUSE: + MouseHandlerFunc = (int (*)(Widget*, int, int, bool, bool, bool))Handler; + break; + + case HANDLER_MOUSEUP: + MouseUpHandlerFunc = (int (*)(Widget*, int, int, bool, bool, bool))Handler; + break; + + case HANDLER_WHEEL: + MouseWheelHandlerFunc = (int (*)(Widget*, int, int, int))Handler; + break; + + case HANDLER_WINMOVE: + WinMoveHandlerFunc = (int (*)(Widget*, int, int))Handler; + break; + + case HANDLER_PAINT: + PaintHandlerFunc = (int (*)(Widget*))Handler; + break; + + default: break; + } +} + +void SetMainLoopFunc(void (*func)()) { + RealTimeLoopFunc = func; +} + +int NWMainLoop(MainLoopMode mode) { + + MSG msg; + loopmode = mode; + + if(mode == RealTimeLoop) { + while(1) { + if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { + if(msg.message == WM_QUIT) break; + TranslateMessage(&msg); + DispatchMessage(&msg); + } else { + if(RealTimeLoopFunc) RealTimeLoopFunc(); + } + } + } else { + while(GetMessage(&msg, 0, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (int)msg.wParam; +} + +bool NWCheckForMessages() { + MSG msg; + return (bool)PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE); +} + + +LRESULT CALLBACK MainHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch(msg) { + case WM_KEYDOWN: + if(KeyHandlerFunc) return KeyHandlerFunc(hWnd, (int)wParam); + break; + + case WM_CLOSE: + if(CloseHandlerFunc) CloseHandlerFunc(0, 0); + DestroyWindow(hWnd); + PostQuitMessage(0); + return 0; + break; + + case WM_MOUSEMOVE: + if(MouseHandlerFunc) MouseHandlerFunc(hWnd, LOWORD(lParam), HIWORD(lParam), (bool)(wParam & MK_LBUTTON), (bool)(wParam & MK_MBUTTON), (bool)(wParam & MK_RBUTTON)); + break; + + case WM_LBUTTONDOWN: + if(MouseHandlerFunc) MouseHandlerFunc(hWnd, LOWORD(lParam), HIWORD(lParam), true, false, false); + break; + + case WM_MBUTTONDOWN: + if(MouseHandlerFunc) MouseHandlerFunc(hWnd, LOWORD(lParam), HIWORD(lParam), false, true, false); + break; + + case WM_RBUTTONDOWN: + if(MouseHandlerFunc) MouseHandlerFunc(hWnd, LOWORD(lParam), HIWORD(lParam), false, false, true); + break; + + case WM_LBUTTONUP: + if(MouseUpHandlerFunc) MouseUpHandlerFunc(hWnd, LOWORD(lParam), HIWORD(lParam), true, false, false); + break; + + case WM_MBUTTONUP: + if(MouseUpHandlerFunc) MouseUpHandlerFunc(hWnd, LOWORD(lParam), HIWORD(lParam), false, true, false); + break; + + case WM_RBUTTONUP: + if(MouseUpHandlerFunc) MouseUpHandlerFunc(hWnd, LOWORD(lParam), HIWORD(lParam), false, false, true); + break; + + case WM_MOUSEWHEEL: + if(MouseWheelHandlerFunc) MouseWheelHandlerFunc(hWnd, LOWORD(lParam), HIWORD(lParam), (short)HIWORD(wParam)); + break; + + case WM_MOVE: + if(WinMoveHandlerFunc) WinMoveHandlerFunc(hWnd, LOWORD(lParam), HIWORD(lParam)); + break; + + case WM_PAINT: + if(PaintHandlerFunc) PaintHandlerFunc(hWnd); + } + + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +Point NWGetScreenSize() { + return Point(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); +} + +void NWCloseWindow(Widget *win) { + PostMessage(win, WM_CLOSE, 0, 0); +} + +std::string NWFileSaveChooser(Widget *win, const char *title, const char *filetypes, const char *defext) { + + char fname[512]; + fname[0] = 0; + + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = win; + ofn.lpstrFilter = filetypes; + ofn.lpstrFile = fname; + ofn.nMaxFile = 512; + ofn.lpstrTitle = title; + ofn.lpstrDefExt = defext; + ofn.Flags = OFN_PATHMUSTEXIST; + + if(!GetSaveFileName(&ofn)) return ""; + + return fname; +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/nwt/nucwin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nwt/nucwin.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,47 @@ +#ifndef _NUCWIN_H_ +#define _NUCWIN_H_ + +#include +#include "widget.h" + +struct Point { + int x, y; + inline Point(int x=0, int y=0) {this->x = x; this->y = y;} +}; + +struct Rect : public RECT { + inline Rect() {} + inline Rect(int l, int t, int r, int b) {left=l; top=t; right=r; bottom=b;} +}; + + +#define HandlerFunctionPtr int (*)(Widget*, int) + +extern char *Arguments; + +enum HandlerType { + HANDLER_KEY, + HANDLER_CLOSE, + HANDLER_MOUSE, + HANDLER_WHEEL, + HANDLER_WINMOVE, + HANDLER_MOUSEUP, + HANDLER_PAINT +}; +enum MainLoopMode {EventLoop, RealTimeLoop}; + +void SetHandler(HandlerType htype, int (*Handler)(Widget*, int)); + +void SetMainLoopFunc(void (*func)()); + +Point NWGetScreenSize(); + +int NWMainLoop(MainLoopMode mode = EventLoop); +bool NWCheckForMessages(); +LRESULT CALLBACK MainHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +void NWCloseWindow(Widget *win); + +std::string NWFileSaveChooser(Widget *win, const char *title, const char *filetypes, const char *defext); + +#endif // _NUCWIN_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/nwt/startup.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nwt/startup.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,33 @@ +#ifndef _STARTUP_H_ +#define _STARTUP_H_ + +#include +#include "nucwin.h" + +int main(); +void RegisterWindowClasses(); + +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR CmdLine, int ShowCmd) { + Arguments = CmdLine; + RegisterWindowClasses(); + return main(); +} + +void RegisterWindowClasses() { + WNDCLASSEX wc; + wc.cbSize = sizeof(WNDCLASSEX); + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hIconSm = wc.hIcon; + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = MainHandler; + wc.lpszClassName = "NucWin"; + wc.lpszMenuName = NULL; + wc.style = CS_HREDRAW | CS_VREDRAW; + RegisterClassEx(&wc); +} + +#endif // _STARTUP_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/nwt/widget.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nwt/widget.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,49 @@ +#include "widget.h" +#include "nucwin.h" + +Widget *NWCreateWindow(const char *name, int x, int y, int xsz, int ysz, uint16 flags) { + if(x == NWT_CENTERX) { + x = (GetSystemMetrics(SM_CXSCREEN) - xsz) >> 1; + } + if(y == NWT_CENTERY) { + y = (GetSystemMetrics(SM_CYSCREEN) - ysz) >> 1; + } + + HINSTANCE AppInstance = GetModuleHandle(0); + unsigned long ex_style = flags & NWT_WIN_TOPMOST ? WS_EX_TOPMOST : 0; + return CreateWindowEx(ex_style, "NucWin", name, WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, xsz, ysz, 0, 0, AppInstance, 0); +} + + +void NWResize(Widget *wdg, int nx, int ny) { + int xpos = (GetSystemMetrics(SM_CXSCREEN) - nx) >> 1; + int ypos = (GetSystemMetrics(SM_CYSCREEN) - ny) >> 1; + MoveWindow(wdg, xpos, ypos, nx, ny, true); +} + +void NWResizeClientArea(Widget *wdg, uint32 WinStyle) { + RECT rect; + GetWindowRect(wdg, &rect); + AdjustWindowRectEx(&rect, WinStyle, false, 0); + MoveWindow(wdg, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, true); +} + +void NWSetWindowPos(Widget *wdg, const Point &pos) { + Point sz = NWGetWindowSize(wdg); + MoveWindow(wdg, pos.x, pos.y, sz.x, sz.y, true); +} + +Point NWGetWindowPos(Widget *wdg) { + Rect rect; + GetWindowRect(wdg, &rect); + + return Point(rect.left, rect.top); +} + +Point NWGetWindowSize(Widget *wdg) { + Rect rect; + GetWindowRect(wdg, &rect); + + return Point(rect.right - rect.left, rect.bottom - rect.top); +} + diff -r 000000000000 -r 1cffe3409164 src/nwt/widget.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nwt/widget.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,26 @@ +#ifndef _WIDGET_H_ +#define _WIDGET_H_ + +#include +#include "typedefs.h" + +struct Point; +struct Rect; + +#define NWT_CENTERX -0xdead +#define NWT_CENTERY -0xbeef + +typedef HWND__ Widget; + +#define NWT_WIN_TOPMOST 1 + +Widget *NWCreateWindow(const char *name, int x, int y, int xsz, int ysz, uint16 flags); +void NWResize(Widget *wdg, int nx, int ny); +void NWResizeClientArea(Widget *wdg, uint32 WinStyle); + +void NWSetWindowPos(Widget *wdg, const Point &pos); + +Point NWGetWindowPos(Widget *wdg); +Point NWGetWindowSize(Widget *wdg); + +#endif // _WIDGET_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/treepart.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/treepart.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,156 @@ +#include "treepart.h" + +TreePart::TreePart(GraphicsContext *gc) { + this->gc = gc; + + scene = new Scene(gc); +/* + LeavesParticle = gc->texman->AddTexture("data/textures/leaf.png"); + + leaves = new ParticleSystem(gc); + leaves->SetPosition(Vector3(0.0f, 800.0f, 0.0f)); + leaves->SetGravitualForce(0.8f); + leaves->SetFriction(0.05f); + leaves->SetInitialColor(0.6f, 0.5f, 0.5f); + leaves->SetDeathColor(0.6f, 0.5f, 0.5f); + leaves->SetParticleSize(6.0f); + leaves->SetParticleLife(1000); + leaves->SetSpawnRadius(1500.0f); + leaves->SetSpawnRate(20.0f); + leaves->SetTexture(LeavesParticle); + leaves->SetShootDirection(Vector3(0.0f, -10.0f, 0.0f)); + leaves->SetMaxDispersionAngle(QuarterPi / 2.0f); + leaves->SetBlendingMode(BLEND_SRCALPHA, BLEND_INVSRCALPHA); +*/ + WispParticle = gc->texman->AddTexture("data/textures/psys02.jpg"); + + for(int i=0; i<4; i++) { + WispParticles[i] = new ParticleSystem(gc); + WispParticles[i]->SetGravitualForce(0.8f); + WispParticles[i]->SetFriction(0.06f); + WispParticles[i]->SetInitialColor(0.7f, 0.8f, 1.0f); + WispParticles[i]->SetDeathColor(0.2f, 0.2f, 0.5f); + WispParticles[i]->SetParticleSize(7.5f); + WispParticles[i]->SetParticleLife(15); + WispParticles[i]->SetSpawnRadius(0.2f); + WispParticles[i]->SetSpawnRate(4.0f); + WispParticles[i]->SetTexture(WispParticle); + WispParticles[i]->SetShootDirection(Vector3(0.0f, 0.0f, 0.0f)); + WispParticles[i]->SetMaxDispersionAngle(QuarterPi / 2.0f); + WispParticles[i]->SetBlendingMode(BLEND_ONE, BLEND_ONE); + WispParticles[i]->SetSpawningDifferenceDispersion(1.0f); + } + + SceneLoader::SetNormalFileSaving(true); + SceneLoader::SetDataPath("data/textures/"); + SceneLoader::LoadScene("data/geometry/tree2.3ds", &scene); + + Trees = scene->GetObject("Trees"); + scene->RemoveObject(Trees); + + for(int i=0; i<3; i++) { + dummy[i] = new Camera; + } + + Object *graves = scene->GetObject("Graves"); + //graves->SetShadowCasting(true); + + WispPath[0] = scene->GetCurve("wisp1"); + WispPath[1] = scene->GetCurve("wisp2"); + WispPath[2] = scene->GetCurve("wisp3"); + + WispPath[0]->SetArcParametrization(true); + WispPath[1]->SetArcParametrization(true); + WispPath[2]->SetArcParametrization(true); + + dummy[0]->SetCameraPath(WispPath[0], 0, 0, 8000); + dummy[1]->SetCameraPath(WispPath[1], 0, 0, 7000); + dummy[2]->SetCameraPath(WispPath[2], 0, 0, 10000); + + lights[0] = scene->GetLight("wispl1"); + lights[1] = scene->GetLight("wispl2"); + lights[2] = scene->GetLight("wispl3"); + lights[3] = scene->GetLight("wispl04"); + + for(int i=0; i<3; i++) { + lights[i]->SetRange(250.0f); + lights[i]->SetColor(Color(0.6f, 0.6f, 0.9f)); + } + lights[3]->SetColor(Color(0.6f, 0.6f, 0.9f)); + + CamPath = scene->GetCurve("cpath01"); + TargPath = scene->GetCurve("ctarget01"); + + CamPath->SetArcParametrization(true); + TargPath->SetArcParametrization(true); + + cam = scene->GetCamera("Camera02"); + cam->SetClippingPlanes(1.0f, 80000.0f); + cam->SetCameraPath(CamPath, TargPath, 0, 40000); + scene->SetActiveCamera(cam); + + //scene->SetShadows(true); + //lights[3]->SetShadowCasting(true); + + Moon = scene->GetObject("Moon"); + scene->RemoveObject(Moon); + + Stars = scene->GetObject("StarDome"); + scene->RemoveObject(Stars); + +} + +TreePart::~TreePart() { + delete scene; + delete leaves; +} + +void TreePart::MainLoop() { + dword msec = timer.GetMilliSec(); + float t = msec / 1000.0f; + + float start = 10.0f; + float end = 10500.0f; + + gc->D3DDevice->SetRenderState(D3DRS_FOGENABLE, true); + gc->D3DDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR); + gc->D3DDevice->SetRenderState(D3DRS_FOGCOLOR, 0); + gc->D3DDevice->SetRenderState(D3DRS_FOGSTART, *(dword*)(&start)); + gc->D3DDevice->SetRenderState(D3DRS_FOGEND, *(dword*)(&end)); + + cam->FollowPath(msec); + for(int i=0; i<3; i++) { + dummy[i]->FollowPath(msec, true); + lights[i]->SetPosition(dummy[i]->GetPosition()); + } + lights[3]->SetPosition(cam->GetTargetPosition()); + + gc->Clear(0); + gc->ClearZBufferStencil(1.0f, 0); + + scene->Render(); + + gc->SetZWrite(false); + Trees->Render(); + gc->SetZWrite(true); + + //for(int i=0; i<3; i++) { + // lights[i]->Draw(gc, 20.0f); + //} + //lights[3]->Draw(gc, 30.0f); + + gc->D3DDevice->SetRenderState(D3DRS_FOGENABLE, false); + + //leaves->Update(t); + //leaves->Render(); + + Stars->Render(); + Moon->Render(); + + for(int i=0; i<4; i++) { + WispParticles[i]->SetPosition(Vector3(lights[i]->GetPosition())); + WispParticles[i]->Update(t); + WispParticles[i]->Render(); + } +} + diff -r 000000000000 -r 1cffe3409164 src/treepart.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/treepart.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,25 @@ +#ifndef _TREEPART_H_ +#define _TREEPART_H_ + +#include "demosystem/demosys.h" +#include "3deng/particles.h" + +class TreePart : public Part { +private: + //Scene *scene; + ParticleSystem *leaves, *WispParticles[4]; + Texture *WispParticle, *LeavesParticle; + Camera *cam, *dummy[3]; + Curve *CamPath, *TargPath, *WispPath[3]; + Light *lights[4]; + + Object *Trees, *Moon, *Stars; +public: + + TreePart(GraphicsContext *gc); + ~TreePart(); + + void MainLoop(); +}; + +#endif // _TREEPART_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/tunnelpart.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tunnelpart.cpp Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,34 @@ +#include "tunnelpart.h" + +TunnelPart::TunnelPart(GraphicsContext *gc) { + this->gc = gc; + + SceneLoader::SetNormalFileSaving(true); + SceneLoader::SetDataPath("data/textures/"); + SceneLoader::LoadScene("data/geometry/tunnel.3ds", &scene); + + CamPath = scene->GetCurve("Line01"); + TargPath = scene->GetCurve("Line02"); + + CamPath->SetArcParametrization(true); + TargPath->SetArcParametrization(true); + + cam = scene->GetCamera("Camera02"); + cam->SetCameraPath(CamPath, TargPath, 0, 30000); +} + +TunnelPart::~TunnelPart() { + delete scene; +} + +void TunnelPart::MainLoop() { + dword msec = timer.GetMilliSec(); + float t = msec / 1000.0f; + + gc->Clear(0); + gc->ClearZBufferStencil(1.0f, 0); + + cam->FollowPath(msec); + + scene->Render(); +} \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 src/tunnelpart.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tunnelpart.h Thu Oct 23 01:46:07 2014 +0300 @@ -0,0 +1,19 @@ +#ifndef _TUNNELPART_H_ +#define _TUNNELPART_H_ + +#include "demosystem/demosys.h" + +class TunnelPart : public Part { +private: + Curve *CamPath, *TargPath; + Camera *cam; + +public: + + TunnelPart(GraphicsContext *gc); + ~TunnelPart(); + + void MainLoop(); +}; + +#endif // _TUNNELPART_H_ \ No newline at end of file diff -r 000000000000 -r 1cffe3409164 thelab.ico Binary file thelab.ico has changed