port: CMapOutdoor + PythonBackground + minimap (1:1 40250)

GameLib map/area/terrain units, PRTerrainLib Terrain/TextureSet,
PythonBackground(+Module) and ColorTransitionHelper ported verbatim;
pending stand-ins and background module stubs removed. Hand edits:
BeginEnvironment's pointer tag via uintptr_t, LoadWaterMap reads the
file's 32-bit longs. Terrain draw passes stay platform no-ops (Godot
draws the terrain). RecordingDevice gains textures, buffers and render
targets; orthographic draws become UI commands so CPythonMiniMap's
masked tiles show through minimap_image_filter in python_ui_surface.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-24 03:50:09 +09:00
co-authored by Claude Opus 5.5
parent b69116992c
commit 2ead95756e
100 changed files with 17679 additions and 1514 deletions
+107
View File
@@ -0,0 +1,107 @@
// Platform implementation of EterBase/FileDir.h (40250 EterBase/FileDir.cpp): the 40250 code as is, over the
// FindFirstFile/FindNextFile/FindClose of common/Win32Crt.h.
#include "EterBase/StdAfx.h"
#include "EterBase/FileDir.h"
#include <string>
CDir::CDir()
{
Initialize();
}
CDir::~CDir()
{
Destroy();
}
void CDir::Destroy()
{
if (m_hFind)
FindClose(m_hFind);
Initialize();
}
bool CDir::Create(const char * c_szFilter, const char* c_szPath, BOOL bCheckedExtension)
{
Destroy();
std::string stPath = c_szPath;
if (stPath.length())
{
char end = stPath[stPath.length() - 1];
if (end != '\\')
stPath+='\\';
}
std::string stQuery;
stQuery += stPath;
stQuery += "*.*";
m_wfd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
m_hFind = FindFirstFile(stQuery.c_str(), &m_wfd);
if (m_hFind == INVALID_HANDLE_VALUE)
return true;
do
{
if (*m_wfd.cFileName == '.')
continue;
if (IsFolder())
{
if (!OnFolder(c_szFilter, stPath.c_str(), m_wfd.cFileName))
return false;
}
else
{
const char * c_szExtension = strchr(m_wfd.cFileName, '.');
if (!c_szExtension)
continue;
// NOTE : 임시 변수 - [levites]
// 최종적으로는 무조건 TRUE 형태로 만든다.
// 그전에 전 프로젝트의 CDir을 사용하는 곳에서 Extension을 "wav", "gr2" 이런식으로 넣게끔 한다. - [levites]
if (bCheckedExtension)
{
std::string strFilter = c_szFilter;
int iPos = strFilter.find_first_of(';', 0);
if (iPos > 0)
{
std::string strFirstFilter = std::string(c_szFilter).substr(0, iPos);
std::string strSecondFilter = std::string(c_szFilter).substr(iPos+1, strlen(c_szFilter));
if (0 != strFirstFilter.compare(c_szExtension+1) && 0 != strSecondFilter.compare(c_szExtension+1))
continue;
}
else
{
if (0 != stricmp(c_szExtension+1, c_szFilter))
continue;
}
}
if (!OnFile(stPath.c_str(), m_wfd.cFileName))
return false;
}
}
while (FindNextFile(m_hFind, &m_wfd));
return true;
}
bool CDir::IsFolder()
{
if (m_wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
return true;
return false;
}
void CDir::Initialize()
{
memset(&m_wfd, 0, sizeof(m_wfd));
m_hFind = NULL;
}
@@ -0,0 +1,23 @@
// Platform implementation of EterBase/TempFile.h (40250 EterBase/TempFile.cpp): the 40250 code as is; the file
// name comes from the platform CreateTempFileName and DeleteFile is the common/Win32Crt.h shim.
#include "EterBase/StdAfx.h"
#include "EterBase/TempFile.h"
#include "EterBase/Utils.h"
#include "EterBase/Debug.h"
CTempFile::~CTempFile()
{
Destroy();
DeleteFile(m_szFileName);
}
CTempFile::CTempFile(const char * c_pszPrefix)
{
strncpy(m_szFileName, CreateTempFileName(c_pszPrefix), MAX_PATH);
if (!Create(m_szFileName, CFileBase::FILEMODE_WRITE))
{
TraceError("CTempFile::CTempFile cannot create temporary file. (filename: %s)", m_szFileName);
return;
}
}
@@ -3,6 +3,8 @@
#include "UIRenderCommands.h"
#include "CpuBuffer.h"
#include <algorithm>
#include <cmath>
#include <cstring>
#include <mutex>
@@ -52,6 +54,148 @@ void copy_color(float out[4], const D3DCOLORVALUE& c)
out[0] = c.r; out[1] = c.g; out[2] = c.b; out[3] = c.a;
}
int format_bytes(D3DFORMAT format)
{
switch (format)
{
case D3DFMT_A4R4G4B4: case D3DFMT_R5G6B5: case D3DFMT_A1R5G5B5: case D3DFMT_X1R5G5B5: case D3DFMT_X4R4G4B4:
case D3DFMT_D16: case D3DFMT_D16_LOCKABLE:
return 2;
case D3DFMT_A8: case D3DFMT_L8:
return 1;
default:
return 4;
}
}
// PORT: device-created resources live in CPU memory with D3D reference counting. Textures made by
// CreateTexture (CTerrain's splat alpha maps and attribute marks, CSnowEnvironment's blur targets)
// keep their mip levels as bytes; nothing samples them because terrain and offscreen passes are
// drawn by the Godot side.
struct CpuTexture;
struct CpuSurface final : IDirect3DSurface8
{
ULONG refs = 1;
CpuTexture* parent = nullptr; // a texture level, or null for a standalone surface
UINT level = 0;
D3DSURFACE_DESC desc = {};
std::vector<uint8_t> bytes; // standalone surfaces only
ULONG AddRef() override { return ++refs; }
ULONG Release() override;
HRESULT GetDesc(D3DSURFACE_DESC* out) override { *out = desc; return S_OK; }
HRESULT LockRect(D3DLOCKED_RECT* locked, const RECT*, DWORD) override;
HRESULT UnlockRect() override { return S_OK; }
};
struct CpuTexture final : IDirect3DTexture8
{
struct Level { D3DSURFACE_DESC desc; std::vector<uint8_t> bytes; };
ULONG refs = 1;
std::vector<Level> levels;
ULONG AddRef() override { return ++refs; }
ULONG Release() override
{
const ULONG left = --refs;
if (!left)
delete this;
return left;
}
DWORD GetLevelCount() override { return DWORD(levels.size()); }
HRESULT GetLevelDesc(UINT level, D3DSURFACE_DESC* out) override
{
if (level >= levels.size())
return E_FAIL;
*out = levels[level].desc;
return S_OK;
}
HRESULT GetSurfaceLevel(UINT level, IDirect3DSurface8** out) override
{
if (level >= levels.size())
return E_FAIL;
auto* surface = new CpuSurface();
surface->parent = this;
surface->level = level;
surface->desc = levels[level].desc;
AddRef();
*out = surface;
return S_OK;
}
HRESULT LockRect(UINT level, D3DLOCKED_RECT* locked, const RECT*, DWORD) override
{
if (level >= levels.size())
return E_FAIL;
locked->Pitch = INT(levels[level].desc.Width * format_bytes(levels[level].desc.Format));
locked->pBits = levels[level].bytes.data();
return S_OK;
}
HRESULT UnlockRect(UINT level) override { return level < levels.size() ? S_OK : E_FAIL; }
};
ULONG CpuSurface::Release()
{
const ULONG left = --refs;
if (!left)
{
if (parent)
parent->Release();
delete this;
}
return left;
}
HRESULT CpuSurface::LockRect(D3DLOCKED_RECT* locked, const RECT* rect, DWORD flags)
{
if (parent)
return parent->LockRect(level, locked, rect, flags);
locked->Pitch = INT(desc.Width * format_bytes(desc.Format));
locked->pBits = bytes.data();
return S_OK;
}
D3DSURFACE_DESC surface_desc(UINT width, UINT height, D3DFORMAT format, DWORD usage, D3DPOOL pool)
{
D3DSURFACE_DESC desc = {};
desc.Format = format;
desc.Type = D3DRTYPE_SURFACE;
desc.Usage = usage;
desc.Pool = pool;
desc.Size = width * height * format_bytes(format);
desc.MultiSampleType = D3DMULTISAMPLE_NONE;
desc.Width = width;
desc.Height = height;
return desc;
}
struct DeviceVertexBuffer final : MtCpuVertexBuffer
{
ULONG refs = 1;
ULONG AddRef() override { return ++refs; }
ULONG Release() override
{
const ULONG left = --refs;
if (!left)
delete this;
return left;
}
};
struct DeviceIndexBuffer final : MtCpuIndexBuffer
{
ULONG refs = 1;
ULONG AddRef() override { return ++refs; }
ULONG Release() override
{
const ULONG left = --refs;
if (!left)
delete this;
return left;
}
};
class RecordingDevice final : public IDirect3DDevice8
{
public:
@@ -63,6 +207,23 @@ public:
std::memset(&m_material, 0, sizeof(m_material));
m_material.Diffuse = { 1, 1, 1, 1 };
std::memset(m_lights, 0, sizeof(m_lights));
auto* backBuffer = new CpuSurface();
backBuffer->desc = surface_desc(width, height, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT);
m_backBuffer = backBuffer;
auto* depthBuffer = new CpuSurface();
depthBuffer->desc = surface_desc(width, height, D3DFMT_D16, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT);
m_depthBuffer = depthBuffer;
m_renderTarget = m_backBuffer;
m_renderTarget->AddRef();
m_depthStencil = m_depthBuffer;
m_depthStencil->AddRef();
}
~RecordingDevice() override
{
m_renderTarget->Release();
m_depthStencil->Release();
m_backBuffer->Release();
m_depthBuffer->Release();
}
ULONG AddRef() override { return ++m_refs; }
@@ -120,6 +281,84 @@ public:
m_lights[index] = *light;
return S_OK;
}
HRESULT LightEnable(DWORD index, BOOL enable) override
{
if (index < 8)
m_lightEnabled[index] = enable != FALSE;
return S_OK;
}
HRESULT CreateTexture(UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DTexture8** out) override
{
if (!width || !height)
return E_FAIL;
auto* texture = new CpuTexture();
// Levels == 0 builds the full chain down to 1x1.
for (UINT w = width, h = height; ; w = std::max(1u, w / 2), h = std::max(1u, h / 2))
{
CpuTexture::Level level;
level.desc = surface_desc(w, h, format, usage, pool);
level.bytes.resize(level.desc.Size);
texture->levels.push_back(std::move(level));
if ((levels && texture->levels.size() == levels) || (w == 1 && h == 1))
break;
}
*out = texture;
return S_OK;
}
HRESULT CreateVertexBuffer(UINT length, DWORD, DWORD fvf, D3DPOOL, IDirect3DVertexBuffer8** out) override
{
auto* buffer = new DeviceVertexBuffer();
buffer->bytes.resize(length);
buffer->fvf = fvf;
*out = buffer;
return S_OK;
}
HRESULT CreateIndexBuffer(UINT length, DWORD, D3DFORMAT format, D3DPOOL, IDirect3DIndexBuffer8** out) override
{
auto* buffer = new DeviceIndexBuffer();
buffer->bytes.resize(length);
buffer->format = format;
*out = buffer;
return S_OK;
}
HRESULT CreateDepthStencilSurface(UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE, IDirect3DSurface8** out) override
{
auto* surface = new CpuSurface();
surface->desc = surface_desc(width, height, format, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT);
*out = surface;
return S_OK;
}
HRESULT GetRenderTarget(IDirect3DSurface8** out) override
{
m_renderTarget->AddRef();
*out = m_renderTarget;
return S_OK;
}
HRESULT GetDepthStencilSurface(IDirect3DSurface8** out) override
{
m_depthStencil->AddRef();
*out = m_depthStencil;
return S_OK;
}
// PORT: an offscreen target (CSnowEnvironment's blur pass) swallows its draws; only the back
// buffer's draws are recorded for the Godot renderer.
HRESULT SetRenderTarget(IDirect3DSurface8* target, IDirect3DSurface8* depth) override
{
if (target)
{
target->AddRef();
m_renderTarget->Release();
m_renderTarget = target;
}
if (depth)
{
depth->AddRef();
m_depthStencil->Release();
m_depthStencil = depth;
}
return S_OK;
}
HRESULT Clear(DWORD, const D3DRECT*, DWORD, D3DCOLOR, float, DWORD) override { return S_OK; }
HRESULT SetRenderState(D3DRENDERSTATETYPE state, DWORD value) override
{
if (unsigned(state) < kRenderStates)
@@ -237,10 +476,118 @@ private:
return true;
}
static void transform_point(const float v[4], const float m[16], float out[4])
{
for (int c = 0; c < 4; ++c)
out[c] = v[0] * m[c] + v[1] * m[4 + c] + v[2] * m[8 + c] + v[3] * m[12 + c];
}
static void multiply(const float a[16], const float b[16], float out[16])
{
for (int r = 0; r < 4; ++r)
transform_point(&a[r * 4], b, &out[r * 4]);
}
// Each two-triangle quad of a UI-space draw becomes an image command: its screen corners through
// world * view * projection, its stage-0 texture (or D3DTA_TFACTOR colour when stage 0 selects it)
// and, when stage 1 generates coordinates from the camera-space position through D3DTS_TEXTURE1
// (the minimap's circular filter), the mask's coordinates at the corners.
void record_ui_quads(D3DPRIMITIVETYPE type, const uint8_t* vertices, size_t vertexBytes, UINT stride,
const VertexLayout& layout, const std::vector<std::uint32_t>& indices)
{
if (layout.uv0 < 0)
return;
unsigned width = 0, height = 0;
UIRenderGetSize(&width, &height);
float worldView[16], worldViewProj[16];
multiply(m_transforms[256], m_transforms[D3DTS_VIEW], worldView);
multiply(worldView, m_transforms[D3DTS_PROJECTION], worldViewProj);
const DWORD* stage0 = m_stageStates[0];
const DWORD* stage1 = m_stageStates[1];
const bool factorColor = stage0[D3DTSS_COLOROP] == D3DTOP_SELECTARG1 && stage0[D3DTSS_COLORARG1] == D3DTA_TFACTOR;
const std::uint32_t argb = factorColor ? (0xFF000000u | (m_renderStates[D3DRS_TEXTUREFACTOR] & 0x00FFFFFFu)) : 0xFFFFFFFFu;
const bool masked = m_textures[1] && (stage1[D3DTSS_TEXCOORDINDEX] & 0xFFFF0000u) == D3DTSS_TCI_CAMERASPACEPOSITION &&
stage1[D3DTSS_TEXTURETRANSFORMFLAGS] == D3DTTFF_COUNT2 && stage1[D3DTSS_COLOROP] == D3DTOP_MODULATE &&
stage1[D3DTSS_ALPHAOP] == D3DTOP_SELECTARG1 && stage1[D3DTSS_ALPHAARG1] == D3DTA_TEXTURE;
const std::string texture = factorColor ? std::string() : UIRenderTextureNameFromHandle(m_textures[0]);
const std::string mask = masked ? UIRenderTextureNameFromHandle(m_textures[1]) : std::string();
std::vector<std::vector<std::uint32_t>> quads;
if (type == D3DPT_TRIANGLELIST)
for (size_t i = 0; i + 6 <= indices.size(); i += 6)
quads.push_back({ indices.begin() + i, indices.begin() + i + 6 });
else if (type == D3DPT_TRIANGLESTRIP && indices.size() == 4)
quads.push_back(indices);
for (const auto& quad : quads)
{
std::vector<std::uint32_t> corners;
for (std::uint32_t index : quad)
if (std::find(corners.begin(), corners.end(), index) == corners.end())
corners.push_back(index);
if (corners.size() != 4)
continue;
float sx[4], sy[4], u[4], v[4], mu[4] = {}, mv[4] = {};
bool inside = true;
for (int i = 0; i < 4; ++i)
{
const size_t offset = size_t(corners[i]) * stride;
if (offset + stride > vertexBytes) { inside = false; break; }
const uint8_t* vertex = vertices + offset;
float position[4] = { 0, 0, 0, 1 }, clip[4], camera[4], coord[4];
std::memcpy(position, vertex, 12);
std::memcpy(&u[i], vertex + layout.uv0, 4);
std::memcpy(&v[i], vertex + layout.uv0 + 4, 4);
transform_point(position, worldViewProj, clip);
if (clip[3] == 0.0f) { inside = false; break; }
sx[i] = (clip[0] / clip[3] * 0.5f + 0.5f) * float(width);
sy[i] = (0.5f - clip[1] / clip[3] * 0.5f) * float(height);
if (masked)
{
transform_point(position, worldView, camera);
camera[3] = 1.0f;
transform_point(camera, m_transforms[D3DTS_TEXTURE1], coord);
mu[i] = coord[0];
mv[i] = coord[1];
}
}
if (!inside)
continue;
UIRenderCommand command{UIRenderCommand::Image, 0, 0, 0, 0, argb};
command.su = *std::min_element(u, u + 4); command.eu = *std::max_element(u, u + 4);
command.sv = *std::min_element(v, v + 4); command.ev = *std::max_element(v, v + 4);
// Corners in the command's TL, TR, BL, BR order, by texture coordinate.
const float cu[4] = { command.su, command.eu, command.su, command.eu };
const float cv[4] = { command.sv, command.sv, command.ev, command.ev };
for (int c = 0; c < 4; ++c)
{
int best = 0;
float bestDistance = INFINITY;
for (int i = 0; i < 4; ++i)
{
const float distance = std::fabs(u[i] - cu[c]) + std::fabs(v[i] - cv[c]);
if (distance < bestDistance) { bestDistance = distance; best = i; }
}
command.qx[c] = sx[best]; command.qy[c] = sy[best];
command.mu[c] = mu[best]; command.mv[c] = mv[best];
}
command.x1 = *std::min_element(command.qx, command.qx + 4);
command.y1 = *std::min_element(command.qy, command.qy + 4);
command.x2 = *std::max_element(command.qx, command.qx + 4);
command.y2 = *std::max_element(command.qy, command.qy + 4);
command.text = texture;
command.quad = true;
command.mask = mask;
UIRenderAdd(std::move(command));
}
}
void record(D3DPRIMITIVETYPE type, UINT primitives, const uint8_t* vertices, size_t vertexBytes, UINT stride,
const std::vector<std::uint32_t>& indices)
{
if (type == D3DPT_POINTLIST || indices.empty() || !vertices)
if (type == D3DPT_POINTLIST || indices.empty() || !vertices || m_renderTarget != m_backBuffer)
return;
VertexLayout layout = fvf_layout(m_fvf);
if (!stride)
@@ -253,6 +600,14 @@ private:
if (layout.uv0 + 8 > int(stride)) layout.uv0 = -1;
if (layout.uv1 + 8 > int(stride)) layout.uv1 = -1;
// An orthographic projection over untransformed vertices is a UI-space draw (CPythonMiniMap's
// terrain tiles under CPythonGraphic::SetOrtho2D): it joins the UI command stream in order.
if (!layout.rhw && m_transforms[D3DTS_PROJECTION][11] == 0.0f)
{
record_ui_quads(type, vertices, vertexBytes, stride, layout, indices);
return;
}
Render3DDraw draw;
std::memcpy(draw.world, m_transforms[256], sizeof(draw.world)); // D3DTS_WORLD
std::memcpy(draw.view, m_transforms[D3DTS_VIEW], sizeof(draw.view));
@@ -340,7 +695,7 @@ private:
copy_color(draw.material_diffuse, m_material.Diffuse);
copy_color(draw.material_ambient, m_material.Ambient);
copy_color(draw.material_emissive, m_material.Emissive);
if (m_lights[0].Type == D3DLIGHT_DIRECTIONAL)
if (m_lightEnabled[0] && m_lights[0].Type == D3DLIGHT_DIRECTIONAL)
{
draw.light0 = true;
draw.light0_direction[0] = m_lights[0].Direction.x;
@@ -360,6 +715,11 @@ private:
IDirect3DBaseTexture8* m_textures[kStages] = {};
D3DMATERIAL8 m_material;
D3DLIGHT8 m_lights[8];
bool m_lightEnabled[8] = {};
IDirect3DSurface8* m_backBuffer = nullptr;
IDirect3DSurface8* m_depthBuffer = nullptr;
IDirect3DSurface8* m_renderTarget = nullptr;
IDirect3DSurface8* m_depthStencil = nullptr;
DWORD m_fvf = 0;
MtCpuVertexBuffer* m_stream = nullptr;
UINT m_streamStride = 0;
@@ -1,4 +1,6 @@
#include "EterLib/StdAfx.h"
#include "UIRenderCommands.h"
#include "EterLib/StateManager.h"
#include <algorithm>
@@ -39,10 +41,36 @@ void UIRenderRestoreClip() {
void UIRenderAddImage(const CGraphicTexture* texture, const float x[4], const float y[4],
float su, float sv, float eu, float ev, std::uint32_t argb, int blend) {
// 40250 draws the image quad through the device: the UI pass's world transform places it
// (identity except where a caller sets one, e.g. CPythonMiniMap::RenderAtlas's window offset) and a
// stage-0 MODULATE with D3DTA_TFACTOR tints it (the atlas's NPC/warp/waypoint marks).
D3DXMATRIX world;
D3DXMatrixIdentity(&world);
if (CStateManager* state = CStateManager::InstancePtr()) {
state->GetTransform(D3DTS_WORLD, &world);
DWORD op = 0, arg1 = 0, arg2 = 0;
state->GetTextureStageState(0, D3DTSS_COLOROP, &op);
state->GetTextureStageState(0, D3DTSS_COLORARG1, &arg1);
state->GetTextureStageState(0, D3DTSS_COLORARG2, &arg2);
if (op == D3DTOP_MODULATE && (arg1 == D3DTA_TFACTOR || arg2 == D3DTA_TFACTOR)) {
// TFACTOR x TEXTURE drops the vertex colour; TFACTOR x DIFFUSE scales it. The canvas
// multiplies the texture in.
const std::uint32_t factor = state->GetRenderState(D3DRS_TEXTUREFACTOR) & 0x00FFFFFFu;
const DWORD other = arg1 == D3DTA_TFACTOR ? arg2 : arg1;
if (other == D3DTA_DIFFUSE) {
std::uint32_t tinted = argb & 0xFF000000u;
for (int shift = 0; shift < 24; shift += 8)
tinted |= ((((argb >> shift) & 255) * ((factor >> shift) & 255) + 127) / 255) << shift;
argb = tinted;
} else {
argb = (argb & 0xFF000000u) | factor;
}
}
}
UIRenderCommand command{UIRenderCommand::Image, 0, 0, 0, 0, argb};
for (int i = 0; i < 4; ++i) {
command.qx[i] = x[i] + 0.5f;
command.qy[i] = y[i] + 0.5f;
command.qx[i] = x[i] * world._11 + y[i] * world._21 + world._41 + 0.5f;
command.qy[i] = x[i] * world._12 + y[i] * world._22 + world._42 + 0.5f;
}
command.x1 = std::min({command.qx[0], command.qx[1], command.qx[2], command.qx[3]});
command.y1 = std::min({command.qy[0], command.qy[1], command.qy[2], command.qy[3]});
@@ -18,6 +18,10 @@ struct UIRenderCommand {
float qx[4] = {}, qy[4] = {};
float su = 0, sv = 0, eu = 1, ev = 1;
int blend = 0; // CGraphicExpandedImageInstance::RENDERING_MODE_*
// A second texture stage that modulates the colour and replaces the alpha (40250 CPythonMiniMap's
// circular minimap_image_filter): the mask's texture coordinates at the quad's four corners.
std::string mask;
float mu[4] = {}, mv[4] = {};
};
// D3DXCOLOR (0..1 floats) -> the 0xAARRGGBB the commands carry.
@@ -0,0 +1,79 @@
// Platform implementation of 40250 GameLib/MapOutdoorCharacterShadow.cpp. The render-target lifecycle is
// the 40250 code as is; the shadow-map pass is not run (BeginRenderCharacterShadowToTexture reports it
// cannot render) because the terrain that samples the map is drawn by Godot, which casts its own
// character shadows (PORT-PLAN §3).
#include "GameLib/StdAfx.h"
#include "EterLib/StateManager.h"
#include "EterLib/Camera.h"
#include "GameLib/MapOutdoor.h"
static int recreate = false;
void CMapOutdoor::SetShadowTextureSize(WORD size)
{
if (m_wShadowMapSize != size)
{
recreate = true;
Tracenf("ShadowTextureSize changed %d -> %d", m_wShadowMapSize, size);
}
m_wShadowMapSize = size;
}
void CMapOutdoor::CreateCharacterShadowTexture()
{
extern bool GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW;
if (GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW)
return;
ReleaseCharacterShadowTexture();
if (IsLowTextureMemory())
SetShadowTextureSize(128);
m_ShadowMapViewport.X = 1;
m_ShadowMapViewport.Y = 1;
m_ShadowMapViewport.Width = m_wShadowMapSize - 2;
m_ShadowMapViewport.Height = m_wShadowMapSize - 2;
m_ShadowMapViewport.MinZ = 0.0f;
m_ShadowMapViewport.MaxZ = 1.0f;
if (FAILED(ms_lpd3dDevice->CreateTexture(m_wShadowMapSize, m_wShadowMapSize, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &m_lpCharacterShadowMapTexture)))
{
TraceError("CMapOutdoor Unable to create Character Shadow render target texture\n");
return;
}
if (FAILED(m_lpCharacterShadowMapTexture->GetSurfaceLevel(0, &m_lpCharacterShadowMapRenderTargetSurface)))
{
TraceError("CMapOutdoor Unable to GetSurfaceLevel Character Shadow render target texture\n");
return;
}
if (FAILED(ms_lpd3dDevice->CreateDepthStencilSurface(m_wShadowMapSize, m_wShadowMapSize, D3DFMT_D16, D3DMULTISAMPLE_NONE, &m_lpCharacterShadowMapDepthSurface)))
{
TraceError("CMapOutdoor Unable to create Character Shadow depth Surface\n");
return;
}
}
void CMapOutdoor::ReleaseCharacterShadowTexture()
{
SAFE_RELEASE(m_lpCharacterShadowMapRenderTargetSurface);
SAFE_RELEASE(m_lpCharacterShadowMapDepthSurface);
SAFE_RELEASE(m_lpCharacterShadowMapTexture);
}
// PORT: no shadow-map pass (see the file comment); CPythonBackground::RenderCharacterShadowToTexture
// then skips the shadow instances.
bool CMapOutdoor::BeginRenderCharacterShadowToTexture()
{
return false;
}
// PORT: nothing to restore when the pass did not begin.
void CMapOutdoor::EndRenderCharacterShadowToTexture()
{
}
@@ -0,0 +1,10 @@
// Platform implementation of 40250 GameLib/MapOutdoorRenderHTP.cpp (hardware-transform terrain patches).
// PORT: the Godot Metin2World adapter draws the terrain from the same .raw/.tga/tile data (PORT-PLAN §3):
// the recorder has no texture-coordinate generation or texture transforms, so the patch splat passes are
// not replayed through the D3D8 device.
#include "GameLib/StdAfx.h"
#include "GameLib/MapOutdoor.h"
void CMapOutdoor::__RenderTerrain_RenderHardwareTransformPatch()
{
}
@@ -0,0 +1,93 @@
// Platform implementation of 40250 GameLib/MapOutdoorRenderSTP.cpp (software-transform terrain patches).
// The vertex-buffer lifecycle is the 40250 code as is; the patch drawing is left to the Godot terrain
// (see MapOutdoorRenderHTP.cpp).
#include "GameLib/StdAfx.h"
#include "EterLib/StateManager.h"
#include "GameLib/MapOutdoor.h"
#include "GameLib/TerrainPatch.h"
struct SoftwareTransformPatch_SSplatVertex
{
D3DXVECTOR4 kPosition;
DWORD dwDiffuse;
DWORD dwSpecular;
D3DXVECTOR2 kTex1;
D3DXVECTOR2 kTex2;
};
// PORT: Godot draws the terrain (PORT-PLAN §3).
void CMapOutdoor::__RenderTerrain_RenderSoftwareTransformPatch()
{
}
void CMapOutdoor::__SoftwareTransformPatch_Initialize()
{
{
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::SPLAT_VB_NUM; ++uIndex)
m_kSTPD.m_pkVBSplat[uIndex]=NULL;
m_kSTPD.m_dwSplatPos=0;
}
{
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::NONE_VB_NUM; ++uIndex)
m_kSTPD.m_pkVBNone[uIndex]=NULL;
m_kSTPD.m_dwNonePos=0;
}
}
bool CMapOutdoor::__SoftwareTransformPatch_Create()
{
{
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::SPLAT_VB_NUM; ++uIndex)
{
assert(NULL==m_kSTPD.m_pkVBSplat[uIndex]);
if (FAILED(
ms_lpd3dDevice->CreateVertexBuffer(
sizeof(SoftwareTransformPatch_SSplatVertex)*CTerrainPatch::TERRAIN_VERTEX_COUNT,
D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX2,
D3DPOOL_SYSTEMMEM,
&m_kSTPD.m_pkVBSplat[uIndex]
)
)) return false;
}
}
{
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::NONE_VB_NUM; ++uIndex)
{
assert(NULL==m_kSTPD.m_pkVBNone[uIndex]);
if (FAILED(
ms_lpd3dDevice->CreateVertexBuffer(
sizeof(SoftwareTransformPatch_STVertex)*CTerrainPatch::TERRAIN_VERTEX_COUNT,
D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
D3DFVF_XYZRHW,
D3DPOOL_SYSTEMMEM,
&m_kSTPD.m_pkVBNone[uIndex]
)
)) return false;
}
}
return true;
}
void CMapOutdoor::__SoftwareTransformPatch_Destroy()
{
{
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::SPLAT_VB_NUM; ++uIndex)
{
if (m_kSTPD.m_pkVBSplat[uIndex])
m_kSTPD.m_pkVBSplat[uIndex]->Release();
}
}
{
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::NONE_VB_NUM; ++uIndex)
{
if (m_kSTPD.m_pkVBNone[uIndex])
m_kSTPD.m_pkVBNone[uIndex]->Release();
}
}
__SoftwareTransformPatch_Initialize();
}
@@ -0,0 +1,30 @@
// Platform implementation of 40250 GameLib/MapOutdoorWater.cpp. The water texture set is loaded as in
// 40250; the water surface itself is drawn by the Godot water adapter (PORT-PLAN §3).
#include "GameLib/StdAfx.h"
#include "EterLib/StateManager.h"
#include "EterLib/ResourceManager.h"
#include "GameLib/MapOutdoor.h"
#include "GameLib/TerrainPatch.h"
void CMapOutdoor::LoadWaterTexture()
{
UnloadWaterTexture();
char buf[256];
for (int i = 0; i < 30; ++i)
{
sprintf(buf, "d:/ymir Work/special/water/%02d.dds", i+1);
m_WaterInstances[i].SetImagePointer((CGraphicImage *) CResourceManager::Instance().GetResourcePointer(buf));
}
}
void CMapOutdoor::UnloadWaterTexture()
{
for (int i = 0; i < 30; ++i)
m_WaterInstances[i].Destroy();
}
// PORT: the water patches are drawn by the Godot side.
void CMapOutdoor::RenderWater()
{
}
@@ -1,79 +0,0 @@
// Platform skeleton for GameLib/SnowEnvironment.h (40250 GameLib/SnowEnvironment.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "GameLib/StdAfx.h"
#include "GameLib/SnowEnvironment.h"
#include "../PlatformStub.h"
CSnowEnvironment::CSnowEnvironment()
{
MT_PLATFORM_STUB();
}
CSnowEnvironment::~CSnowEnvironment()
{
MT_PLATFORM_STUB();
}
auto CSnowEnvironment::Create() -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CSnowEnvironment::Destroy() -> void
{
MT_PLATFORM_STUB();
}
auto CSnowEnvironment::Enable() -> void
{
MT_PLATFORM_STUB();
}
auto CSnowEnvironment::Disable() -> void
{
MT_PLATFORM_STUB();
}
auto CSnowEnvironment::Update(const D3DXVECTOR3 &) -> void
{
MT_PLATFORM_STUB();
}
auto CSnowEnvironment::Deform() -> void
{
MT_PLATFORM_STUB();
}
auto CSnowEnvironment::Render() -> void
{
MT_PLATFORM_STUB();
}
auto CSnowEnvironment::__Initialize() -> void
{
MT_PLATFORM_STUB();
}
auto CSnowEnvironment::__CreateBlurTexture() -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CSnowEnvironment::__CreateGeometry() -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CSnowEnvironment::__BeginBlur() -> void
{
MT_PLATFORM_STUB();
}
auto CSnowEnvironment::__ApplyBlur() -> void
{
MT_PLATFORM_STUB();
}
@@ -1,31 +0,0 @@
// Platform skeleton for GameLib/TerrainDecal.h (40250 GameLib/TerrainDecal.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "GameLib/StdAfx.h"
#include "GameLib/TerrainDecal.h"
#include "../PlatformStub.h"
CTerrainDecal::CTerrainDecal(CMapOutdoor *)
{
MT_PLATFORM_STUB();
}
CTerrainDecal::~CTerrainDecal()
{
MT_PLATFORM_STUB();
}
auto CTerrainDecal::Make(D3DXVECTOR3, D3DXVECTOR3, D3DXVECTOR3, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainDecal::Render() -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainDecal::SearchAffectedTerrainMesh(float, float, float, float, DWORD *, D3DXVECTOR3 *, D3DXVECTOR3 *) -> void
{
MT_PLATFORM_STUB();
}
@@ -1,118 +0,0 @@
// Platform skeleton for GameLib/TerrainPatch.h (40250 GameLib/TerrainPatch.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "GameLib/StdAfx.h"
#include "GameLib/TerrainPatch.h"
#include "../PlatformStub.h"
decltype(CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE) CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE{};
auto CTerrainPatch::Clear() -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainPatch::GetWaterFaceCount() -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
auto CTerrainPatch::SoftwareTransformPatch_UpdateTerrainLighting(DWORD, const D3DLIGHT8 &, const D3DMATERIAL8 &) -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainPatch::BuildTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex *) -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainPatch::BuildWaterVertexBuffer(SWaterVertex *, UINT) -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainPatch::__BuildHardwareTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex *) -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainPatch::__BuildSoftwareTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex *) -> void
{
MT_PLATFORM_STUB();
}
CTerrainPatch::SSoftwareTransformPatch::SSoftwareTransformPatch()
{
MT_PLATFORM_STUB();
}
CTerrainPatch::SSoftwareTransformPatch::~SSoftwareTransformPatch()
{
MT_PLATFORM_STUB();
}
auto CTerrainPatch::SSoftwareTransformPatch::Create() -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainPatch::SSoftwareTransformPatch::Destroy() -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainPatch::SSoftwareTransformPatch::__Initialize() -> void
{
MT_PLATFORM_STUB();
}
CTerrainPatchProxy::CTerrainPatchProxy()
{
MT_PLATFORM_STUB();
}
CTerrainPatchProxy::~CTerrainPatchProxy()
{
MT_PLATFORM_STUB();
}
auto CTerrainPatchProxy::Clear() -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainPatchProxy::SetCenterPosition(const D3DXVECTOR3 &) -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainPatchProxy::IsIn(const D3DXVECTOR3 &, float) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CTerrainPatchProxy::GetWaterFaceCount() -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
auto CTerrainPatchProxy::SoftwareTransformPatch_GetTerrainVertexDataPtr() -> SoftwareTransformPatch_SSourceVertex *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<SoftwareTransformPatch_SSourceVertex *>();
}
auto CTerrainPatchProxy::HardwareTransformPatch_GetVertexBufferPtr() -> CGraphicVertexBuffer *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<CGraphicVertexBuffer *>();
}
auto CTerrainPatchProxy::SoftwareTransformPatch_UpdateTerrainLighting(DWORD, const D3DLIGHT8 &, const D3DMATERIAL8 &) -> void
{
MT_PLATFORM_STUB();
}
@@ -1,80 +0,0 @@
// Platform skeleton for PRTerrainLib/Terrain.h (40250 PRTerrainLib/Terrain.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "PRTerrainLib/StdAfx.h"
#include "PRTerrainLib/Terrain.h"
#include "../PlatformStub.h"
auto CTerrainImpl::SetTextureSet(CTextureSet *) -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainImpl::GetTextureSet() -> CTextureSet *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<CTextureSet *>();
}
decltype(CTerrainImpl::ms_pTextureSet) CTerrainImpl::ms_pTextureSet{};
CTerrainImpl::CTerrainImpl()
{
MT_PLATFORM_STUB();
}
CTerrainImpl::~CTerrainImpl()
{
MT_PLATFORM_STUB();
}
auto CTerrainImpl::LoadWaterMap(const char *) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CTerrainImpl::LoadWaterMapFile(const char *) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CTerrainImpl::GetShadowMapColor(float, float) -> DWORD
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<DWORD>();
}
auto CTerrainImpl::Initialize() -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainImpl::Clear() -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainImpl::LoadTextures() -> void
{
MT_PLATFORM_STUB();
}
auto CTerrainImpl::LoadHeightMap(const char *) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CTerrainImpl::RAW_LoadTileMap(const char *) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CTerrainImpl::LoadAttrMap(const char *) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
@@ -1,83 +0,0 @@
// Platform skeleton for PRTerrainLib/TextureSet.h (40250 PRTerrainLib/TextureSet.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "PRTerrainLib/StdAfx.h"
#include "PRTerrainLib/TextureSet.h"
#include "../PlatformStub.h"
CTextureSet::CTextureSet()
{
MT_PLATFORM_STUB();
}
CTextureSet::~CTextureSet()
{
MT_PLATFORM_STUB();
}
auto CTextureSet::Initialize() -> void
{
MT_PLATFORM_STUB();
}
auto CTextureSet::Clear() -> void
{
MT_PLATFORM_STUB();
}
auto CTextureSet::Create() -> void
{
MT_PLATFORM_STUB();
}
auto CTextureSet::Load(const char *, float) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CTextureSet::Save(const char *) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CTextureSet::GetTextureCount() -> unsigned long
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<unsigned long>();
}
auto CTextureSet::GetTexture(unsigned long) -> TTerrainTexture &
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<TTerrainTexture &>();
}
auto CTextureSet::RemoveTexture(unsigned long) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CTextureSet::SetTexture(unsigned long, const char *, float, float, float, float, bool, unsigned short, unsigned short, float) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CTextureSet::Reload(float) -> void
{
MT_PLATFORM_STUB();
}
auto CTextureSet::AddTexture(const char *, float, float, float, float, bool, unsigned short, unsigned short, float) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CTextureSet::AddEmptyTexture() -> void
{
MT_PLATFORM_STUB();
}
@@ -35,36 +35,6 @@
#include "UserInterface/PythonTextTail.h"
// 40250 UserInterface/PythonBackgroundModule.cpp
void AddStubConstants_background(PyObject* poModule)
{
(void) poModule;
PyModule_AddIntConstant(poModule, "PART_SKY", CMapOutdoor::PART_SKY);
PyModule_AddIntConstant(poModule, "PART_TREE", CMapOutdoor::PART_TREE);
PyModule_AddIntConstant(poModule, "PART_CLOUD", CMapOutdoor::PART_CLOUD);
PyModule_AddIntConstant(poModule, "PART_WATER", CMapOutdoor::PART_WATER);
PyModule_AddIntConstant(poModule, "PART_OBJECT", CMapOutdoor::PART_OBJECT);
PyModule_AddIntConstant(poModule, "PART_TERRAIN", CMapOutdoor::PART_TERRAIN);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_DEFAULT", CSkyObject::SKY_RENDER_MODE_DEFAULT);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_DIFFUSE", CSkyObject::SKY_RENDER_MODE_DIFFUSE);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_TEXTURE", CSkyObject::SKY_RENDER_MODE_TEXTURE);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE", CSkyObject::SKY_RENDER_MODE_MODULATE);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE2X", CSkyObject::SKY_RENDER_MODE_MODULATE2X);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE4X", CSkyObject::SKY_RENDER_MODE_MODULATE4X);
PyModule_AddIntConstant(poModule, "SHADOW_NONE", CPythonBackground::SHADOW_NONE);
PyModule_AddIntConstant(poModule, "SHADOW_GROUND", CPythonBackground::SHADOW_GROUND);
PyModule_AddIntConstant(poModule, "SHADOW_GROUND_AND_SOLO", CPythonBackground::SHADOW_GROUND_AND_SOLO);
PyModule_AddIntConstant(poModule, "SHADOW_ALL", CPythonBackground::SHADOW_ALL);
PyModule_AddIntConstant(poModule, "SHADOW_ALL_HIGH", CPythonBackground::SHADOW_ALL_HIGH);
PyModule_AddIntConstant(poModule, "SHADOW_ALL_MAX", CPythonBackground::SHADOW_ALL_MAX);
PyModule_AddIntConstant(poModule, "DISTANCE0", CPythonBackground::DISTANCE0);
PyModule_AddIntConstant(poModule, "DISTANCE1", CPythonBackground::DISTANCE1);
PyModule_AddIntConstant(poModule, "DISTANCE2", CPythonBackground::DISTANCE2);
PyModule_AddIntConstant(poModule, "DISTANCE3", CPythonBackground::DISTANCE3);
PyModule_AddIntConstant(poModule, "DISTANCE4", CPythonBackground::DISTANCE4);
PyModule_AddIntConstant(poModule, "DISTANCE_SORT", CMapOutdoor::DISTANCE_SORT);
PyModule_AddIntConstant(poModule, "TEXTURE_SORT", CMapOutdoor::TEXTURE_SORT);
}
// 40250 UserInterface/PythonEventManagerMoudle.cpp
void AddStubConstants_event(PyObject* poModule)
{
@@ -5,7 +5,6 @@
#include "../EterLib/UIRenderCommands.h"
// GameplayModuleConstants.cpp: each module's 40250 constants.
void AddStubConstants_background(PyObject* poModule);
void AddStubConstants_event(PyObject* poModule);
void AddStubConstants_eventMgr(PyObject* poModule);
void AddStubConstants_guild(PyObject* poModule);
@@ -27,106 +26,6 @@ PyObject* stub_call_named(const char* name, PyObject* result = nullptr) {
return result ? result : Py_BuildValue("i", 0);
}
// 40250 UserInterface/PythonBackgroundModule.cpp: background export names.
PyObject* stub_background_IsSoftwareTiling(PyObject*, PyObject*) { return stub_call_named("background.IsSoftwareTiling", Py_BuildValue("i", 0)); }
PyObject* stub_background_EnableSoftwareTiling(PyObject*, PyObject*) { return stub_call_named("background.EnableSoftwareTiling", Py_BuildNone()); }
PyObject* stub_background_EnableSnow(PyObject*, PyObject*) { return stub_call_named("background.EnableSnow", Py_BuildNone()); }
PyObject* stub_background_GlobalPositionToLocalPosition(PyObject*, PyObject*) { return stub_call_named("background.GlobalPositionToLocalPosition", Py_BuildValue("ii", 0, 0)); }
PyObject* stub_background_GlobalPositionToMapInfo(PyObject*, PyObject*) { return stub_call_named("background.GlobalPositionToMapInfo", Py_BuildValue("sii", "", 0, 0)); }
PyObject* stub_background_GetRenderShadowTime(PyObject*, PyObject*) { return stub_call_named("background.GetRenderShadowTime", Py_BuildValue("i", 0)); }
PyObject* stub_background_LoadMap(PyObject*, PyObject*) { return stub_call_named("background.LoadMap", Py_BuildNone()); }
PyObject* stub_background_Destroy(PyObject*, PyObject*) { return stub_call_named("background.Destroy", Py_BuildNone()); }
PyObject* stub_background_RegisterEnvironmentData(PyObject*, PyObject*) { return stub_call_named("background.RegisterEnvironmentData", Py_BuildNone()); }
PyObject* stub_background_SetEnvironmentData(PyObject*, PyObject*) { return stub_call_named("background.SetEnvironmentData", Py_BuildNone()); }
PyObject* stub_background_GetCurrentMapName(PyObject*, PyObject*) { return stub_call_named("background.GetCurrentMapName", Py_BuildValue("s", "")); }
PyObject* stub_background_GetPickingPoint(PyObject*, PyObject*) { return stub_call_named("background.GetPickingPoint", Py_BuildValue("fff", 0.0, 0.0, 0.0)); }
PyObject* stub_background_BeginEnvironment(PyObject*, PyObject*) { return stub_call_named("background.BeginEnvironment", Py_BuildNone()); }
PyObject* stub_background_EndEnvironment(PyObject*, PyObject*) { return stub_call_named("background.EndEnvironment", Py_BuildNone()); }
PyObject* stub_background_SetCharacterDirLight(PyObject*, PyObject*) { return stub_call_named("background.SetCharacterDirLight", Py_BuildNone()); }
PyObject* stub_background_SetBackgroundDirLight(PyObject*, PyObject*) { return stub_call_named("background.SetBackgroundDirLight", Py_BuildNone()); }
PyObject* stub_background_Initialize(PyObject*, PyObject*) { return stub_call_named("background.Initialize", Py_BuildNone()); }
PyObject* stub_background_Update(PyObject*, PyObject*) { return stub_call_named("background.Update", Py_BuildNone()); }
PyObject* stub_background_Render(PyObject*, PyObject*) { return stub_call_named("background.Render", Py_BuildNone()); }
PyObject* stub_background_RenderPCBlocker(PyObject*, PyObject*) { return stub_call_named("background.RenderPCBlocker", Py_BuildNone()); }
PyObject* stub_background_RenderCollision(PyObject*, PyObject*) { return stub_call_named("background.RenderCollision", Py_BuildNone()); }
PyObject* stub_background_RenderSky(PyObject*, PyObject*) { return stub_call_named("background.RenderSky", Py_BuildNone()); }
PyObject* stub_background_RenderCloud(PyObject*, PyObject*) { return stub_call_named("background.RenderCloud", Py_BuildNone()); }
PyObject* stub_background_RenderWater(PyObject*, PyObject*) { return stub_call_named("background.RenderWater", Py_BuildNone()); }
PyObject* stub_background_RenderEffect(PyObject*, PyObject*) { return stub_call_named("background.RenderEffect", Py_BuildNone()); }
PyObject* stub_background_RenderBeforeLensFlare(PyObject*, PyObject*) { return stub_call_named("background.RenderBeforeLensFlare", Py_BuildNone()); }
PyObject* stub_background_RenderAfterLensFlare(PyObject*, PyObject*) { return stub_call_named("background.RenderAfterLensFlare", Py_BuildNone()); }
PyObject* stub_background_RenderCharacterShadowToTexture(PyObject*, PyObject*) { return stub_call_named("background.RenderCharacterShadowToTexture", Py_BuildNone()); }
PyObject* stub_background_RenderDungeon(PyObject*, PyObject*) { return stub_call_named("background.RenderDungeon", Py_BuildNone()); }
PyObject* stub_background_GetHeight(PyObject*, PyObject*) { return stub_call_named("background.GetHeight", Py_BuildValue("f", 0.0)); }
PyObject* stub_background_SetShadowLevel(PyObject*, PyObject*) { return stub_call_named("background.SetShadowLevel", Py_BuildNone()); }
PyObject* stub_background_SetVisiblePart(PyObject*, PyObject*) { return stub_call_named("background.SetVisiblePart", Py_BuildNone()); }
PyObject* stub_background_GetShadowMapColor(PyObject*, PyObject*) { return stub_call_named("background.GetShadowMapColor", Py_BuildValue("i", 0)); }
PyObject* stub_background_SetSplatLimit(PyObject*, PyObject*) { return stub_call_named("background.SetSplatLimit", Py_BuildNone()); }
PyObject* stub_background_GetRenderedSplatNum(PyObject*, PyObject*) { return stub_call_named("background.GetRenderedSplatNum", Py_BuildValue("iifs", 0, 0, 0.0, "")); }
PyObject* stub_background_GetRenderedGraphicThingInstanceNum(PyObject*, PyObject*) { return stub_call_named("background.GetRenderedGraphicThingInstanceNum", Py_BuildValue("ii", 0, 0)); }
PyObject* stub_background_SelectViewDistanceNum(PyObject*, PyObject*) { return stub_call_named("background.SelectViewDistanceNum", Py_BuildNone()); }
PyObject* stub_background_SetViewDistanceSet(PyObject*, PyObject*) { return stub_call_named("background.SetViewDistanceSet", Py_BuildNone()); }
PyObject* stub_background_GetFarClip(PyObject*, PyObject*) { return stub_call_named("background.GetFarClip", Py_BuildValue("f", 0.0)); }
PyObject* stub_background_GetDistanceSetInfo(PyObject*, PyObject*) { return stub_call_named("background.GetDistanceSetInfo", Py_BuildValue("ifff", 0, 0.0, 0.0, 0.0)); }
PyObject* stub_background_SetBGLoading(PyObject*, PyObject*) { return stub_call_named("background.SetBGLoading", Py_BuildNone()); }
PyObject* stub_background_SetRenderSort(PyObject*, PyObject*) { return stub_call_named("background.SetRenderSort", Py_BuildNone()); }
PyObject* stub_background_SetTransparentTree(PyObject*, PyObject*) { return stub_call_named("background.SetTransparentTree", Py_BuildNone()); }
PyObject* stub_background_SetXMasTree(PyObject*, PyObject*) { return stub_call_named("background.SetXMasTree", Py_BuildNone()); }
PyObject* stub_background_RegisterDungeonMapName(PyObject*, PyObject*) { return stub_call_named("background.RegisterDungeonMapName", Py_BuildNone()); }
PyObject* stub_background_VisibleGuildArea(PyObject*, PyObject*) { return stub_call_named("background.VisibleGuildArea", Py_BuildNone()); }
PyObject* stub_background_DisableGuildArea(PyObject*, PyObject*) { return stub_call_named("background.DisableGuildArea", Py_BuildNone()); }
PyObject* stub_background_WarpTest(PyObject*, PyObject*) { return stub_call_named("background.WarpTest", Py_BuildNone()); }
PyMethodDef methods_background[] = {
{ "IsSoftwareTiling", stub_background_IsSoftwareTiling, METH_VARARGS },
{ "EnableSoftwareTiling", stub_background_EnableSoftwareTiling, METH_VARARGS },
{ "EnableSnow", stub_background_EnableSnow, METH_VARARGS },
{ "GlobalPositionToLocalPosition", stub_background_GlobalPositionToLocalPosition, METH_VARARGS },
{ "GlobalPositionToMapInfo", stub_background_GlobalPositionToMapInfo, METH_VARARGS },
{ "GetRenderShadowTime", stub_background_GetRenderShadowTime, METH_VARARGS },
{ "LoadMap", stub_background_LoadMap, METH_VARARGS },
{ "Destroy", stub_background_Destroy, METH_VARARGS },
{ "RegisterEnvironmentData", stub_background_RegisterEnvironmentData, METH_VARARGS },
{ "SetEnvironmentData", stub_background_SetEnvironmentData, METH_VARARGS },
{ "GetCurrentMapName", stub_background_GetCurrentMapName, METH_VARARGS },
{ "GetPickingPoint", stub_background_GetPickingPoint, METH_VARARGS },
{ "BeginEnvironment", stub_background_BeginEnvironment, METH_VARARGS },
{ "EndEnvironment", stub_background_EndEnvironment, METH_VARARGS },
{ "SetCharacterDirLight", stub_background_SetCharacterDirLight, METH_VARARGS },
{ "SetBackgroundDirLight", stub_background_SetBackgroundDirLight, METH_VARARGS },
{ "Initialize", stub_background_Initialize, METH_VARARGS },
{ "Update", stub_background_Update, METH_VARARGS },
{ "Render", stub_background_Render, METH_VARARGS },
{ "RenderPCBlocker", stub_background_RenderPCBlocker, METH_VARARGS },
{ "RenderCollision", stub_background_RenderCollision, METH_VARARGS },
{ "RenderSky", stub_background_RenderSky, METH_VARARGS },
{ "RenderCloud", stub_background_RenderCloud, METH_VARARGS },
{ "RenderWater", stub_background_RenderWater, METH_VARARGS },
{ "RenderEffect", stub_background_RenderEffect, METH_VARARGS },
{ "RenderBeforeLensFlare", stub_background_RenderBeforeLensFlare, METH_VARARGS },
{ "RenderAfterLensFlare", stub_background_RenderAfterLensFlare, METH_VARARGS },
{ "RenderCharacterShadowToTexture", stub_background_RenderCharacterShadowToTexture, METH_VARARGS },
{ "RenderDungeon", stub_background_RenderDungeon, METH_VARARGS },
{ "GetHeight", stub_background_GetHeight, METH_VARARGS },
{ "SetShadowLevel", stub_background_SetShadowLevel, METH_VARARGS },
{ "SetVisiblePart", stub_background_SetVisiblePart, METH_VARARGS },
{ "GetShadowMapColor", stub_background_GetShadowMapColor, METH_VARARGS },
{ "SetSplatLimit", stub_background_SetSplatLimit, METH_VARARGS },
{ "GetRenderedSplatNum", stub_background_GetRenderedSplatNum, METH_VARARGS },
{ "GetRenderedGraphicThingInstanceNum", stub_background_GetRenderedGraphicThingInstanceNum, METH_VARARGS },
{ "SelectViewDistanceNum", stub_background_SelectViewDistanceNum, METH_VARARGS },
{ "SetViewDistanceSet", stub_background_SetViewDistanceSet, METH_VARARGS },
{ "GetFarClip", stub_background_GetFarClip, METH_VARARGS },
{ "GetDistanceSetInfo", stub_background_GetDistanceSetInfo, METH_VARARGS },
{ "SetBGLoading", stub_background_SetBGLoading, METH_VARARGS },
{ "SetRenderSort", stub_background_SetRenderSort, METH_VARARGS },
{ "SetTransparentTree", stub_background_SetTransparentTree, METH_VARARGS },
{ "SetXMasTree", stub_background_SetXMasTree, METH_VARARGS },
{ "RegisterDungeonMapName", stub_background_RegisterDungeonMapName, METH_VARARGS },
{ "VisibleGuildArea", stub_background_VisibleGuildArea, METH_VARARGS },
{ "DisableGuildArea", stub_background_DisableGuildArea, METH_VARARGS },
{ "WarpTest", stub_background_WarpTest, METH_VARARGS },
{ NULL, NULL }
};
// 40250 UserInterface/PythonEventManagerMoudle.cpp: event export names.
PyObject* stub_event_RegisterEventSet(PyObject*, PyObject*) { return stub_call_named("event.RegisterEventSet", Py_BuildValue("i", 0)); }
PyObject* stub_event_RegisterEventSetFromString(PyObject*, PyObject*) { return stub_call_named("event.RegisterEventSetFromString", Py_BuildValue("i", 0)); }
@@ -557,11 +456,6 @@ PyMethodDef methods_udp[] = {
} // namespace
void init_2v0_gameplay_stubs() {
{
PyObject* module = Py_InitModule("background", methods_background);
PyModule_AddIntConstant(module, "__port_stub__", 1);
AddStubConstants_background(module);
}
{
PyObject* module = Py_InitModule("event", methods_event);
PyModule_AddIntConstant(module, "__port_stub__", 1);
@@ -359,6 +359,7 @@ bool run_main_script_body(const char* lpCmdLine, std::string* error)
initeffect();
initfly();
initskill();
initBackground();
initServerStateChecker();
init_2v0_gameplay_stubs();
@@ -1,362 +0,0 @@
// Stand-in for the 40250 logic unit GameLib/MapManager.cpp, not ported yet: the members the ported units
// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/
// (docs/PORT-PLAN.md).
#include "GameLib/StdAfx.h"
#include "GameLib/MapManager.h"
#include "EterPack/EterPackManager.h"
#include "EterBase/MappedFile.h"
#include "EterLib/StateManager.h"
#include "GameLib/MapUtil.h"
#include <map_setting.h>
#include <terrain_files.h>
#include <terrain_mesh.h>
#include <algorithm>
#include <cmath>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include "../../PlatformStub.h"
namespace {
// PORT: The Godot terrain adapter owns drawing until CMapOutdoor is ported. This
// pack-backed state supplies its 40250 callers with the same height and .msenv
// data during that transition; it is not a CMapOutdoor port.
struct NativeMapState {
fmt::MapSetting setting;
std::string name;
std::map<std::pair<int, int>, fmt::HeightMap> heights;
std::map<std::pair<int, int>, std::vector<BYTE>> attrs; // attr.atr payload, empty when unreadable
bool ready = false;
};
std::map<const CMapManager *, NativeMapState> s_native_maps;
bool pack_bytes(const std::string &name, std::string &out)
{
CMappedFile file;
LPCVOID data = nullptr;
if (!CEterPackManager::Instance().Get(file, name.c_str(), &data))
return false;
out.assign(static_cast<const char *>(data), file.Size());
return true;
}
bool load_height_tile(NativeMapState &state, int tx, int ty)
{
if (tx < 0 || ty < 0 || tx >= state.setting.map_size_x || ty >= state.setting.map_size_y)
return false;
const auto key = std::make_pair(tx, ty);
if (state.heights.find(key) != state.heights.end())
return true;
char tile[16];
snprintf(tile, sizeof(tile), "%03d%03d", tx, ty);
std::string bytes;
if (!pack_bytes(state.name + "/" + tile + "/height.raw", bytes) || bytes.size() != 131 * 131 * 2)
return false;
fmt::HeightMap map;
map.raw.resize(131 * 131);
for (size_t i = 0; i < map.raw.size(); ++i)
map.raw[i] = static_cast<unsigned char>(bytes[i * 2]) |
(static_cast<unsigned char>(bytes[i * 2 + 1]) << 8);
state.heights.emplace(key, std::move(map));
return true;
}
// attr.atr: {u16 magic=2634, u16 w=256, u16 h=256} + 256*256 bytes (40250 CTerrainImpl::LoadAttrMap).
const std::vector<BYTE> *attr_tile(NativeMapState &state, int tx, int ty)
{
if (tx < 0 || ty < 0 || tx >= state.setting.map_size_x || ty >= state.setting.map_size_y)
return nullptr;
const auto key = std::make_pair(tx, ty);
auto found = state.attrs.find(key);
if (found == state.attrs.end())
{
char tile[16];
snprintf(tile, sizeof(tile), "%03d%03d", tx, ty);
std::string bytes;
std::vector<BYTE> attr;
const size_t payload = size_t(CTerrainImpl::ATTRMAP_XSIZE) * CTerrainImpl::ATTRMAP_YSIZE;
if (pack_bytes(state.name + "/" + tile + "/attr.atr", bytes) && bytes.size() == 6 + payload &&
(static_cast<unsigned char>(bytes[0]) | (static_cast<unsigned char>(bytes[1]) << 8)) == 2634)
attr.assign(bytes.begin() + 6, bytes.end());
found = state.attrs.emplace(key, std::move(attr)).first;
}
return found->second.empty() ? nullptr : &found->second;
}
}
// CMapOutdoor::GetHeight is max(terrain, object height under CCullingManager); no map objects are registered
// until CMapOutdoor is ported, so it is the terrain height.
auto CMapManager::GetHeight(float fx, float fy) -> float
{
return GetTerrainHeight(fx, fy);
}
// CMapOutdoor::GetTerrainHeight over the native height tiles.
auto CMapManager::GetTerrainHeight(float fx, float fy) -> float
{
auto found = s_native_maps.find(this);
if (found == s_native_maps.end() || !found->second.ready)
return 0.0f;
NativeMapState &state = found->second;
const double x = fx, y = std::abs(double(fy));
if (x < 0 || y < 0)
return 0.0f;
const int tx = int(x / 25600.0), ty = int(y / 25600.0);
if (!load_height_tile(state, tx, ty))
return 0.0f;
const float height = float(fmt::terrain_height_at(state.heights.at({tx, ty}), x - tx * 25600.0,
y - ty * 25600.0, state.setting.height_scale));
return height;
}
// CMapOutdoor::GetNormal → CTerrain::GetNormal. 40250 fills CTerrain::m_acNormalMap at LoadHeightMap with
// CTerrain::CalculateNormal and reads the cell's byte triple; the same formula runs here per call on the
// cached height tile (GetHeightMapValue = raw[(y+1)*131 + x+1]).
bool CMapManager::GetNormal(int ix, int iy, D3DXVECTOR3 * pv3Normal)
{
auto found = s_native_maps.find(this);
if (found == s_native_maps.end() || !found->second.ready)
return false;
NativeMapState &state = found->second;
const int count_x = state.setting.map_size_x, count_y = state.setting.map_size_y;
ix = std::clamp(ix, 0, count_x * CTerrainImpl::TERRAIN_XSIZE);
iy = std::clamp(iy, 0, count_y * CTerrainImpl::TERRAIN_YSIZE);
const int tx = std::min(ix / CTerrainImpl::TERRAIN_XSIZE, count_x - 1);
const int ty = std::min(iy / CTerrainImpl::TERRAIN_YSIZE, count_y - 1);
if (!load_height_tile(state, tx, ty))
return false;
while (ix >= CTerrainImpl::TERRAIN_XSIZE)
ix -= CTerrainImpl::TERRAIN_XSIZE;
while (iy >= CTerrainImpl::TERRAIN_YSIZE)
iy -= CTerrainImpl::TERRAIN_YSIZE;
const int x = ix / CTerrainImpl::CELLSCALE, y = iy / CTerrainImpl::CELLSCALE;
const std::vector<uint16_t> &raw = state.heights.at({tx, ty}).raw;
auto height = [&](int sx, int sy) {
return float(raw[(sy + 1) * CTerrainImpl::HEIGHTMAP_RAW_XSIZE + sx + 1]);
};
D3DXVECTOR3 normal;
normal.x = -state.setting.height_scale * (height(x - 1, y) - height(x + 1, y));
normal.y = -state.setting.height_scale * (height(x, y - 1) - height(x, y + 1));
normal.z = 2.0f * static_cast<float>(CTerrainImpl::CELLSCALE);
normal *= 127.0f / D3DXVec3Length(&normal);
// PR_FLOAT_TO_INT (fistp, then one down when it rounded up) into the char normal map.
const signed char n[3] = {
static_cast<signed char>(int(std::floor(normal.x))),
static_cast<signed char>(int(std::floor(normal.y))),
static_cast<signed char>(int(std::floor(normal.z))),
};
pv3Normal->x = -((float)n[0]) * 0.007874016f;
pv3Normal->y = ((float)n[1]) * 0.007874016f;
pv3Normal->z = ((float)n[2]) * 0.007874016f;
return true;
}
CMapManager::CMapManager() : mc_pcurEnvironmentData(NULL)
{
m_pkMap = NULL;
m_isSoftwareTilingEnableReserved=false;
// Initialize();
}
CMapManager::~CMapManager()
{
Destroy();
}
void CMapManager::Initialize()
{
mc_pcurEnvironmentData = NULL;
__LoadMapInfoVector();
}
void CMapManager::Create()
{
// PORT: CMapOutdoor is still rendered by Metin2World, not this native object.
}
void CMapManager::Destroy()
{
Clear();
for (auto &entry : m_EnvironmentDataMap)
delete entry.second;
m_EnvironmentDataMap.clear();
}
void CMapManager::__LoadMapInfoVector()
{
std::string bytes;
if (!pack_bytes(m_stAtlasInfoFileName, bytes) && !pack_bytes("AtlasInfo.txt", bytes))
return;
std::istringstream lines(bytes);
std::string line;
m_kVct_kMapInfo.clear();
while (std::getline(lines, line)) {
std::istringstream fields(line);
TMapInfo info{};
if (!(fields >> info.m_strName >> info.m_dwBaseX >> info.m_dwBaseY >> info.m_dwSizeX >> info.m_dwSizeY))
continue;
info.m_dwEndX = info.m_dwBaseX + info.m_dwSizeX * 25600;
info.m_dwEndY = info.m_dwBaseY + info.m_dwSizeY * 25600;
m_kVct_kMapInfo.push_back(info);
}
}
auto CMapManager::Clear() -> void
{
s_native_maps.erase(this);
mc_pcurEnvironmentData = NULL;
}
auto CMapManager::AllocMap() -> CMapBase *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<CMapBase *>();
}
auto CMapManager::LoadMap(const std::string &name, float x, float y, float) -> bool
{
NativeMapState next;
next.name = name;
std::string bytes, error;
if (!pack_bytes(name + "/setting.txt", bytes) || !fmt::parse_map_setting(bytes, next.setting, &error)) {
TraceError("native map setting failed: %s (%s)", name.c_str(), error.c_str());
return false;
}
if (!load_height_tile(next, int(x / 25600.0f), int(y / 25600.0f))) {
TraceError("native map height tile failed: %s (%d,%d)", name.c_str(), int(x / 25600.0f), int(y / 25600.0f));
return false;
}
for (auto &entry : m_EnvironmentDataMap)
delete entry.second;
m_EnvironmentDataMap.clear();
mc_pcurEnvironmentData = NULL;
if (!next.setting.environment.empty()) {
auto env = std::make_unique<TEnvironmentData>();
Environment_Init(*env);
const std::string env_path = "d:/ymir work/environment/" + next.setting.environment;
if (Environment_Load(*env, env_path.c_str())) {
m_EnvironmentDataMap[0] = env.release();
mc_pcurEnvironmentData = m_EnvironmentDataMap[0];
} else {
TraceError("native map environment failed: %s", env_path.c_str());
}
}
next.ready = true;
s_native_maps[this] = std::move(next);
return true;
}
auto CMapManager::isPhysicalCollision(const D3DXVECTOR3 &) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CMapManager::GetWaterHeight(int, int, long *) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CMapManager::GetShadowMapColor(float, float) -> DWORD
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<DWORD>();
}
// 40250 MapManager.cpp:506 → CMapOutdoor::isAttrOn (MapOutdoor.cpp:1202).
bool CMapManager::isAttrOn(float fX, float fY, BYTE byAttr)
{
if (!IsMapReady())
return false;
// PORT: PR_FLOAT_TO_INT is x87 fistp (round to nearest) corrected down, i.e. floor.
return isAttrOn(int(std::floor(fX)), int(std::floor(fY)), byAttr);
}
// 40250 MapManager.cpp:524 → CMapOutdoor::isAttrOn (MapOutdoor.cpp:1220) → CTerrain::isAttrOn (AreaTerrain.cpp:487).
// PORT: CMapOutdoor/CTerrain are not ported; the terrain count and the attribute map come from the native map
// state (Setting.txt MapSize, <map>/<xxxyyy>/attr.atr) instead of the loaded CTerrain list.
bool CMapManager::isAttrOn(int iX, int iY, BYTE byAttr)
{
if (!IsMapReady())
return false;
auto state = s_native_maps.find(this);
if (state == s_native_maps.end() || !state->second.ready)
return false;
const int countX = state->second.setting.map_size_x, countY = state->second.setting.map_size_y;
if (iX < 0 || iY < 0 || iX > countX * CTerrainImpl::TERRAIN_XSIZE || iY > countY * CTerrainImpl::TERRAIN_YSIZE)
return false;
WORD wTerrainCoordX, wTerrainCoordY;
wTerrainCoordX = iX / CTerrainImpl::TERRAIN_XSIZE;
wTerrainCoordY = iY / CTerrainImpl::TERRAIN_YSIZE;
const std::vector<BYTE> *attr = attr_tile(state->second, wTerrainCoordX, wTerrainCoordY);
if (!attr)
return false;
WORD wLocalX, wLocalY;
wLocalX = (iX - wTerrainCoordX * CTerrainImpl::TERRAIN_XSIZE) / (CTerrainImpl::HALF_CELLSCALE);
wLocalY = (iY - wTerrainCoordY * CTerrainImpl::TERRAIN_YSIZE) / (CTerrainImpl::HALF_CELLSCALE);
if (wLocalX >= CTerrainImpl::ATTRMAP_XSIZE || wLocalY >= CTerrainImpl::ATTRMAP_YSIZE)
return false;
BYTE byMapAttr = (*attr)[wLocalY * CTerrainImpl::ATTRMAP_XSIZE + wLocalX];
if ( byAttr < 16 )
return (byMapAttr & byAttr) ? true : false;
else
{
if ( byAttr/16 == byMapAttr/16)
return true;
else
return false;
}
}
auto CMapManager::BeginEnvironment() -> void
{
if (!IsMapReady() || !mc_pcurEnvironmentData)
return;
STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, TRUE);
STATEMANAGER.SetMaterial(&mc_pcurEnvironmentData->Material);
STATEMANAGER.SetLight(0, &mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND]);
// PORT: RecordingDevice stores SetLight but has no D3D LightEnable slot yet.
}
auto CMapManager::EndEnvironment() -> void
{
if (IsMapReady() && mc_pcurEnvironmentData)
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
}
// PORT: MapOutdoor is not allocated yet; report the pack-backed transition map's readiness.
bool CMapManager::IsMapReady()
{
auto found = s_native_maps.find(this);
return found != s_native_maps.end() && found->second.ready;
}
// 40250 MapManager.cpp: true when the current map is a CMapOutdoor. PORT: CMapOutdoor is not ported (the Godot
// terrain adapter draws the map), so there is no outdoor map object to hand out; false keeps the 40250 callers
// (CPythonMiniMap::Update/Render/LoadAtlas) on their "no outdoor map" path instead of reaching into one.
auto CMapManager::IsMapOutdoor() -> bool
{
MT_PLATFORM_STUB();
return false;
}
auto CMapManager::GetMapOutdoorRef() -> CMapOutdoor &
{
MT_PLATFORM_STUB();
// Never constructed (CMapOutdoor's constructor is not ported either); unreachable while IsMapOutdoor() is false.
alignas(CMapOutdoor) static unsigned char storage[sizeof(CMapOutdoor)];
return *reinterpret_cast<CMapOutdoor *>(storage);
}
@@ -1,18 +0,0 @@
// Stand-in for the 40250 logic unit GameLib/MapOutdoor.cpp, not ported yet: the members the ported units
// reference, as platform_stub.py stubs. Only reached behind CMapManager::IsMapOutdoor(), which is false until
// CMapOutdoor is ported. Delete this file in the commit that ports the unit into port/ (docs/PORT-PLAN.md).
#include "GameLib/StdAfx.h"
#include "GameLib/MapOutdoor.h"
#include "../../PlatformStub.h"
auto CMapOutdoor::GetTerrainPointer(BYTE, CTerrain **) -> BOOL
{
MT_PLATFORM_STUB();
return FALSE;
}
auto CMapOutdoor::GetBaseXY(DWORD *, DWORD *) -> void
{
MT_PLATFORM_STUB();
}
@@ -1,11 +0,0 @@
// Pending MapType.cpp dependency of InstanceBase; the full unit is not ported yet.
#include "GameLib/StdAfx.h"
#include "GameLib/MapType.h"
float SPixelPosition_CalculateDistanceSq3d(const TPixelPosition& left, const TPixelPosition& right)
{
float dx = left.x - right.x;
float dy = left.y - right.y;
float dz = left.z - right.z;
return dx * dx + dy * dy + dz * dz;
}
@@ -1,17 +0,0 @@
// Stand-in for the 40250 logic unit GameLib/PropertyManager.cpp, not ported yet: the members the ported units
// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/
// (docs/PORT-PLAN.md).
#include "GameLib/StdAfx.h"
#include "GameLib/PropertyManager.h"
#include "../../PlatformStub.h"
CPropertyManager::CPropertyManager()
{
MT_PLATFORM_STUB();
}
CPropertyManager::~CPropertyManager()
{
MT_PLATFORM_STUB();
}
@@ -1,342 +0,0 @@
// Stand-in for the 40250 logic unit UserInterface/PythonBackground.cpp, not ported yet: the members the ported units
// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/
// (docs/PORT-PLAN.md).
#include "UserInterface/StdAfx.h"
#include "UserInterface/PythonBackground.h"
#include "UserInterface/InstanceBase.h"
#include "EterLib/StateManager.h"
#include "../../PlatformStub.h"
auto CPythonBackground::Destroy() -> void
{
CMapManager::Destroy();
m_bVisibleGuildArea = FALSE;
}
auto CPythonBackground::Create() -> void
{
CMapManager::Create();
}
auto CPythonBackground::GlobalPositionToLocalPosition(LONG &x, LONG &y) -> void
{
x -= m_dwBaseX;
y -= m_dwBaseY;
}
auto CPythonBackground::LocalPositionToGlobalPosition(LONG &x, LONG &y) -> void
{
x += m_dwBaseX;
y += m_dwBaseY;
}
auto CPythonBackground::RefreshShadowLevel() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::Update(float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::ClearGuildArea() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::RegisterGuildArea(int, int, int, int) -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::CreateTargetEffect(DWORD, DWORD) -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::CreateTargetEffect(DWORD, long, long) -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::DeleteTargetEffect(DWORD) -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::Warp(DWORD x, DWORD y) -> void
{
if (m_kVct_kMapInfo.empty())
Initialize();
auto found = std::find_if(m_kVct_kMapInfo.begin(), m_kVct_kMapInfo.end(),
[x, y](const TMapInfo &info) {
return x >= info.m_dwBaseX && x < info.m_dwEndX &&
y >= info.m_dwBaseY && y < info.m_dwEndY;
});
if (found == m_kVct_kMapInfo.end()) {
TraceError("NOT_FOUND_GLOBAL_POSITION(%u, %u)", x, y);
return;
}
if (!LoadMap(found->m_strName, float(x - found->m_dwBaseX),
float(y - found->m_dwBaseY), 0.0f)) {
TraceError("CPythonBackground::Warp map load failed: %s", found->m_strName.c_str());
return;
}
m_dwBaseX = found->m_dwBaseX;
m_dwBaseY = found->m_dwBaseY;
m_strMapName = found->m_strName;
}
auto CPythonBackground::GetWarpMapName() -> const char *
{
return m_strMapName.c_str();
}
CPythonBackground::CPythonBackground()
{
m_eViewDistanceNum=0;
m_dwBaseX=0;
m_dwBaseY=0;
m_bVisibleGuildArea=FALSE;
m_iXMasTreeGrade=0;
}
CPythonBackground::~CPythonBackground()
{
MT_PLATFORM_STUB();
}
// 40250 PythonBackground.cpp:547-608, verbatim. No map objects are registered with CCullingManager until
// CMapOutdoor is ported, so the checkers see no opponent and advancing is never blocked.
struct CollisionChecker
{
bool isBlocked;
CInstanceBase* pInstance;
CollisionChecker(CInstanceBase* pInstance) : pInstance(pInstance), isBlocked(false) {}
void operator () (CGraphicObjectInstance* pOpponent)
{
if (isBlocked)
return;
if (!pOpponent)
return;
if (pInstance->IsBlockObject(*pOpponent))
isBlocked=true;
}
};
struct CollisionAdjustChecker
{
bool isBlocked;
CInstanceBase* pInstance;
CollisionAdjustChecker(CInstanceBase* pInstance) : pInstance(pInstance), isBlocked(false) {}
void operator () (CGraphicObjectInstance* pOpponent)
{
if (!pOpponent)
return;
if (pInstance->AvoidObject(*pOpponent))
isBlocked=true;
}
};
bool CPythonBackground::CheckAdvancing(CInstanceBase * pInstance)
{
if (!IsMapReady())
return true;
Vector3d center;
float radius;
pInstance->GetGraphicThingInstanceRef().GetBoundingSphere(center,radius);
CCullingManager & rkCullingMgr = CCullingManager::Instance();
CollisionAdjustChecker kCollisionAdjustChecker(pInstance);
rkCullingMgr.ForInRange(center, radius, &kCollisionAdjustChecker);
if (kCollisionAdjustChecker.isBlocked)
{
CollisionChecker kCollisionChecker(pInstance);
rkCullingMgr.ForInRange(center, radius, &kCollisionChecker);
if (kCollisionChecker.isBlocked)
{
pInstance->BlockMovement();
return true;
}
else
{
pInstance->NEW_MoveToDestPixelPositionDirection(pInstance->NEW_GetDstPixelPositionRef());
}
return false;
}
return false;
}
namespace
{
// 40250 CMapOutdoor::__PickTerrainHeight (MapOutdoor.cpp:448), marching the ray against the terrain height.
// PORT: CMapOutdoor is not ported; the terrain is the native CMapManager height map, and GetTerrainNum/
// GetTerrainPointer become "the map is ready" (GetHeight reads the height tile under the point).
bool PickTerrainHeight(CMapManager& rkMap, float& fPos, const D3DXVECTOR3& v3Start, const D3DXVECTOR3& v3End, float fStep,
float fRayRange, float fLimitRange, D3DXVECTOR3* pv3Pick)
{
D3DXVECTOR3 v3CurPos;
float fRayRangeInv=1.0f/fRayRange;
while (fPos < fRayRange && fPos<fLimitRange)
{
D3DXVec3Lerp(&v3CurPos, &v3Start, &v3End, fPos*fRayRangeInv);
float fMultiplier = 1.0f;
if (rkMap.IsMapReady())
{
// PORT: PR_FLOAT_TO_INT is x87 fistp (round to nearest) corrected down, i.e. floor.
int ix = int(std::floor(v3CurPos.x)), iy = int(std::floor(fabs(v3CurPos.y)));
float fMapHeight = rkMap.GetHeight(float(ix), float(iy));
if ( fMapHeight >= v3CurPos.z)
{
*pv3Pick = v3CurPos;
return true;
}
else
{
fMultiplier = fMAX(1.0f, 0.01f * ( v3CurPos.z - fMapHeight ) );
}
}
fPos += fStep * fMultiplier;
}
return false;
}
}
// 40250 CMapOutdoor::GetPickingPointWithRayOnlyTerrain (MapOutdoor.cpp:549).
bool CPythonBackground::GetPickingPointWithRayOnlyTerrain(const CRay & rRay, D3DXVECTOR3 * v3IntersectPt)
{
bool bTerrainPick = false;
D3DXVECTOR3 v3TerrainPick;
D3DXVECTOR3 v3Start, v3End, v3Dir;
float fRayRange;
rRay.GetStartPoint(&v3Start);
rRay.GetDirection(&v3Dir, &fRayRange);
rRay.GetEndPoint(&v3End);
float fPos = 0.0f;
bTerrainPick=true;
if (!PickTerrainHeight(*this, fPos, v3Start, v3End, 5.0f, fRayRange, 5000.0f, &v3TerrainPick))
if (!PickTerrainHeight(*this, fPos, v3Start, v3End, 10.0f, fRayRange, 10000.0f, &v3TerrainPick))
if (!PickTerrainHeight(*this, fPos, v3Start, v3End, 100.0f, fRayRange, 100000.0f, &v3TerrainPick))
bTerrainPick=false;
if (bTerrainPick)
{
*v3IntersectPt = v3TerrainPick;
return true;
}
return false;
}
// 40250 CMapOutdoor::GetPickingPointWithRay (MapOutdoor.cpp:484).
// PORT: the object pick (FGetPickingPoint over CCullingManager) needs CMapOutdoor's area objects; only the
// terrain half runs until the map is ported.
bool CPythonBackground::GetPickingPointWithRay(const CRay & rRay, D3DXVECTOR3 * v3IntersectPt)
{
return GetPickingPointWithRayOnlyTerrain(rRay, v3IntersectPt);
}
// 40250 PythonBackground.cpp:173 (CPythonApplication::RenderGame's SetPerspective); m_pkMap stays null
// until the map is ported, so this is the 50000 far clip.
float CPythonBackground::GetFarClip()
{
if (!m_pkMap)
return 50000.0f;
if (m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip==0.0f)
{
TraceError("CPythonBackground::GetFarClip m_eViewDistanceNum=%d", m_eViewDistanceNum);
m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip=25600.0f;
}
return m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip;
}
auto CPythonBackground::Render() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::RenderAfterLensFlare() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::RenderBeforeLensFlare() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::RenderCharacterShadowToTexture() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::RenderCloud() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::RenderEffect() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::RenderPCBlocker() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::RenderSky() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::RenderSnow() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::RenderWater() -> void
{
MT_PLATFORM_STUB();
}
auto CPythonBackground::SetBackgroundDirLight() -> void
{
if (!IsMapReady() || !mc_pcurEnvironmentData)
return;
STATEMANAGER.SetLight(0, &mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND]);
}
auto CPythonBackground::SetCharacterDirLight() -> void
{
if (!IsMapReady() || !mc_pcurEnvironmentData)
return;
STATEMANAGER.SetLight(0, &mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_CHARACTER]);
}
void CPythonBackground::Initialize()
{
std::string atlas(LocaleService_GetLocalePath());
atlas += "/AtlasInfo.txt";
SetAtlasInfoFileName(atlas.c_str());
CMapManager::Initialize();
}
// 40250 PythonBackground.cpp:263 → CMapOutdoor::GetPickingPoint (MapOutdoor.cpp:443): the cursor ray.
bool CPythonBackground::GetPickingPoint(D3DXVECTOR3 * v3IntersectPt)
{
return GetPickingPointWithRay(ms_Ray, v3IntersectPt);
}
@@ -21,3 +21,14 @@ auto CPythonSystem::IsShowDamage() -> bool
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CPythonSystem::GetShadowLevel() -> int
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<int>();
}
auto CPythonSystem::SetSoftwareTiling(bool isEnable) -> void
{
MT_PLATFORM_STUB();
}
+30
View File
@@ -0,0 +1,30 @@
#ifndef __ETER_FILE_DIR__
#define __ETER_FILE_DIR__
#include <windows.h>
class CDir
{
public:
CDir();
virtual ~CDir();
void Destroy();
bool Create(const char* c_szFilter, const char* c_szPath="", BOOL bCheckedExtension = FALSE);
protected:
virtual bool OnFolder(const char* c_szFilter, const char* c_szPath, const char* c_szName) = 0;
virtual bool OnFile(const char* c_szPath, const char* c_szName) = 0;
protected:
bool IsFolder();
void Initialize();
protected:
WIN32_FIND_DATA m_wfd;
HANDLE m_hFind;
};
#endif
+16
View File
@@ -0,0 +1,16 @@
#ifndef __INC_ETERBASE_TEMPFILE_H__
#define __INC_ETERBASE_TEMPFILE_H__
#include "FileBase.h"
class CTempFile : public CFileBase
{
public:
CTempFile(const char * c_pszPrefix = NULL);
virtual ~CTempFile();
protected:
char m_szFileName[MAX_PATH+1];
};
#endif
@@ -0,0 +1,104 @@
#include "StdAfx.h"
#include "ColorTransitionHelper.h"
void CColorTransitionHelper::Clear(const float & c_rfRed,
const float & c_rfGreen,
const float & c_rfBlue,
const float & c_rfAlpha)
{
m_fSrcRed = c_rfRed;
m_fSrcGreen = c_rfGreen;
m_fSrcBlue = c_rfBlue;
m_fSrcAlpha = c_rfAlpha;
m_fDstRed = c_rfRed;
m_fDstGreen = c_rfGreen;
m_fDstBlue = c_rfBlue;
m_fDstAlpha = c_rfAlpha;
m_dwCurColor = 0x00000000;
m_dwStartTime = m_dwDuration = 0;
}
void CColorTransitionHelper::SetSrcColor(const float & c_rfRed,
const float & c_rfGreen,
const float & c_rfBlue,
const float & c_rfAlpha)
{
m_fSrcRed = c_rfRed;
m_fSrcGreen = c_rfGreen;
m_fSrcBlue = c_rfBlue;
m_fSrcAlpha = c_rfAlpha;
}
void CColorTransitionHelper::SetTransition(const float & c_rfRed,
const float & c_rfGreen,
const float & c_rfBlue,
const float & c_rfAlpha,
const DWORD & dwDuration)
{
m_fDstRed = c_rfRed;
m_fDstGreen = c_rfGreen;
m_fDstBlue = c_rfBlue;
m_fDstAlpha = c_rfAlpha;
m_dwDuration = dwDuration;
}
void CColorTransitionHelper::StartTransition()
{
m_bTransitionStarted = true;
m_dwStartTime = GetCurrentTime();
}
bool CColorTransitionHelper::Update()
{
// if (!m_bTransitionStarted)
// return false;
DWORD dwCurTime = GetCurrentTime();
DWORD dwElapsedTime = dwCurTime - m_dwStartTime;
float fpercent = (float)(dwElapsedTime) / (float)(m_dwDuration);
if (fpercent <= 0.0f)
fpercent = 0.0f;
if (fpercent >= 1.0f)
fpercent = 1.0f;
float fCurRed, fCurGreen, fCurBlue, fCurAlpha;
fCurRed = m_fSrcRed + (m_fDstRed - m_fSrcRed) * fpercent;
fCurGreen = m_fSrcGreen + (m_fDstGreen - m_fSrcGreen) * fpercent;
fCurBlue = m_fSrcBlue + (m_fDstBlue - m_fSrcBlue) * fpercent;
fCurAlpha = m_fSrcAlpha + (m_fDstAlpha - m_fSrcAlpha) * fpercent;
// Tracef("%f, %f, %f, %f\n", fCurRed, fCurGreen, fCurBlue, fCurAlpha);
m_dwCurColor = (((DWORD)(fCurAlpha * 255.0f)&0xff)<< 24) |
(((DWORD)(fCurRed * 255.0f)&0xff) << 16) |
(((DWORD)(fCurGreen * 255.0f)&0xff) << 8) |
((DWORD)(fCurBlue * 255.0f)&0xff);
if ( (1.0f == fpercent) && (fCurAlpha == m_fDstAlpha) && (fCurRed == m_fDstRed) && (fCurGreen == m_fDstGreen) && (fCurBlue == m_fDstBlue) )
{
m_bTransitionStarted = false;
return false;
}
return true;
}
const D3DCOLOR & CColorTransitionHelper::GetCurColor()
{
return m_dwCurColor;
}
CColorTransitionHelper::CColorTransitionHelper():m_bTransitionStarted(false)
{
Clear(0.0f, 0.0f, 0.0f, 0.0f);
}
CColorTransitionHelper::~CColorTransitionHelper()
{
Clear(0.0f, 0.0f, 0.0f, 0.0f);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+265
View File
@@ -0,0 +1,265 @@
#include "StdAfx.h"
#include "DungeonBlock.h"
#include "../EterLib/StateManager.h"
class CDungeonModelInstance : public CGrannyModelInstance
{
public:
CDungeonModelInstance() {}
virtual ~CDungeonModelInstance() {}
void RenderDungeonBlock()
{
if (IsEmpty())
return;
STATEMANAGER.SetVertexShader(ms_pnt2VS);
LPDIRECT3DVERTEXBUFFER8 lpd3dRigidPNTVtxBuf = m_pModel->GetPNTD3DVertexBuffer();
if (lpd3dRigidPNTVtxBuf)
{
STATEMANAGER.SetStreamSource(0, lpd3dRigidPNTVtxBuf, sizeof(TPNT2Vertex));
RenderMeshNodeListWithTwoTexture(CGrannyMesh::TYPE_RIGID, CGrannyMaterial::TYPE_BLEND_PNT);
}
}
void RenderDungeonBlockShadow()
{
if (IsEmpty())
return;
STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xffffffff);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR);
STATEMANAGER.SetVertexShader(ms_pnt2VS);
LPDIRECT3DVERTEXBUFFER8 lpd3dRigidPNTVtxBuf = m_pModel->GetPNTD3DVertexBuffer();
if (lpd3dRigidPNTVtxBuf)
{
STATEMANAGER.SetStreamSource(0, lpd3dRigidPNTVtxBuf, sizeof(TPNT2Vertex));
RenderMeshNodeListWithoutTexture(CGrannyMesh::TYPE_RIGID, CGrannyMaterial::TYPE_BLEND_PNT);
}
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAOP);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND);
}
};
struct FUpdate
{
float fElapsedTime;
D3DXMATRIX * pmatWorld;
void operator() (CGrannyModelInstance * pInstance)
{
pInstance->Update(CGrannyModelInstance::ANIFPS_MIN);
pInstance->UpdateLocalTime(fElapsedTime);
pInstance->Deform(pmatWorld);
}
};
void CDungeonBlock::Update()
{
Transform();
FUpdate Update;
Update.fElapsedTime = 0.0f;
Update.pmatWorld = &m_worldMatrix;
for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), Update);
}
struct FRender
{
void operator() (CDungeonModelInstance * pInstance)
{
pInstance->RenderDungeonBlock();
}
};
void CDungeonBlock::Render()
{
// if (!isShow())
// return;
for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), FRender());
}
struct FRenderShadow
{
void operator() (CDungeonModelInstance * pInstance)
{
pInstance->RenderDungeonBlockShadow();
}
};
void CDungeonBlock::OnRenderShadow()
{
for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), FRenderShadow());
}
struct FBoundBox
{
D3DXVECTOR3 * m_pv3Min;
D3DXVECTOR3 * m_pv3Max;
FBoundBox(D3DXVECTOR3 * pv3Min, D3DXVECTOR3 * pv3Max)
{
m_pv3Min = pv3Min;
m_pv3Max = pv3Max;
}
void operator() (CGrannyModelInstance * pInstance)
{
pInstance->GetBoundBox(m_pv3Min, m_pv3Max);
}
};
bool CDungeonBlock::GetBoundingSphere(D3DXVECTOR3 & v3Center, float & fRadius)
{
v3Center = m_v3Center;
fRadius = m_fRadius;
D3DXVec3TransformCoord(&v3Center, &v3Center, &GetTransform());
return true;
}
void CDungeonBlock::OnUpdateCollisionData(const CStaticCollisionDataVector * pscdVector)
{
assert(pscdVector);
CStaticCollisionDataVector::const_iterator it;
for(it = pscdVector->begin();it!=pscdVector->end();++it)
{
AddCollision(&(*it),&GetTransform());
}
}
void CDungeonBlock::OnUpdateHeighInstance(CAttributeInstance * pAttributeInstance)
{
assert(pAttributeInstance);
SetHeightInstance(pAttributeInstance);
}
bool CDungeonBlock::OnGetObjectHeight(float fX, float fY, float * pfHeight)
{
if (m_pHeightAttributeInstance && m_pHeightAttributeInstance->GetHeight(fX, fY, pfHeight))
return true;
return false;
}
void CDungeonBlock::BuildBoundingSphere()
{
D3DXVECTOR3 v3Min, v3Max;
for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), FBoundBox(&v3Min, &v3Max));
m_v3Center = (v3Min+v3Max) * 0.5f;
const auto vv = (v3Max - v3Min);
m_fRadius = D3DXVec3Length(&vv)*0.5f + 150.0f; // extra length for attached objects
}
bool CDungeonBlock::Intersect(float * pfu, float * pfv, float * pft)
{
TModelInstanceContainer::iterator itor = m_ModelInstanceContainer.begin();
for (; itor != m_ModelInstanceContainer.end(); ++itor)
{
CDungeonModelInstance * pInstance = *itor;
if (pInstance->Intersect(&CGraphicObjectInstance::GetTransform(), pfu, pfv, pft))
return true;
}
return false;
}
void CDungeonBlock::GetBoundBox(D3DXVECTOR3 * pv3Min, D3DXVECTOR3 * pv3Max)
{
pv3Min->x = +10000000.0f;
pv3Min->y = +10000000.0f;
pv3Min->z = +10000000.0f;
pv3Max->x = -10000000.0f;
pv3Max->y = -10000000.0f;
pv3Max->z = -10000000.0f;
TModelInstanceContainer::iterator itor = m_ModelInstanceContainer.begin();
for (; itor != m_ModelInstanceContainer.end(); ++itor)
{
CDungeonModelInstance * pInstance = *itor;
D3DXVECTOR3 v3Min;
D3DXVECTOR3 v3Max;
pInstance->GetBoundBox(&v3Min, &v3Max);
pv3Min->x = min(v3Min.x, pv3Min->x);
pv3Min->y = min(v3Min.x, pv3Min->y);
pv3Min->z = min(v3Min.x, pv3Min->z);
pv3Max->x = max(v3Max.x, pv3Max->x);
pv3Max->y = max(v3Max.x, pv3Max->y);
pv3Max->z = max(v3Max.x, pv3Max->z);
}
}
bool CDungeonBlock::Load(const char * c_szFileName)
{
Destroy();
m_pThing = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(c_szFileName);
m_pThing->AddReference();
if (m_pThing->GetModelCount() <= 0)
{
TraceError("CDungeonBlock::Load(filename=%s) - model count is %d\n", c_szFileName, m_pThing->GetModelCount());
return false;
}
m_ModelInstanceContainer.reserve(m_pThing->GetModelCount());
for (int i = 0; i < m_pThing->GetModelCount(); ++i)
{
CDungeonModelInstance * pModelInstance = new CDungeonModelInstance;
pModelInstance->SetMainModelPointer(m_pThing->GetModelPointer(i), &m_kDeformableVertexBuffer);
DWORD dwVertexCount = pModelInstance->GetVertexCount();
m_kDeformableVertexBuffer.Destroy();
m_kDeformableVertexBuffer.Create(
dwVertexCount,
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1,
D3DUSAGE_WRITEONLY,
D3DPOOL_MANAGED);
m_ModelInstanceContainer.push_back(pModelInstance);
}
return true;
}
void CDungeonBlock::__Initialize()
{
m_v3Center = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_fRadius = 0.0f;
m_pThing = NULL;
}
void CDungeonBlock::Destroy()
{
if (m_pThing)
{
m_pThing->Release();
m_pThing = NULL;
}
stl_wipe(m_ModelInstanceContainer);
__Initialize();
}
CDungeonBlock::CDungeonBlock()
{
__Initialize();
}
CDungeonBlock::~CDungeonBlock()
{
Destroy();
}
+101
View File
@@ -0,0 +1,101 @@
#include "StdAfx.h"
#include "MapBase.h"
CMapBase::CMapBase()
{
Clear();
}
CMapBase::~CMapBase()
{
Clear();
}
void CMapBase::Clear()
{
m_strName = "";
m_eType = MAPTYPE_INVALID;
mc_pEnvironmentData = NULL;
Leave();
}
bool CMapBase::Enter()
{
m_bReady = true;
return true;
}
bool CMapBase::Leave()
{
m_bReady = false;
return true;
}
void CMapBase::SetEnvironmentDataPtr(const TEnvironmentData * c_pEnvironmentData)
{
mc_pEnvironmentData = c_pEnvironmentData;
OnSetEnvironmentDataPtr();
}
void CMapBase::ResetEnvironmentDataPtr(const TEnvironmentData * c_pEnvironmentData)
{
mc_pEnvironmentData = c_pEnvironmentData;
OnResetEnvironmentDataPtr();
}
void CMapBase::Render()
{
if (IsReady())
OnRender();
}
bool CMapBase::LoadProperty()
{
std::string strFileName = GetName() + "\\MapProperty.txt";
CTokenVectorMap stTokenVectorMap;
if (!LoadMultipleTextData(strFileName.c_str(), stTokenVectorMap))
{
TraceError("CMapBase::LoadProperty(FileName=%s) - LoadMultipleTextData ERROR \306\304\300\317\300\314 \276\370\300\273 \260\241\264\311\274\272\300\314 \270\271\275\300\264\317\264\331.", strFileName.c_str());
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("scripttype"))
{
TraceError("CMapBase::LoadProperty(FileName=%s) - FIND 'scripttype' - FAILED", strFileName.c_str());
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("maptype"))
{
TraceError("CMapBase::LoadProperty(FileName=%s) - FIND 'maptype' - FAILED", strFileName.c_str());
return false;
}
// NOTE: 이미 존재하는 맵 데이터와 동일한 데이터를 사용하는 맵을 새로 추가할 때, 맵 배포 용량을 줄이기 위한 작업.
// MapProperty.txt 파일에 ParentMapName 값이 설정되어 있다면, 실제 모든 데이터는 ParentMap에서 읽어온다.
// 데이터의 부분공유(부분 오버라이트?) 기능은 필요 없대서, Parent Map에서 모든 데이터를 읽어옴.
if (stTokenVectorMap.end() != stTokenVectorMap.find("parentmapname"))
{
m_strParentMapName = stTokenVectorMap["parentmapname"][0];
}
const std::string & c_rstrType = stTokenVectorMap["scripttype"][0];
const std::string & c_rstrMapType = stTokenVectorMap["maptype"][0];
if (0 != c_rstrType.compare("MapProperty"))
{
TraceError("CMapBase::LoadProperty(FileName=%s) - Resourse Type ERROR", strFileName.c_str());
return false;
}
if (0 == c_rstrMapType.compare("Indoor"))
SetType(MAPTYPE_INDOOR);
else if (0 == c_rstrMapType.compare("Outdoor"))
SetType(MAPTYPE_OUTDOOR);
else if (0 == c_rstrMapType.compare("Invalid"))
SetType(MAPTYPE_OUTDOOR);
return true;
}
+638
View File
@@ -0,0 +1,638 @@
#include "StdAfx.h"
#include "../EterLib/StateManager.h"
#include "../EterPack/EterPackManager.h"
#include "MapManager.h"
#include "MapOutdoor.h"
#include "PropertyLoader.h"
//////////////////////////////////////////////////////////////////////////
// 기본 함수
//////////////////////////////////////////////////////////////////////////
bool CMapManager::IsMapOutdoor()
{
if (m_pkMap)
return true;
return false;
}
CMapOutdoor& CMapManager::GetMapOutdoorRef()
{
assert(NULL!=m_pkMap);
return *m_pkMap;
}
CMapManager::CMapManager() : mc_pcurEnvironmentData(NULL)
{
m_pkMap = NULL;
m_isSoftwareTilingEnableReserved=false;
// Initialize();
}
CMapManager::~CMapManager()
{
Destroy();
}
bool CMapManager::IsSoftwareTilingEnable()
{
return CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE;
}
void CMapManager::ReserveSoftwareTilingEnable(bool isEnable)
{
m_isSoftwareTilingEnableReserved=isEnable;
}
void CMapManager::Initialize()
{
mc_pcurEnvironmentData = NULL;
__LoadMapInfoVector();
}
void CMapManager::Create()
{
assert(NULL==m_pkMap && "CMapManager::Create");
if (m_pkMap)
{
Clear();
return;
}
CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE=m_isSoftwareTilingEnableReserved;
m_pkMap = (CMapOutdoor*)AllocMap();
assert(NULL!=m_pkMap && "CMapManager::Create MAP is NULL");
}
void CMapManager::Destroy()
{
stl_wipe_second(m_EnvironmentDataMap);
if (m_pkMap)
{
m_pkMap->Clear();
delete m_pkMap;
m_pkMap = NULL;
}
}
void CMapManager::Clear()
{
if (m_pkMap)
m_pkMap->Clear();
}
CMapBase * CMapManager::AllocMap()
{
return new CMapOutdoor;
}
//////////////////////////////////////////////////////////////////////////
// Map
//////////////////////////////////////////////////////////////////////////
void CMapManager::LoadProperty()
{
CPropertyLoader PropertyLoader;
PropertyLoader.SetPropertyManager(&m_PropertyManager);
PropertyLoader.Create("*.*", "Property");
}
bool CMapManager::LoadMap(const std::string & c_rstrMapName, float x, float y, float z)
{
CMapOutdoor& rkMap = GetMapOutdoorRef();
rkMap.Leave();
rkMap.SetName(c_rstrMapName);
rkMap.LoadProperty();
if ( CMapBase::MAPTYPE_INDOOR == rkMap.GetType())
{
TraceError("CMapManager::LoadMap() Indoor Map Load Failed");
return false;
}
else if (CMapBase::MAPTYPE_OUTDOOR == rkMap.GetType())
{
if (!rkMap.Load(x, y, z))
{
TraceError("CMapManager::LoadMap() Outdoor Map Load Failed");
return false;
}
RegisterEnvironmentData(0, rkMap.GetEnvironmentDataName().c_str());
SetEnvironmentData(0);
}
else
{
TraceError("CMapManager::LoadMap() Invalid Map Type");
return false;
}
rkMap.Enter();
return true;
}
bool CMapManager::IsMapReady()
{
if (!m_pkMap)
return false;
return m_pkMap->IsReady();
}
bool CMapManager::UnloadMap(const std::string c_strMapName)
{
CMapOutdoor& rkMap=GetMapOutdoorRef();
if (c_strMapName != rkMap.GetName() && "" != rkMap.GetName())
{
LogBoxf("%s: Unload Map Failed", c_strMapName.c_str());
return false;
}
Clear();
return true;
}
bool CMapManager::UpdateMap(float fx, float fy, float fz)
{
if (!m_pkMap)
return false;
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.Update(fx, -fy, fz);
}
void CMapManager::UpdateAroundAmbience(float fx, float fy, float fz)
{
if (!m_pkMap)
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.UpdateAroundAmbience(fx, -fy, fz);
}
float CMapManager::GetHeight(float fx, float fy)
{
if (!m_pkMap)
{
TraceError("CMapManager::GetHeight(%f, %f) - \270\312\300\314 \273\375\274\272\265\307\301\366 \276\312\300\272 \273\363\305\302\277\241\274\255 \301\242\261\331", fx, fy);
return 0.0f;
}
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetHeight(fx, fy);
}
float CMapManager::GetTerrainHeight(float fx, float fy)
{
if (!m_pkMap)
{
TraceError("CMapManager::GetTerrainHeight(%f, %f) - \270\312\300\314 \273\375\274\272\265\307\301\366 \276\312\300\272 \273\363\305\302\277\241\274\255 \301\242\261\331", fx, fy);
return 0.0f;
}
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetTerrainHeight(fx, fy);
}
bool CMapManager::GetWaterHeight(int iX, int iY, long * plWaterHeight)
{
if (!m_pkMap)
{
TraceError("CMapManager::GetTerrainHeight(%f, %f) - \270\312\300\314 \273\375\274\272\265\307\301\366 \276\312\300\272 \273\363\305\302\277\241\274\255 \301\242\261\331", iX, iY);
return false;
}
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetWaterHeight(iX, iY, plWaterHeight);
}
//////////////////////////////////////////////////////////////////////////
// Environment
//////////////////////////////////////////////////////////////////////////
void CMapManager::BeginEnvironment()
{
if (!m_pkMap)
return;
if (!mc_pcurEnvironmentData)
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
// Light always on
STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, TRUE);
// Fog
STATEMANAGER.SaveRenderState(D3DRS_FOGENABLE, mc_pcurEnvironmentData->bFogEnable);
// Material
STATEMANAGER.SetMaterial(&mc_pcurEnvironmentData->Material);
// Directional Light
if (mc_pcurEnvironmentData->bDirLightsEnable[ENV_DIRLIGHT_BACKGROUND])
{
ms_lpd3dDevice->LightEnable(0, TRUE);
rkMap.ApplyLight((DWORD)(uintptr_t)mc_pcurEnvironmentData, mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND]); // PORT: 64-bit pointer tag
}
else
ms_lpd3dDevice->LightEnable(0, FALSE);
if (mc_pcurEnvironmentData->bFogEnable)
{
DWORD dwFogColor = mc_pcurEnvironmentData->FogColor;
STATEMANAGER.SetRenderState(D3DRS_FOGCOLOR, dwFogColor);
if (mc_pcurEnvironmentData->bDensityFog)
{
float fDensity = 0.00015f;
STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP); // pixel fog
STATEMANAGER.SetRenderState(D3DRS_FOGDENSITY, *((DWORD *) &fDensity)); // vertex fog
}
else
{
CSpeedTreeForestDirectX8& rkForest=CSpeedTreeForestDirectX8::Instance();
rkForest.SetFog(
mc_pcurEnvironmentData->GetFogNearDistance(),
mc_pcurEnvironmentData->GetFogFarDistance()
);
float fFogNear=mc_pcurEnvironmentData->GetFogNearDistance();
float fFogFar=mc_pcurEnvironmentData->GetFogFarDistance();
STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR); // vertex fox
STATEMANAGER.SetRenderState(D3DRS_RANGEFOGENABLE, TRUE); // vertex fox
STATEMANAGER.SetRenderState(D3DRS_FOGSTART, *((DWORD *) &fFogNear)); // USED BY D3DFOG_LINEAR
STATEMANAGER.SetRenderState(D3DRS_FOGEND, *((DWORD *) &fFogFar)); // USED BY D3DFOG_LINEAR
}
}
rkMap.OnBeginEnvironment();
}
void CMapManager::EndEnvironment()
{
if (!mc_pcurEnvironmentData)
return;
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
STATEMANAGER.RestoreRenderState(D3DRS_FOGENABLE);
}
void CMapManager::SetEnvironmentData(int nEnvDataIndex)
{
const TEnvironmentData * c_pEnvironmenData;
if (GetEnvironmentData(nEnvDataIndex, &c_pEnvironmenData))
SetEnvironmentDataPtr(c_pEnvironmenData);
}
void CMapManager::SetEnvironmentDataPtr(const TEnvironmentData * c_pEnvironmentData)
{
if (!m_pkMap)
return;
if (!c_pEnvironmentData)
{
assert(!"null environment data");
TraceError("null environment data");
return;
}
CMapOutdoor& rkMap=GetMapOutdoorRef();
mc_pcurEnvironmentData = c_pEnvironmentData;
rkMap.SetEnvironmentDataPtr(mc_pcurEnvironmentData);
}
void CMapManager::ResetEnvironmentDataPtr(const TEnvironmentData * c_pEnvironmentData)
{
if (!m_pkMap)
return;
if (!c_pEnvironmentData)
{
assert(!"null environment data");
TraceError("null environment data");
return;
}
CMapOutdoor& rkMap=GetMapOutdoorRef();
mc_pcurEnvironmentData = c_pEnvironmentData;
rkMap.ResetEnvironmentDataPtr(mc_pcurEnvironmentData);
}
void CMapManager::BlendEnvironmentData(const TEnvironmentData * c_pEnvironmentData, int iTransitionTime)
{
}
bool CMapManager::RegisterEnvironmentData(DWORD dwIndex, const char * c_szFileName)
{
TEnvironmentData * pEnvironmentData = AllocEnvironmentData();
if (!LoadEnvironmentData(c_szFileName, pEnvironmentData))
{
DeleteEnvironmentData(pEnvironmentData);
return false;
}
TEnvironmentDataMap::iterator f=m_EnvironmentDataMap.find(dwIndex);
if (m_EnvironmentDataMap.end()==f)
{
m_EnvironmentDataMap.insert(TEnvironmentDataMap::value_type(dwIndex, pEnvironmentData));
}
else
{
delete f->second;
f->second=pEnvironmentData;
}
return true;
}
void CMapManager::GetCurrentEnvironmentData(const TEnvironmentData ** c_ppEnvironmentData)
{
*c_ppEnvironmentData = mc_pcurEnvironmentData;
}
bool CMapManager::GetEnvironmentData(DWORD dwIndex, const TEnvironmentData ** c_ppEnvironmentData)
{
TEnvironmentDataMap::iterator itor = m_EnvironmentDataMap.find(dwIndex);
if (m_EnvironmentDataMap.end() == itor)
{
*c_ppEnvironmentData = NULL;
return false;
}
*c_ppEnvironmentData = itor->second;
return true;
}
void CMapManager::RefreshPortal()
{
if (!IsMapReady())
return;
CMapOutdoor & rMap = GetMapOutdoorRef();
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (!rMap.GetAreaPointer(i, &pArea))
continue;
pArea->RefreshPortal();
}
}
void CMapManager::ClearPortal()
{
if (!IsMapReady())
return;
CMapOutdoor & rMap = GetMapOutdoorRef();
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (!rMap.GetAreaPointer(i, &pArea))
continue;
pArea->ClearPortal();
}
}
void CMapManager::AddShowingPortalID(int iID)
{
if (!IsMapReady())
return;
CMapOutdoor & rMap = GetMapOutdoorRef();
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (!rMap.GetAreaPointer(i, &pArea))
continue;
pArea->AddShowingPortalID(iID);
}
}
TEnvironmentData * CMapManager::AllocEnvironmentData()
{
TEnvironmentData * pEnvironmentData = new TEnvironmentData;
Environment_Init(*pEnvironmentData);
return pEnvironmentData;
}
void CMapManager::DeleteEnvironmentData(TEnvironmentData * pEnvironmentData)
{
delete pEnvironmentData;
pEnvironmentData = NULL;
}
BOOL CMapManager::LoadEnvironmentData(const char * c_szFileName, TEnvironmentData * pEnvironmentData)
{
if (!pEnvironmentData)
return FALSE;
return (BOOL)Environment_Load(*pEnvironmentData, c_szFileName);
}
DWORD CMapManager::GetShadowMapColor(float fx, float fy)
{
if (!IsMapReady())
return 0xFFFFFFFF;
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetShadowMapColor(fx, fy);
}
std::vector<int> & CMapManager::GetRenderedSplatNum(int * piPatch, int * piSplat, float * pfSplatRatio)
{
if (!m_pkMap)
{
static std::vector<int> s_emptyVector;
*piPatch = 0;
*piSplat = 0;
return s_emptyVector;
}
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetRenderedSplatNum(piPatch, piSplat, pfSplatRatio);
}
CArea::TCRCWithNumberVector & CMapManager::GetRenderedGraphicThingInstanceNum(DWORD * pdwGraphicThingInstanceNum, DWORD * pdwCRCNum)
{
if (!m_pkMap)
{
static CArea::TCRCWithNumberVector s_emptyVector;
*pdwGraphicThingInstanceNum = 0;
*pdwCRCNum = 0;
return s_emptyVector;
}
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetRenderedGraphicThingInstanceNum(pdwGraphicThingInstanceNum, pdwCRCNum);
}
bool CMapManager::GetNormal(int ix, int iy, D3DXVECTOR3 * pv3Normal)
{
if (!IsMapReady())
return false;
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetNormal(ix, iy, pv3Normal);
}
bool CMapManager::isPhysicalCollision(const D3DXVECTOR3 & c_rvCheckPosition)
{
if (!IsMapReady())
return false;
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.isAttrOn(c_rvCheckPosition.x, -c_rvCheckPosition.y, CTerrainImpl::ATTRIBUTE_BLOCK);
}
bool CMapManager::isAttrOn(float fX, float fY, BYTE byAttr)
{
if (!IsMapReady())
return false;
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.isAttrOn(fX, fY, byAttr);
}
bool CMapManager::GetAttr(float fX, float fY, BYTE * pbyAttr)
{
if (!IsMapReady())
return false;
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetAttr(fX, fY, pbyAttr);
}
bool CMapManager::isAttrOn(int iX, int iY, BYTE byAttr)
{
if (!IsMapReady())
return false;
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.isAttrOn(iX, iY, byAttr);
}
bool CMapManager::GetAttr(int iX, int iY, BYTE * pbyAttr)
{
if (!IsMapReady())
return false;
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetAttr(iX, iY, pbyAttr);
}
// 2004.10.14.myevan.TEMP_CAreaLoaderThread
/*
bool CMapManager::BGLoadingEnable()
{
if (!IsMapReady())
return false;
return ((CMapOutdoor*)m_pMap)->BGLoadingEnable();
}
void CMapManager::BGLoadingEnable(bool bBGLoadingEnable)
{
if (!IsMapReady())
return;
((CMapOutdoor*)m_pMap)->BGLoadingEnable(bBGLoadingEnable);
}
*/
void CMapManager::SetTerrainRenderSort(CMapOutdoor::ETerrainRenderSort eTerrainRenderSort)
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.SetTerrainRenderSort(eTerrainRenderSort);
}
void CMapManager::SetTransparentTree(bool bTransparenTree)
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.SetTransparentTree(bTransparenTree);
}
CMapOutdoor::ETerrainRenderSort CMapManager::GetTerrainRenderSort()
{
if (!IsMapReady())
return CMapOutdoor::DISTANCE_SORT;
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetTerrainRenderSort();
}
void CMapManager::GetBaseXY(DWORD * pdwBaseX, DWORD * pdwBaseY)
{
if (!IsMapReady())
{
*pdwBaseX = 0;
*pdwBaseY = 0;
}
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.GetBaseXY(pdwBaseX, pdwBaseY);
}
void CMapManager::__LoadMapInfoVector()
{
CMappedFile kFile;
LPCVOID pData;
if (!CEterPackManager::Instance().Get(kFile, m_stAtlasInfoFileName.c_str(), &pData))
if (!CEterPackManager::Instance().Get(kFile, "AtlasInfo.txt", &pData))
return;
CMemoryTextFileLoader textFileLoader;
textFileLoader.Bind(kFile.Size(), pData);
char szMapName[256];
int x, y;
int width, height;
for (UINT uLineIndex=0; uLineIndex<textFileLoader.GetLineCount(); ++uLineIndex)
{
const std::string& c_rstLine=textFileLoader.GetLineString(uLineIndex);
sscanf(c_rstLine.c_str(), "%s %d %d %d %d",
szMapName,
&x, &y, &width, &height);
if ('\0'==szMapName[0])
continue;
TMapInfo kMapInfo;
kMapInfo.m_strName = szMapName;
kMapInfo.m_dwBaseX = x;
kMapInfo.m_dwBaseY = y;
kMapInfo.m_dwSizeX = width;
kMapInfo.m_dwSizeY = height;
kMapInfo.m_dwEndX = kMapInfo.m_dwBaseX + kMapInfo.m_dwSizeX * CTerrainImpl::TERRAIN_XSIZE;
kMapInfo.m_dwEndY = kMapInfo.m_dwBaseY + kMapInfo.m_dwSizeY * CTerrainImpl::TERRAIN_YSIZE;
m_kVct_kMapInfo.push_back(kMapInfo);
}
return;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,529 @@
#include "StdAfx.h"
#include "MapOutdoor.h"
void CMapOutdoor::SetIndexBuffer()
{
void * pIndices;
long x, y;
DWORD dwIndexNum = TERRAIN_PATCHSIZE * TERRAIN_PATCHSIZE * 4;
#ifdef WORLD_EDITOR
m_pwIndices = new WORD[dwIndexNum];
if (!m_pwIndices)
TraceError("CMapOutdoor::SetIndexBuffer() IndexBuffer is NULL");
memset(m_pwIndices, 0, sizeof(WORD) * dwIndexNum);
if (!m_IndexBuffer.Create(dwIndexNum, D3DFMT_INDEX16))
TraceError("CMapOutdoor::SetIndexBuffer() IndexBuffer Create Error");
WORD count = 0;
WORD count2 = 0;
long ry = 0;
BYTE ucNumLineWarp = TERRAIN_PATCHSIZE + 1;
for (y = 0; y < TERRAIN_PATCHSIZE; y++)
{
if (ry % 2 == 0)
{
m_pwIndices[count++] = count2;
m_pwIndices[count++] = count2+ucNumLineWarp;
}
else
{
m_pwIndices[count++] = count2+ucNumLineWarp;
m_pwIndices[count++] = count2;
}
for (x = 0; x < TERRAIN_PATCHSIZE; x++)
{
if (ry % 2 == 1)
{
m_pwIndices[count++] = (WORD) (count2+ucNumLineWarp-1);
m_pwIndices[count++] = (WORD) (count2-1);
count2 -= (short) 1;
}
else
{
m_pwIndices[count++] = (WORD) (count2+1);
m_pwIndices[count++] = (WORD) (count2+ucNumLineWarp+1);
count2 += (short) 1;
}
}
if (y < TERRAIN_PATCHSIZE-1)
{
m_pwIndices[count++] = (WORD) (count2+ucNumLineWarp);
m_pwIndices[count++] = (WORD) (count2+ucNumLineWarp);
count2 += ucNumLineWarp;
}
ry++;
}
m_wNumIndices = count;
if (!m_IndexBuffer.Lock((void **) &pIndices))
TraceError("CMapOutdoor::SetIndexBuffer() IndexBuffer Unlock Error");
memcpy(pIndices, m_pwIndices, count * sizeof(WORD));
m_IndexBuffer.Unlock();
delete [] m_pwIndices;
m_pwIndices = NULL;
#else
WORD count[TERRAINPATCH_LODMAX], count2[TERRAINPATCH_LODMAX];
BYTE uci;
for (uci = 0; uci < TERRAINPATCH_LODMAX; ++uci)
{
m_pwaIndices[uci] = new WORD[dwIndexNum];
memset(m_pwaIndices[uci], 0, sizeof(WORD) * dwIndexNum);
count[uci] = 0;
count2[uci] = 0;
if ( !m_IndexBuffer[uci].Create(dwIndexNum, D3DFMT_INDEX16) )
TraceError("CMapOutdoor::SetIndexBuffer() IndexBuffer Create Error");
}
BYTE ucNumLineWarp = TERRAIN_PATCHSIZE + 1;
for (y = 0; y < TERRAIN_PATCHSIZE; y++)
{
if (y%2 == 0)
{
m_pwaIndices[0][(count[0])++] = count2[0];
m_pwaIndices[0][(count[0])++] = count2[0]+ucNumLineWarp;
}
else
{
m_pwaIndices[0][(count[0])++] = count2[0]+ucNumLineWarp;
m_pwaIndices[0][(count[0])++] = count2[0];
}
for (x = 0; x < TERRAIN_PATCHSIZE; x++)
{
if (y%2 == 0)
{
m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]+1);
m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]+ucNumLineWarp+1);
count2[0] += (short) 1;
}
else
{
m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]+ucNumLineWarp-1);
m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]-1);
count2[0] -= (short) 1;
}
if (0 == x%2)
{
if (0 == y)
{
if (0 == x)
ADDLvl1TL(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp);
else if ((TERRAIN_PATCHSIZE - 2) == x)
ADDLvl1TR(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp);
else
ADDLvl1T(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp);
}
else if ((TERRAIN_PATCHSIZE - 2) == y)
{
if (0 == x)
ADDLvl1BL(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp);
else if ((TERRAIN_PATCHSIZE - 2) == x)
ADDLvl1BR(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp);
else
ADDLvl1B(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp);
}
else if (0 == y%2)
{
if (0 == x)
ADDLvl1L(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp);
else if ((TERRAIN_PATCHSIZE - 2) == x)
ADDLvl1R(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp);
else
ADDLvl1M(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp);
}
count2[1] += 2;
}
if (0 == x%4)
{
if (0 == y)
{
if (0 == x)
ADDLvl2TL(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp);
else if ((TERRAIN_PATCHSIZE - 4) == x)
ADDLvl2TR(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp);
else
ADDLvl2T(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp);
}
else if ((TERRAIN_PATCHSIZE - 4) == y)
{
if (0 == x)
ADDLvl2BL(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp);
else if ((TERRAIN_PATCHSIZE - 4) == x)
ADDLvl2BR(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp);
else
ADDLvl2B(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp);
}
else if (0 == y%4)
{
if (0 == x)
ADDLvl2L(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp);
else if ((TERRAIN_PATCHSIZE - 4) == x)
ADDLvl2R(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp);
else
ADDLvl2M(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp);
}
count2[2] += 4;
}
}
if (y < TERRAIN_PATCHSIZE-1)
{
m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]+ucNumLineWarp);
m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]+ucNumLineWarp);
count2[0] += ucNumLineWarp;
if (0 == y%2)
count2[1] += 2;
if (0 == y%4)
count2[2] += 4;
}
}
for (uci = 0; uci < TERRAINPATCH_LODMAX; ++uci)
{
m_wNumIndices[uci] = count[uci];
if( !m_IndexBuffer[uci].Lock((void **) &pIndices) )
TraceError("CMapOutdoor::SetIndexBuffer() IndexBuffer Unlock Error");
memcpy(pIndices, m_pwaIndices[uci], count[uci] * sizeof(WORD));
m_IndexBuffer[uci].Unlock();
delete [] m_pwaIndices[uci];
m_pwaIndices[uci] = NULL;
}
#endif
}
void CMapOutdoor::ADDLvl1TL(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 1;
pIndices[rwCount++] = c_rwCurCount;
}
void CMapOutdoor::ADDLvl1T(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 1;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
}
void CMapOutdoor::ADDLvl1TR(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 1;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
}
void CMapOutdoor::ADDLvl1L(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
}
void CMapOutdoor::ADDLvl1R(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
}
void CMapOutdoor::ADDLvl1BL(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
}
void CMapOutdoor::ADDLvl1B(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
}
void CMapOutdoor::ADDLvl1BR(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1;
}
void CMapOutdoor::ADDLvl1M(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + 2;
}
void CMapOutdoor::ADDLvl2TL(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
ADDLvl1TL(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp);
ADDLvl1T(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp);
ADDLvl1L(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp);
ADDLvl1M(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp);
}
void CMapOutdoor::ADDLvl2T(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
ADDLvl1T(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp);
ADDLvl1T(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp);
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
}
void CMapOutdoor::ADDLvl2TR(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
ADDLvl1T(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp);
ADDLvl1TR(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp);
ADDLvl1M(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp);
ADDLvl1R(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp);
}
void CMapOutdoor::ADDLvl2L(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
ADDLvl1L(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp);
ADDLvl1L(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp);
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + 4;
pIndices[rwCount++] = c_rwCurCount + 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 2;
}
void CMapOutdoor::ADDLvl2R(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
ADDLvl1R(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp);
ADDLvl1R(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp);
pIndices[rwCount++] = c_rwCurCount + 2;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 2;
}
void CMapOutdoor::ADDLvl2BL(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
ADDLvl1L(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp);
ADDLvl1M(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp);
ADDLvl1BL(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp);
ADDLvl1B(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp);
}
void CMapOutdoor::ADDLvl2B(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + 4;
pIndices[rwCount++] = c_rwCurCount + 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 4;
ADDLvl1B(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp);
ADDLvl1B(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp);
}
void CMapOutdoor::ADDLvl2BR(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
ADDLvl1M(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp);
ADDLvl1R(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp);
ADDLvl1B(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp);
ADDLvl1BR(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp);
}
void CMapOutdoor::ADDLvl2M(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp)
{
pIndices[rwCount++] = c_rwCurCount;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4;
pIndices[rwCount++] = c_rwCurCount + 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4;
pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 4;
pIndices[rwCount++] = c_rwCurCount + 4;
}
@@ -0,0 +1,544 @@
#include "StdAfx.h"
#include "MapOutdoor.h"
#include "AreaTerrain.h"
#include "AreaLoaderThread.h"
#include "../EterLib/ResourceManager.h"
#include "../EterPack/EterPackManager.h"
//CAreaLoaderThread CMapOutdoor::ms_AreaLoaderThread;
bool CMapOutdoor::Load(float x, float y, float z)
{
Destroy();
CEterPackManager& rkPackMgr=CEterPackManager::Instance();
{
static std::string s_strOldPathName="";
// 2004.08.09.myevan.Pack파일을 찾을때.. 폴더명만으로는 그냥 리턴되는 부분이 있다
std::string c_rstrNewPathName=GetName()+"\\cache";
s_strOldPathName=c_rstrNewPathName;
}
std::string strFileName = GetMapDataDirectory() + "\\Setting.txt";
if (!LoadSetting(strFileName.c_str()))
TraceError("CMapOutdoor::Load : LoadSetting(%s) Failed", strFileName.c_str());
#ifdef WORLD_EDITOR
if (!LoadMonsterAreaInfo())
TraceError("CMapOutdoor::Load - LoadMonsterAreaInfo ERROR");
#endif
CreateTerrainPatchProxyList();
BuildQuadTree();
LoadWaterTexture();
CreateCharacterShadowTexture();
m_lOldReadX = -1;
// TODO: SetRenderingDevice에서 Environment로 부터 라이트 속성을 넘겨줘야 스태틱 라이트가 제대로 작동한다.
CSpeedTreeForestDirectX8::Instance().SetRenderingDevice(ms_lpd3dDevice);
Update(x, y, z);
__HeightCache_Init();
// LOCAL_ENVIRONMENT_DATA
std::string local_envDataName = GetMapDataDirectory() + "\\" + m_settings_envDataName;
if (rkPackMgr.isExist(local_envDataName.c_str()))
{
m_envDataName = local_envDataName;
}
else
{
const std::string& c_rstrEnvironmentRoot = "d:/ymir work/environment/";
const std::string& c_rstrMapName = GetName();
m_envDataName = c_rstrEnvironmentRoot + m_settings_envDataName;
if (0 == m_envDataName.compare(c_rstrEnvironmentRoot))
{
const std::string& strAppendName = c_rstrMapName.substr(c_rstrMapName.size() - 2, 2);
m_envDataName = c_rstrEnvironmentRoot + strAppendName + ".msenv";
}
}
// LOCAL_ENVIRONMENT_DATA_END
return true;
}
std::string& CMapOutdoor::GetEnvironmentDataName()
{
return m_envDataName;
}
bool CMapOutdoor::isTerrainLoaded(WORD wX, WORD wY)
{
for (DWORD i = 0; i < m_TerrainVector.size(); ++i)
{
CTerrain * pTerrain = m_TerrainVector[i];
WORD usCoordX, usCoordY;
pTerrain->GetCoordinate(&usCoordX, &usCoordY);
if (usCoordX == wX && usCoordY == wY)
return true;
}
return false;
}
bool CMapOutdoor::isAreaLoaded(WORD wX, WORD wY)
{
for (DWORD i = 0; i < m_AreaVector.size(); ++i)
{
CArea * pArea = m_AreaVector[i];
WORD usCoordX, usCoordY;
pArea->GetCoordinate(&usCoordX, &usCoordY);
if (usCoordX == wX && usCoordY == wY)
return true;
}
return false;
}
// 현재 좌표를 기반으로 주위(ex. 3x3)에 있는 Terrain과 Area포인터를
// m_pTerrain과 m_pArea에 연결한다.
void CMapOutdoor::AssignTerrainPtr()
{
// 월드에디터에서 화면을 죽죽죽 넘길 때 터레인을 저장해야 하기
// 때문에 이 virtual method를 호출 한다. 이 메소드는 CMapOutDoor에서는 아무 행동도
// 하지 않는다.
OnPreAssignTerrainPtr();
short sReferenceCoordMinX, sReferenceCoordMaxX, sReferenceCoordMinY, sReferenceCoordMaxY;
sReferenceCoordMinX = max(m_CurCoordinate.m_sTerrainCoordX - LOAD_SIZE_WIDTH, 0);
sReferenceCoordMaxX = min(m_CurCoordinate.m_sTerrainCoordX + LOAD_SIZE_WIDTH, m_sTerrainCountX - 1);
sReferenceCoordMinY = max(m_CurCoordinate.m_sTerrainCoordY - LOAD_SIZE_WIDTH, 0);
sReferenceCoordMaxY = min(m_CurCoordinate.m_sTerrainCoordY + LOAD_SIZE_WIDTH, m_sTerrainCountY - 1);
DWORD i;
for (i = 0; i < AROUND_AREA_NUM; ++i)
{
m_pArea[i] = NULL;
m_pTerrain[i] = NULL;
}
for (i = 0; i < m_TerrainVector.size(); ++i)
{
CTerrain * pTerrain = m_TerrainVector[i];
WORD usCoordX, usCoordY;
pTerrain->GetCoordinate(&usCoordX, &usCoordY);
if (usCoordX >= sReferenceCoordMinX &&
usCoordX <= sReferenceCoordMaxX &&
usCoordY >= sReferenceCoordMinY &&
usCoordY <= sReferenceCoordMaxY)
{
m_pTerrain[(usCoordY - m_CurCoordinate.m_sTerrainCoordY + LOAD_SIZE_WIDTH) * 3 +
(usCoordX - m_CurCoordinate.m_sTerrainCoordX + LOAD_SIZE_WIDTH) ] = pTerrain;
}
}
for (i = 0; i < m_AreaVector.size(); ++i)
{
CArea * pArea = m_AreaVector[i];
WORD usCoordX, usCoordY;
pArea->GetCoordinate(&usCoordX, &usCoordY);
if (usCoordX >= sReferenceCoordMinX &&
usCoordX <= sReferenceCoordMaxX &&
usCoordY >= sReferenceCoordMinY &&
usCoordY <= sReferenceCoordMaxY)
{
m_pArea[(usCoordY - m_CurCoordinate.m_sTerrainCoordY + LOAD_SIZE_WIDTH) * 3 +
(usCoordX - m_CurCoordinate.m_sTerrainCoordX + LOAD_SIZE_WIDTH) ] = pArea;
}
}
}
bool CMapOutdoor::LoadArea(WORD wAreaCoordX, WORD wAreaCoordY, WORD wCellCoordX, WORD wCellCoordY)
{
if (isAreaLoaded(wAreaCoordX, wAreaCoordY))
return true;
#ifdef _DEBUG
DWORD dwStartTime = ELTimer_GetMSec();
#endif
unsigned long ulID = (unsigned long) (wAreaCoordX) * 1000L + (unsigned long) (wAreaCoordY);
char szAreaPathName[64+1];
_snprintf(szAreaPathName, sizeof(szAreaPathName), "%s\\%06u\\", GetMapDataDirectory().c_str(), ulID);
CArea * pArea = CArea::New();
pArea->SetMapOutDoor(this);
#ifdef _DEBUG
Tracef("CMapOutdoor::LoadArea1 %d\n", ELTimer_GetMSec() - dwStartTime);
dwStartTime = ELTimer_GetMSec();
#endif
pArea->SetCoordinate(wAreaCoordX, wAreaCoordY);
if ( !pArea->Load(szAreaPathName) )
TraceError(" CMapOutdoor::LoadArea(%d, %d) LoadShadowMap ERROR", wAreaCoordX, wAreaCoordY);
#ifdef _DEBUG
Tracef("CMapOutdoor::LoadArea2 %d\n", ELTimer_GetMSec() - dwStartTime);
dwStartTime = ELTimer_GetMSec();
#endif
m_AreaVector.push_back(pArea);
pArea->EnablePortal(m_bEnablePortal);
#ifdef _DEBUG
Tracef("CMapOutdoor::LoadArea3 %d\n", ELTimer_GetMSec() - dwStartTime);
#endif
return true;
}
bool CMapOutdoor::LoadTerrain(WORD wTerrainCoordX, WORD wTerrainCoordY, WORD wCellCoordX, WORD wCellCoordY)
{
if (isTerrainLoaded(wTerrainCoordX, wTerrainCoordY))
return true;
//////////////////////////////////////////////////////////////////////////
DWORD dwStartTime = ELTimer_GetMSec();
unsigned long ulID = (unsigned long) (wTerrainCoordX) * 1000L + (unsigned long) (wTerrainCoordY);
char filename[256];
sprintf(filename, "%s\\%06u\\AreaProperty.txt", GetMapDataDirectory().c_str(), ulID);
CTokenVectorMap stTokenVectorMap;
if (!LoadMultipleTextData(filename, stTokenVectorMap))
{
TraceError("CMapOutdoor::LoadTerrain AreaProperty Read Error\n");
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("scripttype"))
{
TraceError("CMapOutdoor::LoadTerrain AreaProperty FileFormat Error 1\n");
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("areaname"))
{
TraceError("CMapOutdoor::LoadTerrain AreaProperty FileFormat Error 2\n");
return false;
}
const std::string & c_rstrType = stTokenVectorMap["scripttype"][0];
const std::string & c_rstrAreaName = stTokenVectorMap["areaname"][0];
if (c_rstrType != "AreaProperty")
{
TraceError("CMapOutdoor::LoadTerrain AreaProperty FileFormat Error 3\n");
return false;
}
CTerrain * pTerrain = CTerrain::New();
pTerrain->Clear();
pTerrain->SetMapOutDoor(this);
pTerrain->SetCoordinate(wTerrainCoordX, wTerrainCoordY);
pTerrain->CopySettingFromGlobalSetting();
char szRawHeightFieldname[64+1];
char szWaterMapName[64+1];
char szAttrMapName[64+1];
char szShadowTexName[64+1];
char szShadowMapName[64+1];
char szMiniMapTexName[64+1];
char szSplatName[64+1];
_snprintf(szRawHeightFieldname, sizeof(szRawHeightFieldname), "%s\\%06u\\height.raw", GetMapDataDirectory().c_str(), ulID);
_snprintf(szSplatName, sizeof(szSplatName), "%s\\%06u\\tile.raw", GetMapDataDirectory().c_str(), ulID);
_snprintf(szAttrMapName, sizeof(szAttrMapName), "%s\\%06u\\attr.atr", GetMapDataDirectory().c_str(), ulID);
_snprintf(szWaterMapName, sizeof(szWaterMapName), "%s\\%06u\\water.wtr", GetMapDataDirectory().c_str(), ulID);
_snprintf(szShadowTexName, sizeof(szShadowTexName), "%s\\%06u\\shadowmap.dds", GetMapDataDirectory().c_str(), ulID);
_snprintf(szShadowMapName, sizeof(szShadowMapName), "%s\\%06u\\shadowmap.raw", GetMapDataDirectory().c_str(), ulID);
_snprintf(szMiniMapTexName, sizeof(szMiniMapTexName), "%s\\%06u\\minimap.dds", GetMapDataDirectory().c_str(), ulID);
if(!pTerrain->LoadWaterMap(szWaterMapName))
TraceError(" CMapOutdoor::LoadTerrain(%d, %d) LoadWaterMap ERROR", wTerrainCoordX, wTerrainCoordY);
if (!pTerrain->LoadHeightMap(szRawHeightFieldname))
TraceError(" CMapOutdoor::LoadTerrain(%d, %d) LoadHeightMap ERROR", wTerrainCoordX, wTerrainCoordY);
if (!pTerrain->LoadAttrMap(szAttrMapName))
TraceError(" CMapOutdoor::LoadTerrain(%d, %d) LoadAttrMap ERROR", wTerrainCoordX, wTerrainCoordY);
if (!pTerrain->RAW_LoadTileMap(szSplatName))
TraceError(" CMapOutdoor::LoadTerrain(%d, %d) RAW_LoadTileMap ERROR", wTerrainCoordX, wTerrainCoordY);
pTerrain->LoadShadowTexture(szShadowTexName);
if (!pTerrain->LoadShadowMap(szShadowMapName))
TraceError(" CMapOutdoor::LoadTerrain(%d, %d) LoadShadowMap ERROR", wTerrainCoordX, wTerrainCoordY);
pTerrain->LoadMiniMapTexture(szMiniMapTexName);
pTerrain->SetName(c_rstrAreaName.c_str());
pTerrain->CalculateTerrainPatch();
pTerrain->SetReady();
Tracef("CMapOutdoor::LoadTerrain %d\n", ELTimer_GetMSec() - dwStartTime);
m_TerrainVector.push_back(pTerrain);
return true;
}
bool CMapOutdoor::LoadSetting(const char * c_szFileName)
{
NANOBEGIN
CTokenVectorMap stTokenVectorMap;
if (!LoadMultipleTextData(c_szFileName, stTokenVectorMap))
{
TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - LoadMultipleTextData", c_szFileName);
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("scripttype"))
{
TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'scripttype' - FAILED", c_szFileName);
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("viewradius"))
{
TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'viewradius' - FAILED", c_szFileName);
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("cellscale"))
{
TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'cellscale' - FAILED", c_szFileName);
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("heightscale"))
{
TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'heightscale' - FAILED", c_szFileName);
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("mapsize"))
{
TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'mapsize' - FAILED", c_szFileName);
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("textureset"))
{
TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'textureset' - FAILED", c_szFileName);
return false;
}
if (stTokenVectorMap.end() != stTokenVectorMap.find("terrainvisible"))
{
m_bSettingTerrainVisible = (bool) (atoi(stTokenVectorMap["terrainvisible"][0].c_str()) != 0);
}
else
{
m_bSettingTerrainVisible = true;
}
const std::string & c_rstrType = stTokenVectorMap["scripttype"][0];
const std::string & c_rstrViewRadius = stTokenVectorMap["viewradius"][0];
//const std::string & c_rstrCellScale = stTokenVectorMap["cellscale"][0];
const std::string & c_rstrHeightScale = stTokenVectorMap["heightscale"][0];
const std::string & c_rstrMapSizeX = stTokenVectorMap["mapsize"][0];
const std::string & c_rstrMapSizeY = stTokenVectorMap["mapsize"][1];
std::string strTextureSet;
TTokenVector & rkVec_strToken = stTokenVectorMap["textureset"];
if (!rkVec_strToken.empty())
{
strTextureSet = rkVec_strToken[0];
}
if (c_rstrType != "MapSetting")
{
TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - Resourse Type ERROR", c_szFileName);
return false;
}
m_lViewRadius = atol(c_rstrViewRadius.c_str());
#ifdef WORLD_EDITOR
m_lViewRadius <<= 1;
#endif
if (0L >= m_lViewRadius)
{
TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - VIEWRADIUS IS NOT GREATER THAN 0", c_szFileName);
return false;
}
m_fHeightScale = atof(c_rstrHeightScale.c_str());
SetTerrainCount(atoi(c_rstrMapSizeX.c_str()), atoi(c_rstrMapSizeY.c_str()));
m_fTerrainTexCoordBase = 1.0f / (float) (CTerrainImpl::PATCH_XSIZE * CTerrainImpl::CELLSCALE);
if (stTokenVectorMap.end() != stTokenVectorMap.find("baseposition"))
{
const std::string & c_rstrMapBaseX = stTokenVectorMap["baseposition"][0];
const std::string & c_rstrMapBaseY = stTokenVectorMap["baseposition"][1];
SetBaseXY((DWORD)atol(c_rstrMapBaseX.c_str()), (DWORD)atol(c_rstrMapBaseY.c_str()));
}
std::string stTextureSetFileName = strTextureSet;
// TextureSet 이 이미 붙어 있을 경우 안붙인다.
if (0 != stTextureSetFileName.find_first_of("textureset", 0))
stTextureSetFileName = "textureset\\"+strTextureSet;
if (!m_TextureSet.Load(stTextureSetFileName.c_str(), m_fTerrainTexCoordBase))
{
#ifdef WORLD_EDITOR
// TextureSet 이 적용되어 있지 않아도 진행
LogBox("TextureSet \300\314 \300\373\277\353\265\307\276\356\300\326\301\366 \276\312\300\272 \270\312 \300\324\264\317\264\331.\n\301\366\307\374 \305\330\275\272\303\347 \300\333\276\367\277\241 \301\326\300\307\307\317\275\303\261\342 \271\331\266\370\264\317\264\331.");
#else
TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - LOAD TEXTURE SET(%s) ERROR", c_szFileName, stTextureSetFileName.c_str());
return false;
#endif
}
CTerrain::SetTextureSet(&m_TextureSet);
if (stTokenVectorMap.end() != stTokenVectorMap.find("environment"))
{
const CTokenVector & c_rEnvironmentVector = stTokenVectorMap["environment"];
if (!c_rEnvironmentVector.empty())
m_settings_envDataName = c_rEnvironmentVector[0];
else
TraceError("CMapOutdoor::LoadSetting(c_szFileName=%s) - Failed to load environment data\n", c_szFileName);
}
m_fWaterTexCoordBase = 1.0f / (float)(CTerrainImpl::CELLSCALE * 4);
D3DXMatrixScaling(&m_matSplatAlpha,
+m_fTerrainTexCoordBase * 2.0f * (float)(CTerrainImpl::PATCH_XSIZE) / (float)(CTerrainImpl::SPLATALPHA_RAW_XSIZE-2),
-m_fTerrainTexCoordBase * 2.0f * (float)(CTerrainImpl::PATCH_YSIZE) / (float)(CTerrainImpl::SPLATALPHA_RAW_XSIZE-2),
0.0f);
m_matSplatAlpha._41 = m_fTerrainTexCoordBase * 4.6f;
m_matSplatAlpha._42 = m_fTerrainTexCoordBase * 4.6f;
D3DXMatrixScaling(&m_matStaticShadow,
+m_fTerrainTexCoordBase * ((float) CTerrainImpl::PATCH_XSIZE / static_cast<float>(CTerrainImpl::XSIZE)),
-m_fTerrainTexCoordBase * ((float) CTerrainImpl::PATCH_YSIZE / static_cast<float>(CTerrainImpl::XSIZE)),
0.0f);
m_matStaticShadow._41 = 0.0f;
m_matStaticShadow._42 = 0.0f;
D3DXMatrixScaling(&m_matDynamicShadowScale, 1.0f / 2550.0f, -1.0f / 2550.0f, 1.0f);
m_matDynamicShadowScale._41 = 0.5f;
m_matDynamicShadowScale._42 = 0.5f;
// Transform
D3DXMatrixScaling(&m_matBuildingTransparent, 1.0f / ((float)ms_iWidth), -1.0f / ((float)ms_iHeight), 1.0f);
m_matBuildingTransparent._41 = 0.5f;
m_matBuildingTransparent._42 = 0.5f;
NANOEND
return true;
}
bool CMapOutdoor::LoadMonsterAreaInfo()
{
RemoveAllMonsterAreaInfo();
char c_szFileName[256];
sprintf(c_szFileName, "%s\\regen.txt", GetMapDataDirectory().c_str());
LPCVOID pModelData;
CMappedFile File;
if (!CEterPackManager::Instance().Get(File, c_szFileName, &pModelData))
{
//TraceError(" CMapOutdoorAccessor::LoadMonsterAreaInfo Load File %s ERROR", c_szFileName);
return false;
}
CMemoryTextFileLoader textFileLoader;
CTokenVector stTokenVector;
textFileLoader.Bind(File.Size(), pModelData);
for (DWORD i = 0; i < textFileLoader.GetLineCount(); ++i)
{
if (!textFileLoader.SplitLine(i, &stTokenVector))
continue;
stl_lowers(stTokenVector[0]);
// Start or End
if (0 == stTokenVector[0].compare("m") || 0 == stTokenVector[0].compare("g"))
{
if (stTokenVector.size() < 11)
{
TraceError("CMapOutdoorAccessor::LoadMonsterAreaInfo Get MonsterInfo File Format ERROR! continue....");
continue;
}
CMonsterAreaInfo::EMonsterAreaInfoType eMonsterAreaInfoType;
if (0 == stTokenVector[0].compare("m"))
{
eMonsterAreaInfoType = CMonsterAreaInfo::MONSTERAREAINFOTYPE_MONSTER;
}
else if (0 == stTokenVector[0].compare("g"))
{
eMonsterAreaInfoType = CMonsterAreaInfo::MONSTERAREAINFOTYPE_GROUP;
}
else
{
TraceError("CMapOutdoorAccessor::LoadMonsterAreaInfo Get MonsterInfo Data ERROR! continue....");
continue;
}
const std::string & c_rstrOriginX = stTokenVector[1].c_str();
const std::string & c_rstrOriginY = stTokenVector[2].c_str();
const std::string & c_rstrSizeX = stTokenVector[3].c_str();
const std::string & c_rstrSizeY = stTokenVector[4].c_str();
const std::string & c_rstrZ = stTokenVector[5].c_str();
const std::string & c_rstrDir = stTokenVector[6].c_str();
const std::string & c_rstrTime = stTokenVector[7].c_str();
const std::string & c_rstrPercent = stTokenVector[8].c_str();
const std::string & c_rstrCount = stTokenVector[9].c_str();
const std::string & c_rstrVID = stTokenVector[10].c_str();
long lOriginX, lOriginY, lSizeX, lSizeY, lZ, lTime, lPercent;
CMonsterAreaInfo::EMonsterDir eMonsterDir;
DWORD dwMonsterCount;
DWORD dwMonsterVID;
lOriginX = atol(c_rstrOriginX.c_str());
lOriginY = atol(c_rstrOriginY.c_str());
lSizeX = atol(c_rstrSizeX.c_str());
lSizeY = atol(c_rstrSizeY.c_str());
lZ = atol(c_rstrZ.c_str());
eMonsterDir = (CMonsterAreaInfo::EMonsterDir) atoi(c_rstrDir.c_str());
lTime = atol(c_rstrTime.c_str());
lPercent = atol(c_rstrPercent.c_str());
dwMonsterCount = (DWORD) atoi(c_rstrCount.c_str());
dwMonsterVID = (DWORD) atoi(c_rstrVID.c_str());
// lOriginX -= m_dwBaseX / 100;
// lOriginY -= m_dwBaseY / 100;
CMonsterAreaInfo * pMonsterAreaInfo = AddMonsterAreaInfo(lOriginX, lOriginY, lSizeX, lSizeY);
pMonsterAreaInfo->SetMonsterAreaInfoType(eMonsterAreaInfoType);
if (CMonsterAreaInfo::MONSTERAREAINFOTYPE_MONSTER == eMonsterAreaInfoType)
pMonsterAreaInfo->SetMonsterVID(dwMonsterVID);
else if (CMonsterAreaInfo::MONSTERAREAINFOTYPE_GROUP == eMonsterAreaInfoType)
pMonsterAreaInfo->SetMonsterGroupID(dwMonsterVID);
pMonsterAreaInfo->SetMonsterCount(dwMonsterCount);
pMonsterAreaInfo->SetMonsterDirection(eMonsterDir);
}
}
return true;
}
@@ -0,0 +1,168 @@
#include "StdAfx.h"
#include "MapOutdoor.h"
#include "TerrainQuadtree.h"
//////////////////////////////////////////////////////////////////////////
// QuadTree
//////////////////////////////////////////////////////////////////////////
void CMapOutdoor::BuildQuadTree()
{
FreeQuadTree();
// m_wPatchCount는 ConvertPatchSplat에서도 정한다, 안전을 위해 여기서 체크한다.
if (0 == m_wPatchCount)
{
TraceError("MapOutdoor::BuildQuadTree : m_wPatchCount is zero, you must call ConvertPatchSplat before call this method.");
return;
}
m_pRootNode = AllocQuadTreeNode(0, 0, m_wPatchCount - 1, m_wPatchCount - 1);
if (!m_pRootNode)
TraceError("CMapOutdoor::BuildQuadTree() RootNode is NULL");
if (m_pRootNode->Size > 1)
SubDivideNode(m_pRootNode);
}
CTerrainQuadtreeNode * CMapOutdoor::AllocQuadTreeNode(long x0, long y0, long x1, long y1)
{
CTerrainQuadtreeNode * Node;
long xsize, ysize;
xsize = x1-x0+1;
ysize = y1-y0+1;
if ((xsize == 0) || (ysize == 0))
return NULL;
Node = new CTerrainQuadtreeNode;
Node->x0 = x0;
Node->y0 = y0;
Node->x1 = x1;
Node->y1 = y1;
if (ysize > xsize)
Node->Size = ysize;
else
Node->Size = xsize;
Node->PatchNum = y0 * m_wPatchCount + x0;
/*
const float fTerrainMin = -(float) (m_lViewRadius * m_lCellScale);
minx = fTerrainMin + x0 * c_byPatchSize * m_lCellScale;
maxx = fTerrainMin + (x1 + 1) * c_byPatchSize * m_lCellScale;
miny = fTerrainMin + y0 * c_byPatchSize * m_lCellScale;
maxy = fTerrainMin + (y1 + 1) * c_byPatchSize * m_lCellScale;
minz = 0.0f;
maxz = 0.0f;
/ * Set up 8 vertices that belong to the bounding box * /
Node->center.x = minx + (maxx - minx) * 0.5f;
Node->center.y = miny + (maxy - miny) * 0.5f;
Node->center.z = minz + (maxz - minz) * 0.5f;
Node->radius = sqrtf(
(maxx-minx)*(maxx-minx)+
(maxy-miny)*(maxy-miny)+
(maxz-minz)*(maxz-minz)
)/2.0f;
*/
Node->center.x = 0.0f;
Node->center.y = 0.0f;
Node->center.z = 0.0f;
Node->radius = 0.0f;
return Node;
}
void CMapOutdoor::SubDivideNode(CTerrainQuadtreeNode * Node)
{
long nw_size;
CTerrainQuadtreeNode * tempnode;
nw_size = Node->Size / 2;
Node->NW_Node = AllocQuadTreeNode (Node->x0, Node->y0, Node->x0 + nw_size-1, Node->y0 + nw_size-1);
Node->NE_Node = AllocQuadTreeNode (Node->x0 + nw_size, Node->y0, Node->x1, Node->y0 + nw_size-1);
Node->SW_Node = AllocQuadTreeNode (Node->x0, Node->y0 + nw_size, Node->x0 + nw_size-1, Node->y1);
Node->SE_Node = AllocQuadTreeNode (Node->x0 + nw_size, Node->y0 + nw_size, Node->x1, Node->y1);
tempnode = (CTerrainQuadtreeNode *) Node->NW_Node;
if ((tempnode != NULL) && (tempnode->Size > 1))
SubDivideNode (tempnode);
tempnode = (CTerrainQuadtreeNode *) Node->NE_Node;
if ((tempnode != NULL) && (tempnode->Size > 1))
SubDivideNode (tempnode);
tempnode = (CTerrainQuadtreeNode *) Node->SW_Node;
if ((tempnode != NULL) && (tempnode->Size > 1))
SubDivideNode (tempnode);
tempnode = (CTerrainQuadtreeNode *) Node->SE_Node;
if ((tempnode != NULL) && (tempnode->Size > 1))
SubDivideNode (tempnode);
}
/*
void CMapOutdoor::RecurseDeleteQuadTree(CTerrainQuadtreeNode *Node)
{
if (Node == NULL)
return;
if (Node->NW_Node != NULL)
{
RecurseDeleteQuadTree(Node->NW_Node);
Node->NW_Node = NULL;
}
if (Node->NE_Node != NULL)
{
RecurseDeleteQuadTree(Node->NE_Node);
Node->NE_Node = NULL;
}
if (Node->SW_Node != NULL)
{
RecurseDeleteQuadTree(Node->SW_Node);
Node->SW_Node = NULL;
}
if (Node->SE_Node != NULL)
{
RecurseDeleteQuadTree(Node->SE_Node);
Node->SE_Node = NULL;
}
free(Node);
}
*/
void CMapOutdoor::FreeQuadTree()
{
if (NULL == m_pRootNode)
return;
if (m_pRootNode->NW_Node)
{
delete m_pRootNode->NW_Node;
m_pRootNode->NW_Node = NULL;
}
if (m_pRootNode->NE_Node)
{
delete m_pRootNode->NE_Node;
m_pRootNode->NE_Node = NULL;
}
if (m_pRootNode->SW_Node)
{
delete m_pRootNode->SW_Node;
m_pRootNode->SW_Node = NULL;
}
if (m_pRootNode->SE_Node)
{
delete m_pRootNode->SE_Node;
m_pRootNode->SE_Node = NULL;
}
delete m_pRootNode;
m_pRootNode = NULL;
}
@@ -0,0 +1,964 @@
#include "StdAfx.h"
#include "MapOutdoor.h"
#include "TerrainPatch.h"
#include "AreaTerrain.h"
#include "TerrainQuadtree.h"
#include "../EterLib/Camera.h"
#include "../EterLib/StateManager.h"
#define MAX_RENDER_SPALT 150
CArea::TCRCWithNumberVector m_dwRenderedCRCWithNumberVector;
CMapOutdoor::TTerrainNumVector CMapOutdoor::FSortPatchDrawStructWithTerrainNum::m_TerrainNumVector;
void CMapOutdoor::RenderTerrain()
{
if (!IsVisiblePart(PART_TERRAIN))
return;
if (!m_bSettingTerrainVisible)
return;
// Inserted by levites
if (!m_pTerrainPatchProxyList)
return;
CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera();
if (!pCamera)
return;
auto vv = ms_matView * ms_matProj;
BuildViewFrustum(vv);
D3DXVECTOR3 v3Eye = pCamera->GetEye();
m_fXforDistanceCaculation = -v3Eye.x;
m_fYforDistanceCaculation = -v3Eye.y;
//////////////////////////////////////////////////////////////////////////
// Push
m_PatchVector.clear();
__RenderTerrain_RecurseRenderQuadTree(m_pRootNode);
// 거리순 정렬
std::sort(m_PatchVector.begin(),m_PatchVector.end());
// 그리기 위한 벡터 세팅
if (CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE)
__RenderTerrain_RenderSoftwareTransformPatch();
else
__RenderTerrain_RenderHardwareTransformPatch();
}
void CMapOutdoor::__RenderTerrain_RecurseRenderQuadTree(CTerrainQuadtreeNode *Node, bool bCullCheckNeed)
{
if (bCullCheckNeed)
{
switch (__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle(Node->center, Node->radius))
{
case VIEW_ALL:
// all child nodes need not cull check
bCullCheckNeed = false;
break;
case VIEW_PART:
break;
case VIEW_NONE:
// no need to render
return;
}
// if no need cull check more
// -> bCullCheckNeed = false;
}
if (Node->Size == 1)
{
D3DXVECTOR3 v3Center = Node->center;
float fDistance = fMAX(fabs(v3Center.x + m_fXforDistanceCaculation), fabs(-v3Center.y + m_fYforDistanceCaculation));
__RenderTerrain_AppendPatch(v3Center, fDistance, Node->PatchNum);
}
else
{
if (Node->NW_Node != NULL)
__RenderTerrain_RecurseRenderQuadTree(Node->NW_Node, bCullCheckNeed);
if (Node->NE_Node != NULL)
__RenderTerrain_RecurseRenderQuadTree(Node->NE_Node, bCullCheckNeed);
if (Node->SW_Node != NULL)
__RenderTerrain_RecurseRenderQuadTree(Node->SW_Node, bCullCheckNeed);
if (Node->SE_Node != NULL)
__RenderTerrain_RecurseRenderQuadTree(Node->SE_Node, bCullCheckNeed);
}
}
int CMapOutdoor::__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle(const D3DXVECTOR3 & c_v3Center, const float & c_fRadius)
{
const int count = 6;
D3DXVECTOR3 center = c_v3Center;
center.y = -center.y;
int i;
float distance[count];
for(i = 0; i < count; ++i)
{
distance[i] = D3DXPlaneDotCoord(&m_plane[i], &center);
if (distance[i] <= -c_fRadius)
return VIEW_NONE;
}
for(i = 0; i < count;++i)
{
if (distance[i] <= c_fRadius)
return VIEW_PART;
}
return VIEW_ALL;
}
void CMapOutdoor::__RenderTerrain_AppendPatch(const D3DXVECTOR3& c_rv3Center, float fDistance, long lPatchNum)
{
assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::__RenderTerrain_AppendPatch");
if (!m_pTerrainPatchProxyList[lPatchNum].isUsed())
return;
m_pTerrainPatchProxyList[lPatchNum].SetCenterPosition(c_rv3Center);
m_PatchVector.push_back(std::make_pair(fDistance, lPatchNum));
}
void CMapOutdoor::ApplyLight(DWORD dwVersion, const D3DLIGHT8& c_rkLight)
{
m_kSTPD.m_dwLightVersion=dwVersion;
STATEMANAGER.SetLight(0, &c_rkLight);
}
// 2004. 2. 17. myevan. 모든 부분을 보이게 초기화 한다
void CMapOutdoor::InitializeVisibleParts()
{
m_dwVisiblePartFlags=0xffffffff;
}
// 2004. 2. 17. myevan. 특정 부분을 보이게 하거나 감추는 함수
void CMapOutdoor::SetVisiblePart(int ePart, bool isVisible)
{
DWORD dwMask=(1<<ePart);
if (isVisible)
{
m_dwVisiblePartFlags|=dwMask;
}
else
{
DWORD dwReverseMask=~dwMask;
m_dwVisiblePartFlags&=dwReverseMask;
}
}
// 2004. 2. 17. myevan. 특정 부분이 보이는지 알아내는 함수
bool CMapOutdoor::IsVisiblePart(int ePart)
{
DWORD dwMask=(1<<ePart);
if (dwMask & m_dwVisiblePartFlags)
return true;
return false;
}
// Splat 개수 제한
void CMapOutdoor::SetSplatLimit(int iSplatNum)
{
m_iSplatLimit = iSplatNum;
}
std::vector<int> & CMapOutdoor::GetRenderedSplatNum(int * piPatch, int * piSplat, float * pfSplatRatio)
{
*piPatch = m_iRenderedPatchNum;
*piSplat = m_iRenderedSplatNum;
*pfSplatRatio = m_iRenderedSplatNumSqSum/float(m_iRenderedPatchNum);
return m_RenderedTextureNumVector;
}
CArea::TCRCWithNumberVector & CMapOutdoor::GetRenderedGraphicThingInstanceNum(DWORD * pdwGraphicThingInstanceNum, DWORD * pdwCRCNum)
{
*pdwGraphicThingInstanceNum = m_dwRenderedGraphicThingInstanceNum;
*pdwCRCNum = m_dwRenderedCRCNum;
return m_dwRenderedCRCWithNumberVector;
}
void CMapOutdoor::RenderBeforeLensFlare()
{
m_LensFlare.DrawBeforeFlare();
if (!mc_pEnvironmentData)
{
TraceError("CMapOutdoor::RenderBeforeLensFlare mc_pEnvironmentData is NULL");
return;
}
m_LensFlare.Compute(mc_pEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND].Direction);
}
void CMapOutdoor::RenderAfterLensFlare()
{
m_LensFlare.AdjustBrightness();
m_LensFlare.DrawFlare();
}
void CMapOutdoor::RenderCollision()
{
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (GetAreaPointer(i, &pArea))
pArea->RenderCollision();
}
}
void CMapOutdoor::RenderScreenFiltering()
{
m_ScreenFilter.Render();
}
void CMapOutdoor::RenderSky()
{
if (IsVisiblePart(PART_SKY))
m_SkyBox.Render();
}
void CMapOutdoor::RenderCloud()
{
if (IsVisiblePart(PART_CLOUD))
m_SkyBox.RenderCloud();
}
void CMapOutdoor::RenderTree()
{
if (IsVisiblePart(PART_TREE))
CSpeedTreeForestDirectX8::Instance().Render();
}
void CMapOutdoor::SetInverseViewAndDynamicShaodwMatrices()
{
CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera();
if (!pCamera)
return;
m_matViewInverse = pCamera->GetInverseViewMatrix();
D3DXVECTOR3 v3Target = pCamera->GetTarget();
D3DXVECTOR3 v3LightEye(v3Target.x - 1.732f * 1250.0f,
v3Target.y - 1250.0f,
v3Target.z + 2.0f * 1.732f * 1250.0f);
const auto vv = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
D3DXMatrixLookAtRH(&m_matLightView, &v3LightEye, &v3Target, &vv);
m_matDynamicShadow = m_matViewInverse * m_matLightView * m_matDynamicShadowScale;
}
void CMapOutdoor::OnRender()
{
#ifdef __PERFORMANCE_CHECKER__
DWORD t1=ELTimer_GetMSec();
SetInverseViewAndDynamicShaodwMatrices();
SetBlendOperation();
DWORD t2=ELTimer_GetMSec();
RenderArea();
DWORD t3=ELTimer_GetMSec();
if (!m_bEnableTerrainOnlyForHeight)
RenderTerrain();
DWORD t4=ELTimer_GetMSec();
RenderTree();
DWORD t5=ELTimer_GetMSec();
DWORD tEnd=ELTimer_GetMSec();
if (tEnd-t1<7)
return;
static FILE* fp=fopen("perf_map_render.txt", "w");
fprintf(fp, "MAP.Total %d (Time %d)\n", tEnd-t1, ELTimer_GetMSec());
fprintf(fp, "MAP.ENV %d\n", t2-t1);
fprintf(fp, "MAP.OBJ %d\n", t3-t2);
fprintf(fp, "MAP.TRN %d\n", t4-t3);
fprintf(fp, "MAP.TRE %d\n", t5-t4);
#else
SetInverseViewAndDynamicShaodwMatrices();
SetBlendOperation();
RenderArea();
RenderTree();
if (!m_bEnableTerrainOnlyForHeight)
RenderTerrain();
RenderBlendArea();
#endif
}
struct FAreaRenderShadow
{
void operator () (CGraphicObjectInstance * pInstance)
{
pInstance->RenderShadow();
pInstance->Hide();
}
};
struct FPCBlockerHide
{
void operator () (CGraphicObjectInstance * pInstance)
{
pInstance->Hide();
}
};
struct FRenderPCBlocker
{
void operator () (CGraphicObjectInstance * pInstance)
{
pInstance->Show();
CGraphicThingInstance* pThingInstance = dynamic_cast <CGraphicThingInstance*> (pInstance);
if (pThingInstance != NULL)
{
if (pThingInstance->HaveBlendThing())
{
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
pThingInstance->BlendRender();
return;
}
}
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
pInstance->RenderPCBlocker();
}
};
void CMapOutdoor::RenderEffect()
{
if (!IsVisiblePart(PART_OBJECT))
return;
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (GetAreaPointer(i, &pArea))
{
pArea->RenderEffect();
}
}
}
struct CMapOutdoor_LessThingInstancePtrRenderOrder
{
bool operator() (CGraphicThingInstance* pkLeft, CGraphicThingInstance* pkRight)
{
//TODO : Camera위치기반으로 소팅
CCamera * pCurrentCamera = CCameraManager::Instance().GetCurrentCamera();
const D3DXVECTOR3 & c_rv3CameraPos = pCurrentCamera->GetEye();
const D3DXVECTOR3 & c_v3LeftPos = pkLeft->GetPosition();
const D3DXVECTOR3 & c_v3RightPos = pkRight->GetPosition();
const auto vv = D3DXVECTOR3(c_rv3CameraPos - c_v3RightPos);
const auto vv2 = D3DXVECTOR3(c_rv3CameraPos - c_v3LeftPos);
return D3DXVec3LengthSq(&vv2) < D3DXVec3LengthSq(&vv);
}
};
struct CMapOutdoor_FOpaqueThingInstanceRender
{
inline void operator () (CGraphicThingInstance * pkThingInst)
{
pkThingInst->Render();
}
};
struct CMapOutdoor_FBlendThingInstanceRender
{
inline void operator () (CGraphicThingInstance * pkThingInst)
{
pkThingInst->BlendRender();
}
};
void CMapOutdoor::RenderArea(bool bRenderAmbience)
{
if (!IsVisiblePart(PART_OBJECT))
return;
m_dwRenderedCRCNum = 0;
m_dwRenderedGraphicThingInstanceNum = 0;
m_dwRenderedCRCWithNumberVector.clear();
// NOTE - 20041201.levites.던젼 그림자 추가
for (int j = 0; j < AROUND_AREA_NUM; ++j)
{
CArea * pArea;
if (GetAreaPointer(j, &pArea))
{
pArea->RenderDungeon();
}
}
#ifndef WORLD_EDITOR
// PCBlocker
std::for_each(m_PCBlockerVector.begin(), m_PCBlockerVector.end(), FPCBlockerHide());
// Shadow Receiver
if (m_bDrawShadow && m_bDrawChrShadow)
{
if (mc_pEnvironmentData != NULL)
STATEMANAGER.SetRenderState(D3DRS_FOGCOLOR, 0xFFFFFFFF);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
// Transform
STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &m_matDynamicShadow);
STATEMANAGER.SetTexture(1, m_lpCharacterShadowMapTexture);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_BORDER);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_BORDER);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_BORDERCOLOR, 0xFFFFFFFF);
std::for_each(m_ShadowReceiverVector.begin(), m_ShadowReceiverVector.end(), FAreaRenderShadow());
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_BORDERCOLOR);
STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1);
if (mc_pEnvironmentData != NULL)
STATEMANAGER.SetRenderState(D3DRS_FOGCOLOR, mc_pEnvironmentData->FogColor);
}
#endif
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, TRUE);
bool m_isDisableSortRendering=false;
if (m_isDisableSortRendering)
{
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (GetAreaPointer(i, &pArea))
{
pArea->Render();
m_dwRenderedCRCNum += pArea->DEBUG_GetRenderedCRCNum();
m_dwRenderedGraphicThingInstanceNum += pArea->DEBUG_GetRenderedGrapphicThingInstanceNum();
CArea::TCRCWithNumberVector & rCRCWithNumberVector = pArea->DEBUG_GetRenderedCRCWithNumVector();
CArea::TCRCWithNumberVector::iterator aIterator = rCRCWithNumberVector.begin();
while (aIterator != rCRCWithNumberVector.end())
{
DWORD dwCRC = (*aIterator++).dwCRC;
CArea::TCRCWithNumberVector::iterator aCRCWithNumberVectorIterator =
std::find_if(m_dwRenderedCRCWithNumberVector.begin(), m_dwRenderedCRCWithNumberVector.end(), CArea::FFindIfCRC(dwCRC));
if ( m_dwRenderedCRCWithNumberVector.end() == aCRCWithNumberVectorIterator)
{
CArea::TCRCWithNumber aCRCWithNumber;
aCRCWithNumber.dwCRC = dwCRC;
aCRCWithNumber.dwNumber = 1;
m_dwRenderedCRCWithNumberVector.push_back(aCRCWithNumber);
}
else
{
CArea::TCRCWithNumber & rCRCWithNumber = *aCRCWithNumberVectorIterator;
rCRCWithNumber.dwNumber += 1;
}
}
#ifdef WORLD_EDITOR
if (bRenderAmbience)
pArea->RenderAmbience();
#endif
}
}
std::sort(m_dwRenderedCRCWithNumberVector.begin(), m_dwRenderedCRCWithNumberVector.end(), CArea::CRCNumComp());
}
else
{
static std::vector<CGraphicThingInstance*> s_kVct_pkOpaqueThingInstSort;
s_kVct_pkOpaqueThingInstSort.clear();
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (GetAreaPointer(i, &pArea))
{
pArea->CollectRenderingObject(s_kVct_pkOpaqueThingInstSort);
#ifdef WORLD_EDITOR
if (bRenderAmbience)
pArea->RenderAmbience();
#endif
}
}
std::sort(s_kVct_pkOpaqueThingInstSort.begin(), s_kVct_pkOpaqueThingInstSort.end(), CMapOutdoor_LessThingInstancePtrRenderOrder());
std::for_each(s_kVct_pkOpaqueThingInstSort.begin(), s_kVct_pkOpaqueThingInstSort.end(), CMapOutdoor_FOpaqueThingInstanceRender());
}
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
#ifndef WORLD_EDITOR
// Shadow Receiver
if (m_bDrawShadow && m_bDrawChrShadow)
{
std::for_each(m_ShadowReceiverVector.begin(), m_ShadowReceiverVector.end(), std::mem_fn(&CGraphicObjectInstance::Show));
}
#endif
}
void CMapOutdoor::RenderBlendArea()
{
if (!IsVisiblePart(PART_OBJECT))
return;
static std::vector<CGraphicThingInstance*> s_kVct_pkBlendThingInstSort;
s_kVct_pkBlendThingInstSort.clear();
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (GetAreaPointer(i, &pArea))
{
pArea->CollectBlendRenderingObject(s_kVct_pkBlendThingInstSort);
}
}
if (s_kVct_pkBlendThingInstSort.size() != 0)
{
//STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
//STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
//STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
//STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
//STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
//STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
//// Transform
//STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &m_matDynamicShadow);
//STATEMANAGER.SetTexture(1, m_lpCharacterShadowMapTexture);
//STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
//STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
//STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
//STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
//STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_BORDER);
//STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_BORDER);
//STATEMANAGER.SaveTextureStageState(1, D3DTSS_BORDERCOLOR, 0xFFFFFFFF);
////std::for_each(m_ShadowReceiverVector.begin(), m_ShadowReceiverVector.end(), FAreaRenderShadow());
//STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX);
//STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS);
//STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU);
//STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV);
//STATEMANAGER.RestoreTextureStageState(1, D3DTSS_BORDERCOLOR);
//STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1);
std::sort(s_kVct_pkBlendThingInstSort.begin(), s_kVct_pkBlendThingInstSort.end(), CMapOutdoor_LessThingInstancePtrRenderOrder());
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
std::for_each(s_kVct_pkBlendThingInstSort.begin(), s_kVct_pkBlendThingInstSort.end(), CMapOutdoor_FBlendThingInstanceRender());
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
}
}
void CMapOutdoor::RenderDungeon()
{
for (int i = 0; i < AROUND_AREA_NUM; ++i)
{
CArea * pArea;
if (!GetAreaPointer(i, &pArea))
continue;
pArea->RenderDungeon();
}
}
void CMapOutdoor::RenderPCBlocker()
{
#ifndef WORLD_EDITOR
// PCBlocker
if (m_PCBlockerVector.size() != 0)
{
STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &m_matBuildingTransparent);
STATEMANAGER.SetTexture(1, m_BuildingTransparentImageInstance.GetTexturePointer()->GetD3DTexture());
std::for_each(m_PCBlockerVector.begin(), m_PCBlockerVector.end(), FRenderPCBlocker());
STATEMANAGER.SetTexture(1, NULL);
STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
}
#endif
}
void CMapOutdoor::SelectIndexBuffer(BYTE byLODLevel, WORD * pwPrimitiveCount, D3DPRIMITIVETYPE * pePrimitiveType)
{
#ifdef WORLD_EDITOR
*pwPrimitiveCount = m_wNumIndices - 2;
*pePrimitiveType = D3DPT_TRIANGLESTRIP;
STATEMANAGER.SetIndices(m_IndexBuffer.GetD3DIndexBuffer(), 0);
#else
if (0 == byLODLevel)
{
*pwPrimitiveCount = m_wNumIndices[byLODLevel] - 2;
*pePrimitiveType = D3DPT_TRIANGLESTRIP;
}
else
{
*pwPrimitiveCount = m_wNumIndices[byLODLevel]/3;
*pePrimitiveType = D3DPT_TRIANGLELIST;
}
STATEMANAGER.SetIndices(m_IndexBuffer[byLODLevel].GetD3DIndexBuffer(), 0);
#endif
}
void CMapOutdoor::SetPatchDrawVector()
{
assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::__SetPatchDrawVector");
m_PatchDrawStructVector.clear();
std::vector<std::pair<float, long> >::iterator aDistancePatchVectorIterator;
TPatchDrawStruct aPatchDrawStruct;
aDistancePatchVectorIterator = m_PatchVector.begin();
while(aDistancePatchVectorIterator != m_PatchVector.end())
{
std::pair<float, long> adistancePatchPair = *aDistancePatchVectorIterator;
CTerrainPatchProxy * pTerrainPatchProxy = &m_pTerrainPatchProxyList[adistancePatchPair.second];
if (!pTerrainPatchProxy->isUsed())
{
++aDistancePatchVectorIterator;
continue;
}
long lPatchNum = pTerrainPatchProxy->GetPatchNum();
if (lPatchNum < 0)
{
++aDistancePatchVectorIterator;
continue;
}
BYTE byTerrainNum = pTerrainPatchProxy->GetTerrainNum();
if (0xFF == byTerrainNum)
{
++aDistancePatchVectorIterator;
continue;
}
CTerrain * pTerrain;
if (!GetTerrainPointer(byTerrainNum, &pTerrain))
{
++aDistancePatchVectorIterator;
continue;
}
aPatchDrawStruct.fDistance = adistancePatchPair.first;
aPatchDrawStruct.byTerrainNum = byTerrainNum;
aPatchDrawStruct.lPatchNum = lPatchNum;
aPatchDrawStruct.pTerrainPatchProxy = pTerrainPatchProxy;
m_PatchDrawStructVector.push_back(aPatchDrawStruct);
++aDistancePatchVectorIterator;
}
std::stable_sort(m_PatchDrawStructVector.begin(), m_PatchDrawStructVector.end(), FSortPatchDrawStructWithTerrainNum());
}
float CMapOutdoor::__GetNoFogDistance()
{
return (float)(CTerrainImpl::CELLSCALE * m_lViewRadius) * 0.5f;
}
float CMapOutdoor::__GetFogDistance()
{
return (float)(CTerrainImpl::CELLSCALE * m_lViewRadius) * 0.75f;
}
struct FPatchNumMatch
{
long m_lPatchNumToCheck;
FPatchNumMatch(long lPatchNum)
{
m_lPatchNumToCheck = lPatchNum;
}
bool operator() (std::pair<long, BYTE> aPair)
{
return m_lPatchNumToCheck == aPair.first;
}
};
void CMapOutdoor::NEW_DrawWireFrame(CTerrainPatchProxy * pTerrainPatchProxy, WORD wPrimitiveCount, D3DPRIMITIVETYPE ePrimitiveType)
{
DWORD dwFillMode = STATEMANAGER.GetRenderState(D3DRS_FILLMODE);
STATEMANAGER.SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
DWORD dwFogEnable = STATEMANAGER.GetRenderState(D3DRS_FOGENABLE);
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, FALSE);
STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTexture(1, NULL);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount);
STATEMANAGER.SetRenderState(D3DRS_FILLMODE, dwFillMode);
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, dwFogEnable);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
}
void CMapOutdoor::DrawWireFrame(long patchnum, WORD wPrimitiveCount, D3DPRIMITIVETYPE ePrimitiveType)
{
assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::DrawWireFrame");
CTerrainPatchProxy * pTerrainPatchProxy= &m_pTerrainPatchProxyList[patchnum];
if (!pTerrainPatchProxy->isUsed())
return;
long sPatchNum = pTerrainPatchProxy->GetPatchNum();
if (sPatchNum < 0)
return;
BYTE ucTerrainNum = pTerrainPatchProxy->GetTerrainNum();
if (0xFF == ucTerrainNum)
return;
DWORD dwFillMode = STATEMANAGER.GetRenderState(D3DRS_FILLMODE);
STATEMANAGER.SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
DWORD dwFogEnable = STATEMANAGER.GetRenderState(D3DRS_FOGENABLE);
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, FALSE);
STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTexture(1, NULL);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount);
STATEMANAGER.SetRenderState(D3DRS_FILLMODE, dwFillMode);
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, dwFogEnable);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
}
// Attr
void CMapOutdoor::RenderMarkedArea()
{
if (!m_pTerrainPatchProxyList)
return;
m_matWorldForCommonUse._41 = 0.0f;
m_matWorldForCommonUse._42 = 0.0f;
STATEMANAGER.SetTransform(D3DTS_WORLD, &m_matWorldForCommonUse);
WORD wPrimitiveCount;
D3DPRIMITIVETYPE eType;
SelectIndexBuffer(0, &wPrimitiveCount, &eType);
D3DXMATRIX matTexTransform, matTexTransformTemp;
D3DXMatrixScaling(&matTexTransform, m_fTerrainTexCoordBase * 32.0f, -m_fTerrainTexCoordBase * 32.0f, 0.0f);
D3DXMatrixMultiply(&matTexTransform, &m_matViewInverse, &matTexTransform);
STATEMANAGER.SaveTransform(D3DTS_TEXTURE0, &matTexTransform);
STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &matTexTransform);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
static long lStartTime = timeGetTime();
float fTime = float((timeGetTime() - lStartTime)%3000) / 3000.0f;
float fAlpha = fabs(fTime - 0.5f) / 2.0f + 0.1f;
STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, D3DXCOLOR(1.0f, 1.0f, 1.0f, fAlpha));
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_POINT);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
STATEMANAGER.SetTexture(0, m_attrImageInstance.GetTexturePointer()->GetD3DTexture());
RecurseRenderAttr(m_pRootNode);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXCOORDINDEX);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_MINFILTER);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_MAGFILTER);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_MIPFILTER);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU);
STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV);
STATEMANAGER.RestoreTransform(D3DTS_TEXTURE0);
STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND);
}
void CMapOutdoor::RecurseRenderAttr(CTerrainQuadtreeNode *Node, bool bCullEnable)
{
if (bCullEnable)
{
if (__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle(Node->center, Node->radius)==VIEW_NONE)
return;
}
{
if (Node->Size == 1)
{
DrawPatchAttr(Node->PatchNum);
}
else
{
if (Node->NW_Node != NULL)
RecurseRenderAttr(Node->NW_Node, bCullEnable);
if (Node->NE_Node != NULL)
RecurseRenderAttr(Node->NE_Node, bCullEnable);
if (Node->SW_Node != NULL)
RecurseRenderAttr(Node->SW_Node, bCullEnable);
if (Node->SE_Node != NULL)
RecurseRenderAttr(Node->SE_Node, bCullEnable);
}
}
}
void CMapOutdoor::DrawPatchAttr(long patchnum)
{
CTerrainPatchProxy * pTerrainPatchProxy = &m_pTerrainPatchProxyList[patchnum];
if (!pTerrainPatchProxy->isUsed())
return;
long sPatchNum = pTerrainPatchProxy->GetPatchNum();
if (sPatchNum < 0)
return;
BYTE ucTerrainNum = pTerrainPatchProxy->GetTerrainNum();
if (0xFF == ucTerrainNum)
return;
// Deal with this material buffer
CTerrain * pTerrain;
if (!GetTerrainPointer(ucTerrainNum, &pTerrain))
return;
if (!pTerrain->IsMarked())
return;
WORD wCoordX, wCoordY;
pTerrain->GetCoordinate(&wCoordX, &wCoordY);
m_matWorldForCommonUse._41 = -(float) (wCoordX * CTerrainImpl::XSIZE * CTerrainImpl::CELLSCALE);
m_matWorldForCommonUse._42 = (float) (wCoordY * CTerrainImpl::YSIZE * CTerrainImpl::CELLSCALE);
D3DXMATRIX matTexTransform, matTexTransformTemp;
D3DXMatrixMultiply(&matTexTransform, &m_matViewInverse, &m_matWorldForCommonUse);
D3DXMatrixMultiply(&matTexTransform, &matTexTransform, &m_matStaticShadow);
STATEMANAGER.SetTransform(D3DTS_TEXTURE1, &matTexTransform);
TTerrainSplatPatch & rAttrSplatPatch = pTerrain->GetMarkedSplatPatch();
STATEMANAGER.SetTexture(1, rAttrSplatPatch.Splats[0].pd3dTexture);
STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_NORMAL);
STATEMANAGER.SetStreamSource(0, pTerrainPatchProxy->HardwareTransformPatch_GetVertexBufferPtr()->GetD3DVertexBuffer(), m_iPatchTerrainVertexSize);
#ifdef WORLD_EDITOR
STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, m_iPatchTerrainVertexCount, 0, m_wNumIndices - 2);
#else
STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, m_iPatchTerrainVertexCount, 0, m_wNumIndices[0] - 2);
#endif
}
File diff suppressed because it is too large Load Diff
+299
View File
@@ -0,0 +1,299 @@
#include "StdAfx.h"
#include "../EterBase/Filename.h"
#include "Property.h"
float SEnvironmentData::GetFogNearDistance() const
{
return m_fFogNearDistance;
}
float SEnvironmentData::GetFogFarDistance() const
{
return m_fFogFarDistance;
}
float SPixelPosition_CalculateDistanceSq3d(const TPixelPosition& c_rkPPosLeft, const TPixelPosition& c_rkPPosRight)
{
float dx=c_rkPPosLeft.x-c_rkPPosRight.x;
float dy=c_rkPPosLeft.y-c_rkPPosRight.y;
float dz=c_rkPPosLeft.z-c_rkPPosRight.z;
return dx*dx+dy*dy+dz*dz;
}
namespace prt
{
DWORD GetPropertyType(const char * c_szTypeName)
{
for (DWORD i = 0; i < PROPERTY_TYPE_MAX_NUM; ++i)
{
if (!strcmp(c_szPropertyTypeName[i], c_szTypeName))
return i;
}
return PROPERTY_TYPE_NONE;
}
const char * GetPropertyExtension(DWORD dwType)
{
if (dwType >= PROPERTY_TYPE_MAX_NUM)
return c_szPropertyExtension[0];
return c_szPropertyExtension[dwType];
}
const char * IntegerNumberToString(int iNumber)
{
static char szString[16+1];
_snprintf(szString, sizeof(szString), "%d", iNumber);
return szString;
}
const char * FloatNumberToString(float fNumber)
{
static char szString[16+1];
_snprintf(szString, sizeof(szString), "%f", fNumber);
return szString;
}
bool PropertyTreeDataToString(TPropertyTree * pData, CProperty * pProperty)
{
pProperty->Clear();
pProperty->PutString("PropertyType", "Tree");
pProperty->PutString("PropertyName", pData->strName.c_str());
pProperty->PutString("TreeFile", pData->strFileName.c_str());
pProperty->PutString("TreeSize", FloatNumberToString(pData->fSize));
pProperty->PutString("TreeVariance", FloatNumberToString(pData->fVariance));
return true;
}
bool PropertyTreeStringToData(CProperty * pProperty, TPropertyTree * pData)
{
const char * c_pszPropertyType;
const char * c_pszPropertyName;
if (!pProperty->GetString("PropertyType", &c_pszPropertyType))
return false;
if (!pProperty->GetString("PropertyName", &c_pszPropertyName))
return false;
if (strcmp(c_pszPropertyType, "Tree"))
return false;
pData->strName = c_pszPropertyName;
///////////////////////////////////////////////////////////////////////////////////
const char * c_pszTreeName;
const char * c_pszTreeSize;
const char * c_pszTreeVariance;
if (!pProperty->GetString("TreeFile", &c_pszTreeName))
return false;
if (!pProperty->GetString("TreeSize", &c_pszTreeSize))
return false;
if (!pProperty->GetString("TreeVariance", &c_pszTreeVariance))
return false;
pData->strFileName = c_pszTreeName;
pData->fSize = atof(c_pszTreeSize);
pData->fVariance = atof(c_pszTreeVariance);
return true;
}
bool PropertyBuildingDataToString(TPropertyBuilding * pData, CProperty * pProperty)
{
pProperty->Clear();
pProperty->PutString("PropertyType", "Building");
pProperty->PutString("PropertyName", pData->strName.c_str());
pProperty->PutString("BuildingFile", pData->strFileName.c_str());
pProperty->PutString("ShadowFlag", IntegerNumberToString(pData->isShadowFlag));
return true;
}
bool PropertyBuildingStringToData(CProperty * pProperty, TPropertyBuilding * pData)
{
const char * c_pszPropertyType;
const char * c_pszPropertyName;
if (!pProperty->GetString("PropertyType", &c_pszPropertyType))
return false;
if (!pProperty->GetString("PropertyName", &c_pszPropertyName))
return false;
if (strcmp(c_pszPropertyType, "Building"))
return false;
pData->strName = c_pszPropertyName;
///////////////////////////////////////////////////////////////////////////////////
const char * c_pszBuildingName;
if (!pProperty->GetString("BuildingFile", &c_pszBuildingName))
return false;
pData->strFileName = c_pszBuildingName;
pData->strAttributeDataFileName = CFileNameHelper::NoExtension(pData->strFileName) + ".mdatr";
const char * c_pszShadowFlag;
if (!pProperty->GetString("ShadowFlag", &c_pszShadowFlag))
{
pData->isShadowFlag = FALSE;
}
else
{
pData->isShadowFlag = atoi(c_pszShadowFlag);
}
return true;
}
bool PropertyEffectDataToString(TPropertyEffect * pData, CProperty * pProperty)
{
pProperty->Clear();
pProperty->PutString("PropertyType", "Effect");
pProperty->PutString("PropertyName", pData->strName.c_str());
pProperty->PutString("EffectFile", pData->strFileName.c_str());
return true;
}
bool PropertyEffectStringToData(CProperty * pProperty, TPropertyEffect * pData)
{
const char * c_pszPropertyType;
const char * c_pszPropertyName;
if (!pProperty->GetString("PropertyType", &c_pszPropertyType))
return false;
if (!pProperty->GetString("PropertyName", &c_pszPropertyName))
return false;
if (strcmp(c_pszPropertyType, "Effect"))
return false;
pData->strName = c_pszPropertyName;
///////////////////////////////////////////////////////////////////////////////////
const char * c_pszEffectName;
if (!pProperty->GetString("EffectFile", &c_pszEffectName))
return false;
pData->strFileName = c_pszEffectName;
return true;
}
bool PropertyAmbienceDataToString(TPropertyAmbience * pData, CProperty * pProperty)
{
pProperty->Clear();
pProperty->PutString("PropertyType", "Ambience");
pProperty->PutString("PropertyName", pData->strName.c_str());
pProperty->PutString("PlayType", pData->strPlayType.c_str());
pProperty->PutString("PlayInterval", FloatNumberToString(pData->fPlayInterval));
pProperty->PutString("PlayIntervalVariation", FloatNumberToString(pData->fPlayIntervalVariation));
pProperty->PutString("MaxVolumeAreaPercentage", FloatNumberToString(pData->fMaxVolumeAreaPercentage));
CTokenVector AmbienceSoundVector;
std::vector<std::string>::iterator itor = pData->AmbienceSoundVector.begin();
for (; itor != pData->AmbienceSoundVector.end(); ++itor)
{
std::string & rstrToken = *itor;
AmbienceSoundVector.push_back(rstrToken.c_str());
}
pProperty->PutVector("AmbienceSoundVector", AmbienceSoundVector);
return true;
}
bool PropertyAmbienceStringToData(CProperty * pProperty, TPropertyAmbience * pData)
{
const char * c_pszPropertyType;
const char * c_pszPropertyName;
if (!pProperty->GetString("PropertyType", &c_pszPropertyType))
return false;
if (!pProperty->GetString("PropertyName", &c_pszPropertyName))
return false;
if (strcmp(c_pszPropertyType, "Ambience"))
return false;
pData->strName = c_pszPropertyName;
///////////////////////////////////////////////////////////////////////////////////
const char * c_pszPlayType;
const char * c_pszPlayInterval;
const char * c_pszPlayIntervalVariation;
const char * c_pszMaxVolumeAreaPercentage = NULL;
CTokenVector AmbienceSoundVector;
if (!pProperty->GetString("PlayType", &c_pszPlayType))
return false;
if (!pProperty->GetString("PlayInterval", &c_pszPlayInterval))
return false;
if (!pProperty->GetString("PlayIntervalVariation", &c_pszPlayIntervalVariation))
return false;
if (!pProperty->GetString("MaxVolumeAreaPercentage", &c_pszMaxVolumeAreaPercentage))
{
pData->fMaxVolumeAreaPercentage = 0.0f;
}
if (!pProperty->GetVector("AmbienceSoundVector", AmbienceSoundVector))
return false;
pData->strPlayType = c_pszPlayType;
pData->fPlayInterval = atof(c_pszPlayInterval);
pData->fPlayIntervalVariation = atof(c_pszPlayIntervalVariation);
if (c_pszMaxVolumeAreaPercentage)
pData->fMaxVolumeAreaPercentage = atof(c_pszMaxVolumeAreaPercentage);
for (CTokenVector::iterator itor = AmbienceSoundVector.begin(); itor != AmbienceSoundVector.end(); ++itor)
pData->AmbienceSoundVector.push_back(*itor);
return true;
}
bool PropertyDungeonBlockDataToString(TPropertyDungeonBlock * pData, CProperty * pProperty)
{
pProperty->Clear();
pProperty->PutString("PropertyType", "DungeonBlock");
pProperty->PutString("PropertyName", pData->strName.c_str());
pProperty->PutString("DungeonBlockFile", pData->strFileName.c_str());
return true;
}
bool PropertyDungeonBlockStringToData(CProperty * pProperty, TPropertyDungeonBlock * pData)
{
const char * c_pszPropertyType;
const char * c_pszPropertyName;
if (!pProperty->GetString("PropertyType", &c_pszPropertyType))
return false;
if (!pProperty->GetString("PropertyName", &c_pszPropertyName))
return false;
if (strcmp(c_pszPropertyType, "DungeonBlock"))
return false;
pData->strName = c_pszPropertyName;
///////////////////////////////////////////////////////////////////////////////////
const char * c_pszDungeonBlockFileName = NULL;
if (!pProperty->GetString("dungeonblockfile", &c_pszDungeonBlockFileName))
return false;
pData->strFileName = c_pszDungeonBlockFileName;
pData->strAttributeDataFileName = CFileNameHelper::NoExtension(pData->strFileName) + std::string(".mdatr");
return true;
}
}; // namespace prt;
@@ -0,0 +1,148 @@
// MonsterAreaInfo.cpp: implementation of the CMonsterAreaInfo class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "MonsterAreaInfo.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMonsterAreaInfo::CMonsterAreaInfo()
{
Clear();
}
CMonsterAreaInfo::~CMonsterAreaInfo()
{
Clear();
}
void CMonsterAreaInfo::Clear()
{
SetOrigin(-1, -1);
SetSize(-1, -1);
RemoveAllMonsters();
}
void CMonsterAreaInfo::SetOrigin(long lOriginX, long lOriginY)
{
m_lOriginX = lOriginX;
m_lOriginY = lOriginY;
SetLRTB();
}
void CMonsterAreaInfo::SetSize(long lSizeX, long lSizeY)
{
m_lSizeX = lSizeX;
m_lSizeY = lSizeY;
SetLRTB();
}
void CMonsterAreaInfo::GetOrigin(long * plOriginX, long * plOriginY)
{
*plOriginX = m_lOriginX;
*plOriginY = m_lOriginY;
}
void CMonsterAreaInfo::GetSize(long * plSizeX, long * plSizeY)
{
*plSizeX = m_lSizeX;
*plSizeY = m_lSizeY;
}
void CMonsterAreaInfo::SetLRTB()
{
m_lLeft = m_lOriginX - m_lSizeX;
m_lTop = m_lOriginY - m_lSizeY;
m_lRight = m_lOriginX + m_lSizeX;
m_lBottom = m_lOriginY + m_lSizeY;
}
void CMonsterAreaInfo::SetMonsterCount(DWORD dwCount)
{
m_dwMonsterCount = dwCount;
if (m_TempMonsterPosVector.size() == dwCount)
return;
m_TempMonsterPosVector.clear();
m_TempMonsterPosVector.resize(dwCount);
for (DWORD dwI = 0; dwI < dwCount; ++dwI)
{
m_TempMonsterPosVector[dwI].x = (float)random_range(m_lLeft, m_lRight);
m_TempMonsterPosVector[dwI].y = (float)random_range(m_lTop, m_lBottom);
}
}
void CMonsterAreaInfo::SetMonsterDirection(EMonsterDir eMonsterDir)
{
m_eMonsterDir = eMonsterDir;
D3DXMATRIX matRotation;
D3DXVECTOR3 v3Direction(0.0f, 1.0f, 0.0f);
float fDegree = 0.0f;
switch(m_eMonsterDir)
{
case DIR_RANDOM:
fDegree = (float) random_range(0, 7) * 45.0f;
break;
case DIR_NORTH:
fDegree = 0.0f;
break;
case DIR_NORTHEAST:
fDegree = 45.0f;
break;
case DIR_EAST:
fDegree = 90.0f;
break;
case DIR_SOUTHEAST:
fDegree = 135.0f;
break;
case DIR_SOUTH:
fDegree = 180.0f;
break;
case DIR_SOUTHWEST:
fDegree = 225.0f;
break;
case DIR_WEST:
fDegree = 270.0f;
break;
case DIR_NORTHWEST:
fDegree = 315.0f;
break;
}
D3DXMatrixRotationZ(&matRotation, -D3DXToRadian(fDegree));
D3DXVec3TransformCoord(&v3Direction, &v3Direction, &matRotation);
m_v2Monsterdirection.x = v3Direction.x;
m_v2Monsterdirection.y = v3Direction.y;
D3DXVec2Normalize(&m_v2Monsterdirection, &m_v2Monsterdirection);
}
void CMonsterAreaInfo::RemoveAllMonsters()
{
SetMonsterAreaInfoType(MONSTERAREAINFOTYPE_INVALID);
SetMonsterGroupID(0);
m_strGroupName.assign("\300\314\270\247\276\370\300\275");
m_strLeaderName.assign("\300\314\270\247\276\370\300\275");
SetMonsterGroupFollowerCount(0);
SetMonsterVID(0);
m_strMonsterName.assign("\300\314\270\247\276\370\300\275");
SetMonsterCount(0);
SetMonsterDirection(DIR_NORTH);
m_TempMonsterPosVector.clear();
}
D3DXVECTOR2 CMonsterAreaInfo::GetTempMonsterPos(DWORD dwIndex)
{
if (dwIndex >= m_TempMonsterPosVector.size())
return D3DXVECTOR2(0.0f, 0.0f);
return m_TempMonsterPosVector[dwIndex];
}
+269
View File
@@ -0,0 +1,269 @@
#include "StdAfx.h"
#include <string.h>
#include "../EterBase/TempFile.h"
#include "PropertyManager.h"
#include "Property.h"
/*
* CProperty 파일 포맷
*
* 0 ~ 4 bytes: fourcc
* 5 ~ 6 bytes: \r\n
*
* 그 이후의 바이트들은 텍스트 파일 로더와 같은 구조
*/
CProperty::CProperty(const char * c_pszFileName) : mc_pFileName(NULL), m_dwCRC(0)
{
m_stFileName = c_pszFileName;
StringPath(m_stFileName);
mc_pFileName = strrchr(m_stFileName.c_str(), '/');
if (!mc_pFileName)
mc_pFileName = m_stFileName.c_str();
else
++mc_pFileName;
}
CProperty::~CProperty()
{
}
DWORD CProperty::GetCRC()
{
return m_dwCRC;
}
const char * CProperty::GetFileName()
{
return (m_stFileName.c_str());
}
bool CProperty::GetString(const char * c_pszKey, const char ** c_ppString)
{
std::string stTempKey = c_pszKey;
stl_lowers(stTempKey);
CTokenVectorMap::iterator it = m_stTokenMap.find(stTempKey.c_str());
// printf("GetString %s %d\n", stTempKey.c_str(), m_stTokenMap.size());
if (m_stTokenMap.end() == it)
return false;
*c_ppString = it->second[0].c_str();
return true;
}
DWORD CProperty::GetSize()
{
return m_stTokenMap.size();
}
bool CProperty::GetVector(const char * c_pszKey, CTokenVector & rTokenVector)
{
std::string stTempKey = c_pszKey;
stl_lowers(stTempKey);
CTokenVectorMap::iterator it = m_stTokenMap.find(stTempKey.c_str());
if (m_stTokenMap.end() == it)
return false;
// NOTE : 튕김 현상 발견
// std::copy(rTokenVector.begin(), it->second.begin(), it->second.end());
// NOTE : 레퍼런스에는 이런 식으로 하게끔 되어 있음
///////////////////////////////////////////////////////////////////////////////
// template <class InputIterator, class OutputIterator>
// OutputIterator copy(InputIterator first, InputIterator last,
// OutputIterator result);
//
// vector<int> V(5);
// iota(V.begin(), V.end(), 1);
// list<int> L(V.size());
// copy(V.begin(), V.end(), L.begin());
// assert(equal(V.begin(), V.end(), L.begin()));
///////////////////////////////////////////////////////////////////////////////
// 헌데 그래도 튕김. - [levites]
// std::copy(it->second.begin(), it->second.end(), rTokenVector.begin());
// 결국 이렇게.. - [levites]
// 현재 사용하는 곳 : WorldEditor/Dialog/MapObjectPropertyPageBuilding.cpp
CTokenVector & rSourceTokenVector = it->second;
CTokenVector::iterator itor = rSourceTokenVector.begin();
for (; itor != rSourceTokenVector.end(); ++itor)
{
rTokenVector.push_back(*itor);
}
return true;
}
void CProperty::PutString(const char * c_pszKey, const char * c_pszString)
{
std::string stTempKey = c_pszKey;
stl_lowers(stTempKey);
// 이미 있는걸 지움
CTokenVectorMap::iterator itor = m_stTokenMap.find(stTempKey);
if (itor != m_stTokenMap.end())
m_stTokenMap.erase(itor);
CTokenVector tokenVector;
tokenVector.push_back(c_pszString);
m_stTokenMap.insert(CTokenVectorMap::value_type(stTempKey, tokenVector));
}
void CProperty::PutVector(const char * c_pszKey, const CTokenVector & c_rTokenVector)
{
std::string stTempKey = c_pszKey;
stl_lowers(stTempKey);
m_stTokenMap.insert(CTokenVectorMap::value_type(stTempKey, c_rTokenVector));
}
void GetTimeString(char * str, time_t ct)
{
struct tm tm;
tm = *localtime(&ct);
_snprintf(str, 15, "%04d%02d%02d%02d%02d%02d",
tm.tm_year + 1900,
tm.tm_mon + 1,
tm.tm_mday,
tm.tm_hour,
tm.tm_min,
tm.tm_sec);
}
bool CProperty::Save(const char * c_pszFileName)
{
CTempFile file;
DWORD fourcc = MAKEFOURCC('Y', 'P', 'R', 'T');
file.Write(&fourcc, sizeof(DWORD));
file.Write("\r\n", 2);
if (0 == m_stCRC.length())
{
char szCRC[MAX_PATH + 16 + 1];
GetTimeString(szCRC, time(0));
strcpy(szCRC + strlen(szCRC), c_pszFileName);
m_dwCRC = CPropertyManager::Instance().GetUniqueCRC(szCRC);
_snprintf(szCRC, sizeof(szCRC), "%u", m_dwCRC);
m_stCRC.assign(szCRC);
}
file.Write(m_stCRC.c_str(), m_stCRC.length());
file.Write("\r\n", 2);
CTokenVectorMap::iterator itor = m_stTokenMap.begin();
char buf[4096 + 1];
while (itor != m_stTokenMap.end())
{
CTokenVector & tokenVector = itor->second;
int len = _snprintf(buf, sizeof(buf), "%s\t", itor->first.c_str());
file.Write(buf, len);
for (DWORD i = 0; i < tokenVector.size(); ++i)
{
len = _snprintf(buf, sizeof(buf), "\t\"%s\"", tokenVector[i].c_str());
file.Write(buf, len);
}
file.Write("\r\n", 2);
++itor;
}
file.Close();
return CPropertyManager::Instance().Put(c_pszFileName, file.GetFileName());
}
bool CProperty::ReadFromMemory(const void * c_pvData, int iLen, const char * c_pszFileName)
{
const char * pcData = (const char *) c_pvData;
if (*(DWORD *) pcData != MAKEFOURCC('Y', 'P', 'R', 'T'))
return false;
pcData += sizeof(DWORD);
if (*pcData != '\r' || *(pcData + 1) != '\n')
{
TraceError("CProperty::ReadFromMemory: File format error after FourCC: %s\n", c_pszFileName);
return false;
}
pcData += 2;
CTokenVector stTokenVector;
/*
char szTimeStamp[64];
memcpy(szTimeStamp, pcData, 14);
szTimeStamp[14] = '\0';
pcData += 14;
if (*pcData != '\r' || *(pcData + 1) != '\n')
{
TraceError("CProperty::ReadFromMemory: File format error after TimeStamp: %s\n", c_pszFileName);
return false;
}
std::string m_stTimeStamp;
m_stTimeStamp = szTimeStamp;
int iTimeStampLen = 14 + _snprintf(szTimeStamp + 14, 64 - 14, "%s", mc_pFileName);
m_dwCRC = GetCRC32(szTimeStamp, iTimeStampLen);
char tmp[64];
sprintf(tmp, "%u", m_dwCRC);
m_stCRC.assign(tmp);
CMemoryTextFileLoader textFileLoader;
textFileLoader.Bind(iLen - (sizeof(DWORD) + 2 + 14 + 2), pcData);
for (DWORD i = 0; i < textFileLoader.GetLineCount(); ++i)
{
if (!textFileLoader.SplitLine(i, &stTokenVector))
continue;
stl_lowers(stTokenVector[0]);
std::string stKey = stTokenVector[0];
stTokenVector.erase(stTokenVector.begin());
PutVector(stKey.c_str(), stTokenVector);
}
return true;
*/
CMemoryTextFileLoader textFileLoader;
textFileLoader.Bind(iLen - (sizeof(DWORD) + 2), pcData);
m_stCRC = textFileLoader.GetLineString(0);
m_dwCRC = atoi(m_stCRC.c_str());
for (DWORD i = 1; i < textFileLoader.GetLineCount(); ++i)
{
if (!textFileLoader.SplitLine(i, &stTokenVector))
continue;
stl_lowers(stTokenVector[0]);
std::string stKey = stTokenVector[0];
stTokenVector.erase(stTokenVector.begin());
PutVector(stKey.c_str(), stTokenVector);
}
//Tracef("Property: %s\n", c_pszFileName);
return true;
}
void CProperty::Clear()
{
m_stTokenMap.clear();
}
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <string>
class CProperty
{
public:
CProperty(const char * c_pszFileName);
~CProperty();
void Clear();
bool ReadFromMemory(const void * c_pvData, int iLen, const char * c_pszFileName);
const char * GetFileName();
bool GetVector(const char * c_pszKey, CTokenVector & rTokenVector);
bool GetString(const char * c_pszKey, const char ** c_ppString);
void PutVector(const char * c_pszKey, const CTokenVector & c_rTokenVector);
void PutString(const char * c_pszKey, const char * c_pszString);
bool Save(const char * c_pszFileName);
DWORD GetSize();
DWORD GetCRC();
protected:
std::string m_stFileName;
std::string m_stCRC;
const char * mc_pFileName;
DWORD m_dwCRC;
CTokenVectorMap m_stTokenMap;
};
@@ -0,0 +1,68 @@
#include "StdAfx.h"
#include "PropertyLoader.h"
#include "PropertyManager.h"
#include "Property.h"
bool CPropertyLoader::OnFolder(const char* c_szFilter, const char* c_szPathName, const char* c_szFileName)
{
std::string stPathName = "";
stPathName += c_szPathName;
stPathName += c_szFileName;
CPropertyLoader PropertyLoader;
PropertyLoader.SetPropertyManager(m_pPropertyManager);
PropertyLoader.Create(c_szFilter, stPathName.c_str());
return true;
}
bool CPropertyLoader::OnFile(const char* c_szPathName, const char* c_szFileName)
{
RegisterFile(c_szPathName, c_szFileName);
return true;
}
DWORD CPropertyLoader::RegisterFile(const char * c_szPathName, const char * c_szFileName)
{
std::string strFileName = "";
strFileName += c_szPathName;
strFileName += c_szFileName;
std::string stExt;
GetFileExtension(strFileName.c_str(), strFileName.length(), &stExt);
stl_lowers(stExt);
stl_lowers(strFileName);
// 패스를 소문자로 만들고 \\ 는 / 로 바꾼다.
StringPath(strFileName);
// 예약된 CRC 처리 (지워진 CRC)
if (0 == strFileName.compare("property/reserve"))
{
m_pPropertyManager->LoadReservedCRC(strFileName.c_str());
return 1;
}
else
{
CProperty * pProperty;
if (m_pPropertyManager->Register(strFileName.c_str(), &pProperty))
return pProperty->GetCRC();
else
return 0;
}
}
void CPropertyLoader::SetPropertyManager(CPropertyManager * pPropertyManager)
{
m_pPropertyManager = pPropertyManager;
}
CPropertyLoader::CPropertyLoader()
{
m_pPropertyManager = NULL;
}
CPropertyLoader::~CPropertyLoader()
{
}
@@ -0,0 +1,21 @@
#pragma once
#include "../EterBase/FileDir.h"
class CPropertyManager;
class CPropertyLoader : public CDir
{
public:
CPropertyLoader();
virtual ~CPropertyLoader();
void SetPropertyManager(CPropertyManager * pPropertyManager);
DWORD RegisterFile(const char* c_szPathName, const char* c_szFileName);
virtual bool OnFolder(const char* c_szFilter, const char* c_szPathName, const char* c_szFileName);
virtual bool OnFile(const char* c_szPathName, const char* c_szFileName);
protected:
CPropertyManager * m_pPropertyManager;
};
@@ -0,0 +1,255 @@
#include "StdAfx.h"
#include "../EterPack/EterPackManager.h"
#include "PropertyManager.h"
#include "Property.h"
CPropertyManager::CPropertyManager() : m_isFileMode(true)
{
}
CPropertyManager::~CPropertyManager()
{
Clear();
}
bool CPropertyManager::Initialize(const char * c_pszPackFileName)
{
if (c_pszPackFileName)
{
if (!m_pack.Create(m_fileDict, c_pszPackFileName, "", true))
{
LogBoxf("Cannot open property pack file (filename %s)", c_pszPackFileName);
return false;
}
m_isFileMode = false;
TDataPositionMap & indexMap = m_pack.GetIndexMap();
TDataPositionMap::iterator itor = indexMap.begin();
typedef std::map<DWORD, TEterPackIndex *> TDataPositionMap;
int i = 0;
while (indexMap.end() != itor)
{
TEterPackIndex * pIndex = itor->second;
++itor;
if (!stricmp("property/reserve", pIndex->filename))
{
LoadReservedCRC(pIndex->filename);
continue;
}
if (!Register(pIndex->filename))
continue;
++i;
}
}
else
{
m_isFileMode = true;
// NOTE : 여기서 Property를 등록시키면 WorldEditor에서 이상이 생김 ;
// 또한, Property Tree List에도 등록을 시켜야 되기 때문에 바깥쪽에서.. - [levites]
}
return true;
}
bool CPropertyManager::BuildPack()
{
if (!m_pack.Create(m_fileDict, "property", ""))
return false;
WIN32_FIND_DATA fdata;
HANDLE hFind = FindFirstFile("property\\*", &fdata);
if (hFind == INVALID_HANDLE_VALUE)
return false;
do
{
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
char szSourceFileName[256 + 1];
_snprintf(szSourceFileName, sizeof(szSourceFileName), "property\\%s", fdata.cFileName);
m_pack.Put(fdata.cFileName, szSourceFileName,COMPRESSED_TYPE_NONE,"");
}
while (FindNextFile(hFind, &fdata));
FindClose(hFind);
return true;
}
bool CPropertyManager::LoadReservedCRC(const char * c_pszFileName)
{
CMappedFile file;
LPCVOID c_pvData;
if (!CEterPackManager::Instance().Get(file, c_pszFileName, &c_pvData))
return false;
CMemoryTextFileLoader textFileLoader;
textFileLoader.Bind(file.Size(), c_pvData);
for (DWORD i = 0; i < textFileLoader.GetLineCount(); ++i)
{
const char * pszLine = textFileLoader.GetLineString(i).c_str();
if (!pszLine || !*pszLine)
continue;
ReserveCRC(atoi(pszLine));
}
return true;
}
void CPropertyManager::ReserveCRC(DWORD dwCRC)
{
m_ReservedCRCSet.insert(dwCRC);
}
DWORD CPropertyManager::GetUniqueCRC(const char * c_szSeed)
{
std::string stTmp = c_szSeed;
while (1)
{
DWORD dwCRC = GetCRC32(stTmp.c_str(), stTmp.length());
if (m_ReservedCRCSet.find(dwCRC) == m_ReservedCRCSet.end() &&
m_PropertyByCRCMap.find(dwCRC) == m_PropertyByCRCMap.end())
return dwCRC;
char szAdd[2];
_snprintf(szAdd, sizeof(szAdd), "%d", random() % 10);
stTmp += szAdd;
}
}
bool CPropertyManager::Register(const char * c_pszFileName, CProperty ** ppProperty)
{
CMappedFile file;
LPCVOID c_pvData;
if (!CEterPackManager::Instance().Get(file, c_pszFileName, &c_pvData))
return false;
CProperty * pProperty = new CProperty(c_pszFileName);
if (!pProperty->ReadFromMemory(c_pvData, file.Size(), c_pszFileName))
{
delete pProperty;
return false;
}
DWORD dwCRC = pProperty->GetCRC();
TPropertyCRCMap::iterator itor = m_PropertyByCRCMap.find(dwCRC);
if (m_PropertyByCRCMap.end() != itor)
{
Tracef("Property already registered, replace %s to %s\n",
itor->second->GetFileName(),
c_pszFileName);
delete itor->second;
itor->second = pProperty;
}
else
m_PropertyByCRCMap.insert(TPropertyCRCMap::value_type(dwCRC, pProperty));
if (ppProperty)
*ppProperty = pProperty;
return true;
}
bool CPropertyManager::Get(const char * c_pszFileName, CProperty ** ppProperty)
{
return Register(c_pszFileName, ppProperty);
}
bool CPropertyManager::Get(DWORD dwCRC, CProperty ** ppProperty)
{
TPropertyCRCMap::iterator itor = m_PropertyByCRCMap.find(dwCRC);
if (m_PropertyByCRCMap.end() == itor)
return false;
*ppProperty = itor->second;
return true;
}
bool CPropertyManager::Put(const char * c_pszFileName, const char * c_pszSourceFileName)
{
if (!CopyFile(c_pszSourceFileName, c_pszFileName, FALSE))
return false;
if (!m_isFileMode) // 팩 파일에도 넣음
{
if (!m_pack.Put(c_pszFileName, NULL, COMPRESSED_TYPE_NONE,""))
{
assert(!"CPropertyManager::Put cannot write to pack file");
return false;
}
}
Register(c_pszFileName);
return true;
}
bool CPropertyManager::Erase(DWORD dwCRC)
{
TPropertyCRCMap::iterator itor = m_PropertyByCRCMap.find(dwCRC);
if (m_PropertyByCRCMap.end() == itor)
return false;
CProperty * pProperty = itor->second;
m_PropertyByCRCMap.erase(itor);
DeleteFile(pProperty->GetFileName());
ReserveCRC(pProperty->GetCRC());
if (!m_isFileMode) // 파일 모드가 아니면 팩에서도 지움
m_pack.Delete(pProperty->GetFileName());
FILE * fp = fopen("property/reserve", "a+");
if (!fp)
LogBox("\277\271\276\340 CRC \306\304\300\317\300\273 \277\255 \274\366 \276\370\275\300\264\317\264\331.");
else
{
char szCRC[64 + 1];
_snprintf(szCRC, sizeof(szCRC), "%u\r\n", pProperty->GetCRC());
fputs(szCRC, fp);
fclose(fp);
}
delete pProperty;
return true;
}
bool CPropertyManager::Erase(const char * c_pszFileName)
{
CProperty * pProperty = NULL;
if (Get(c_pszFileName, &pProperty))
return Erase(pProperty->GetCRC());
return false;
}
void CPropertyManager::Clear()
{
stl_wipe_second(m_PropertyByCRCMap);
}
@@ -0,0 +1,353 @@
#include "StdAfx.h"
#include "SnowEnvironment.h"
#include "../EterLib/StateManager.h"
#include "../EterLib/Camera.h"
#include "../EterLib/ResourceManager.h"
#include "SnowParticle.h"
void CSnowEnvironment::Enable()
{
if (!m_bSnowEnable)
{
Create();
}
m_bSnowEnable = TRUE;
}
void CSnowEnvironment::Disable()
{
m_bSnowEnable = FALSE;
}
void CSnowEnvironment::Update(const D3DXVECTOR3 & c_rv3Pos)
{
if (!m_bSnowEnable)
{
if (m_kVct_pkParticleSnow.empty())
return;
}
m_v3Center=c_rv3Pos;
}
void CSnowEnvironment::Deform()
{
if (!m_bSnowEnable)
{
if (m_kVct_pkParticleSnow.empty())
return;
}
const D3DXVECTOR3 & c_rv3Pos=m_v3Center;
static long s_lLastTime = CTimer::Instance().GetCurrentMillisecond();
long lcurTime = CTimer::Instance().GetCurrentMillisecond();
float fElapsedTime = float(lcurTime - s_lLastTime) / 1000.0f;
s_lLastTime = lcurTime;
CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera();
if (!pCamera)
return;
const D3DXVECTOR3 & c_rv3View = pCamera->GetView();
D3DXVECTOR3 v3ChangedPos = c_rv3View * 3500.0f + c_rv3Pos;
v3ChangedPos.z = c_rv3Pos.z;
std::vector<CSnowParticle*>::iterator itor = m_kVct_pkParticleSnow.begin();
for (; itor != m_kVct_pkParticleSnow.end();)
{
CSnowParticle * pSnow = *itor;
pSnow->Update(fElapsedTime, v3ChangedPos);
if (!pSnow->IsActivate())
{
CSnowParticle::Delete(pSnow);
itor = m_kVct_pkParticleSnow.erase(itor);
}
else
{
++itor;
}
}
if (m_bSnowEnable)
{
for (int p = 0; p < min(10, m_dwParticleMaxNum - m_kVct_pkParticleSnow.size()); ++p)
{
CSnowParticle * pSnowParticle = CSnowParticle::New();
pSnowParticle->Init(v3ChangedPos);
m_kVct_pkParticleSnow.push_back(pSnowParticle);
}
}
}
void CSnowEnvironment::__BeginBlur()
{
if (!m_bBlurEnable)
return;
ms_lpd3dDevice->GetRenderTarget(&m_lpOldSurface);
ms_lpd3dDevice->GetDepthStencilSurface(&m_lpOldDepthStencilSurface);
ms_lpd3dDevice->SetRenderTarget(m_lpSnowRenderTargetSurface, m_lpSnowDepthSurface);
ms_lpd3dDevice->Clear(0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L);
STATEMANAGER.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);
}
void CSnowEnvironment::__ApplyBlur()
{
if (!m_bBlurEnable)
return;
// {
// STATEMANAGER.SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
// STATEMANAGER.SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
// STATEMANAGER.SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
// STATEMANAGER.SetRenderState( D3DRS_COLORVERTEX ,TRUE);
// STATEMANAGER.SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE , D3DMCS_COLOR1 );
// STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
// STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
// STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
// STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
// STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
// STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
// DWORD alphaColor = 0xFFFFFF | ((DWORD)(0.6f*255.0f) << 24);
//
// BlurVertex V[4] = { BlurVertex(D3DXVECTOR3(0.0f,0.0f,0.0f),1.0f, alphaColor, 0,0) ,
// BlurVertex(D3DXVECTOR3(wTextureSize,0.0f,0.0f),1.0f, alphaColor, 1,0) ,
// BlurVertex(D3DXVECTOR3(0.0f,wTextureSize,0.0f),1.0f, alphaColor, 0,1) ,
// BlurVertex(D3DXVECTOR3(wTextureSize,wTextureSize,0.0f),1.0f, alphaColor, 1,1) };
// //누적 블러 텍스쳐를 찍는다.
// STATEMANAGER.SetTexture(0,m_lpAccumTexture);
// STATEMANAGER.SetVertexShader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE|D3DFVF_TEX1 );
// STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,V,sizeof(BlurVertex));
// }
//
// {
// STATEMANAGER.SetRenderTarget(m_lpAccumRenderTargetSurface, m_lpAccumDepthSurface);
//
// BlurVertex V[4] = { BlurVertex(D3DXVECTOR3(0.0f,0.0f,0.0f),1.0f, 0xFFFFFF, 0,0) ,
// BlurVertex(D3DXVECTOR3(wTextureSize,0.0f,0.0f),1.0f, 0xFFFFFF, 1,0) ,
// BlurVertex(D3DXVECTOR3(0.0f,wTextureSize,0.0f),1.0f, 0xFFFFFF, 0,1) ,
// BlurVertex(D3DXVECTOR3(wTextureSize,wTextureSize,0.0f),1.0f, 0xFFFFFF, 1,1) };
//
// STATEMANAGER.SetTexture(0,m_lpSnowTexture);
// STATEMANAGER.SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);
// STATEMANAGER.SetVertexShader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE|D3DFVF_TEX1 );
// STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,V,sizeof(BlurVertex));
// }
///////////////
{
ms_lpd3dDevice->SetRenderTarget(m_lpOldSurface, m_lpOldDepthStencilSurface);
STATEMANAGER.SetTexture(0,m_lpSnowTexture);
STATEMANAGER.SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
D3DSURFACE_DESC desc;
m_lpOldSurface->GetDesc(&desc);
float sx = (float)desc.Width ;
float sy = (float)desc.Height;
SAFE_RELEASE( m_lpOldSurface );
SAFE_RELEASE( m_lpOldDepthStencilSurface );
BlurVertex V[4] = { BlurVertex(D3DXVECTOR3(0.0f,0.0f,0.0f),1.0f ,0xFFFFFF, 0,0) ,
BlurVertex(D3DXVECTOR3(sx,0.0f,0.0f),1.0f ,0xFFFFFF, 1,0) ,
BlurVertex(D3DXVECTOR3(0.0f,sy,0.0f),1.0f ,0xFFFFFF, 0,1) ,
BlurVertex(D3DXVECTOR3(sx,sy,0.0f),1.0f ,0xFFFFFF, 1,1) };
STATEMANAGER.SetVertexShader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE|D3DFVF_TEX1 );
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,V,sizeof(BlurVertex));
}
}
void CSnowEnvironment::Render()
{
if (!m_bSnowEnable)
{
if (m_kVct_pkParticleSnow.empty())
return;
}
__BeginBlur();
DWORD dwParticleCount = min(m_dwParticleMaxNum, m_kVct_pkParticleSnow.size());
CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera();
if (!pCamera)
return;
const D3DXVECTOR3 & c_rv3Up = pCamera->GetUp();
const D3DXVECTOR3 & c_rv3Cross = pCamera->GetCross();
SParticleVertex * pv3Verticies;
if (SUCCEEDED(m_pVB->Lock(0, sizeof(SParticleVertex)*dwParticleCount*4, (BYTE **) &pv3Verticies, D3DLOCK_DISCARD)))
{
int i = 0;
std::vector<CSnowParticle*>::iterator itor = m_kVct_pkParticleSnow.begin();
for (; i < dwParticleCount && itor != m_kVct_pkParticleSnow.end(); ++i, ++itor)
{
CSnowParticle * pSnow = *itor;
pSnow->SetCameraVertex(c_rv3Up, c_rv3Cross);
pSnow->GetVerticies(pv3Verticies[i*4+0],
pv3Verticies[i*4+1],
pv3Verticies[i*4+2],
pv3Verticies[i*4+3]);
}
m_pVB->Unlock();
}
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTexture(1, NULL);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
m_pImageInstance->GetGraphicImagePointer()->GetTextureReference().SetTextureStage(0);
STATEMANAGER.SetIndices(m_pIB, 0);
STATEMANAGER.SetStreamSource(0, m_pVB, sizeof(SParticleVertex));
STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_TEX1);
STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, dwParticleCount*4, 0, dwParticleCount*2);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
__ApplyBlur();
}
bool CSnowEnvironment::__CreateBlurTexture()
{
if (!m_bBlurEnable)
return true;
if (FAILED(ms_lpd3dDevice->CreateTexture(m_wBlurTextureSize, m_wBlurTextureSize, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_lpSnowTexture)))
return false;
if (FAILED(m_lpSnowTexture->GetSurfaceLevel(0, &m_lpSnowRenderTargetSurface)))
return false;
if (FAILED(ms_lpd3dDevice->CreateDepthStencilSurface(m_wBlurTextureSize, m_wBlurTextureSize, D3DFMT_D16, D3DMULTISAMPLE_NONE, &m_lpSnowDepthSurface)))
return false;
if (FAILED(ms_lpd3dDevice->CreateTexture(m_wBlurTextureSize, m_wBlurTextureSize, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_lpAccumTexture)))
return false;
if (FAILED(m_lpAccumTexture->GetSurfaceLevel(0, &m_lpAccumRenderTargetSurface)))
return false;
if (FAILED(ms_lpd3dDevice->CreateDepthStencilSurface(m_wBlurTextureSize, m_wBlurTextureSize, D3DFMT_D16, D3DMULTISAMPLE_NONE, &m_lpAccumDepthSurface)))
return false;
return true;
}
bool CSnowEnvironment::__CreateGeometry()
{
if (FAILED(ms_lpd3dDevice->CreateVertexBuffer(sizeof(SParticleVertex)*m_dwParticleMaxNum*4,
D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
D3DFVF_XYZ | D3DFVF_TEX1,
D3DPOOL_SYSTEMMEM,
&m_pVB)))
return false;
if (FAILED(ms_lpd3dDevice->CreateIndexBuffer(sizeof(WORD)*m_dwParticleMaxNum*6,
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&m_pIB)))
return false;
WORD* dstIndices;
if (FAILED(m_pIB->Lock(0, sizeof(WORD)*m_dwParticleMaxNum*6, (BYTE**)&dstIndices, 0)))
return false;
const WORD c_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, };
for (int i = 0; i < m_dwParticleMaxNum; ++i)
{
for (int j = 0; j < 6; ++j)
{
dstIndices[i*6 + j] = i*4 + c_awFillRectIndices[j];
}
}
m_pIB->Unlock();
return true;
}
bool CSnowEnvironment::Create()
{
Destroy();
if (!__CreateBlurTexture())
return false;
if (!__CreateGeometry())
return false;
CGraphicImage * pImage = (CGraphicImage *)CResourceManager::Instance().GetResourcePointer("d:/ymir work/special/snow.dds");
m_pImageInstance = CGraphicImageInstance::New();
m_pImageInstance->SetImagePointer(pImage);
return true;
}
void CSnowEnvironment::Destroy()
{
SAFE_RELEASE(m_lpSnowTexture);
SAFE_RELEASE(m_lpSnowRenderTargetSurface);
SAFE_RELEASE(m_lpSnowDepthSurface);
SAFE_RELEASE(m_lpAccumTexture);
SAFE_RELEASE(m_lpAccumRenderTargetSurface);
SAFE_RELEASE(m_lpAccumDepthSurface);
SAFE_RELEASE(m_pVB);
SAFE_RELEASE(m_pIB);
stl_wipe(m_kVct_pkParticleSnow);
CSnowParticle::DestroyPool();
if (m_pImageInstance)
{
CGraphicImageInstance::Delete(m_pImageInstance);
m_pImageInstance = NULL;
}
__Initialize();
}
void CSnowEnvironment::__Initialize()
{
m_bSnowEnable = FALSE;
m_lpSnowTexture = NULL;
m_lpSnowRenderTargetSurface = NULL;
m_lpSnowDepthSurface = NULL;
m_lpAccumTexture = NULL;
m_lpAccumRenderTargetSurface = NULL;
m_lpAccumDepthSurface = NULL;
m_pVB = NULL;
m_pIB = NULL;
m_pImageInstance = NULL;
m_kVct_pkParticleSnow.reserve(m_dwParticleMaxNum);
}
CSnowEnvironment::CSnowEnvironment()
{
m_bBlurEnable = FALSE;
m_dwParticleMaxNum = 3000;
m_wBlurTextureSize = 512;
__Initialize();
}
CSnowEnvironment::~CSnowEnvironment()
{
Destroy();
}
+103
View File
@@ -0,0 +1,103 @@
#include "StdAfx.h"
#include "SnowParticle.h"
const float c_fSnowDistance = 70000.0f;
std::vector<CSnowParticle*> CSnowParticle::ms_kVct_SnowParticlePool;
void CSnowParticle::SetCameraVertex(const D3DXVECTOR3 & rv3Up, const D3DXVECTOR3 & rv3Cross)
{
m_v3Up = rv3Up*m_fHalfWidth;
m_v3Cross = rv3Cross*m_fHalfHeight;
}
bool CSnowParticle::IsActivate()
{
return m_bActivate;
}
void CSnowParticle::Update(float fElapsedTime, const D3DXVECTOR3 & c_rv3Pos)
{
m_v3Position += m_v3Velocity * fElapsedTime;
m_v3Position.x += m_v3Cross.x * sin(m_fcurRadian) / 10.0f;
m_v3Position.y += m_v3Cross.y * sin(m_fcurRadian) / 10.0f;
m_fcurRadian += m_fPeriod * fElapsedTime;
if (m_v3Position.z < c_rv3Pos.z - 500.0f)
m_bActivate = false;
else if (abs(m_v3Position.x - c_rv3Pos.x) > c_fSnowDistance)
m_bActivate = false;
else if (abs(m_v3Position.y - c_rv3Pos.y) > c_fSnowDistance)
m_bActivate = false;
}
void CSnowParticle::GetVerticies(SParticleVertex & rv3Vertex1, SParticleVertex & rv3Vertex2,
SParticleVertex & rv3Vertex3, SParticleVertex & rv3Vertex4)
{
rv3Vertex1.v3Pos = m_v3Position - m_v3Cross - m_v3Up;
rv3Vertex1.u = 0.0f;
rv3Vertex1.v = 0.0f;
rv3Vertex2.v3Pos = m_v3Position + m_v3Cross - m_v3Up;
rv3Vertex2.u = 1.0f;
rv3Vertex2.v = 0.0f;
rv3Vertex3.v3Pos = m_v3Position - m_v3Cross + m_v3Up;
rv3Vertex3.u = 0.0f;
rv3Vertex3.v = 1.0f;
rv3Vertex4.v3Pos = m_v3Position + m_v3Cross + m_v3Up;
rv3Vertex4.u = 1.0f;
rv3Vertex4.v = 1.0f;
}
void CSnowParticle::Init(const D3DXVECTOR3 & c_rv3Pos)
{
float fRot = frandom(0.0f, 36000.0f) / 100.0f;
float fDistance = frandom(0.0f, c_fSnowDistance) / 10.0f;
m_v3Position.x = c_rv3Pos.x + fDistance*sin((double)D3DXToRadian(fRot));
m_v3Position.y = c_rv3Pos.y + fDistance*cos((double)D3DXToRadian(fRot));
m_v3Position.z = c_rv3Pos.z + frandom(1500.0f, 2000.0f);
m_v3Velocity.x = 0.0f;
m_v3Velocity.y = 0.0f;
m_v3Velocity.z = frandom(-50.0f, -200.0f);
m_fHalfWidth = frandom(2.0f, 7.0f);
m_fHalfHeight = m_fHalfWidth;
m_bActivate = true;
m_bChangedSize = false;
m_fPeriod = frandom(1.5f, 5.0f);
m_fcurRadian = frandom(-1.6f, 1.6f);
m_fAmplitude = frandom(1.0f, 3.0f);
}
CSnowParticle * CSnowParticle::New()
{
if (ms_kVct_SnowParticlePool.empty())
{
return new CSnowParticle;
}
CSnowParticle * pParticle = ms_kVct_SnowParticlePool.back();
ms_kVct_SnowParticlePool.pop_back();
return pParticle;
}
void CSnowParticle::Delete(CSnowParticle * pSnowParticle)
{
ms_kVct_SnowParticlePool.push_back(pSnowParticle);
}
void CSnowParticle::DestroyPool()
{
stl_wipe(ms_kVct_SnowParticlePool);
}
CSnowParticle::CSnowParticle()
{
}
CSnowParticle::~CSnowParticle()
{
}
+59
View File
@@ -0,0 +1,59 @@
#pragma once
struct SParticleVertex
{
D3DXVECTOR3 v3Pos;
float u, v;
};
struct BlurVertex
{
D3DXVECTOR3 pos;
FLOAT rhw;
DWORD color;
FLOAT tu, tv;
static const DWORD FVF;
BlurVertex(D3DXVECTOR3 p, float w,DWORD c,float u,float v):pos(p),rhw(w),color(c),tu(u),tv(v) {}
~BlurVertex(){};
};
class CSnowParticle
{
public:
CSnowParticle();
~CSnowParticle();
static CSnowParticle * New();
static void Delete(CSnowParticle * pSnowParticle);
static void DestroyPool();
void Init(const D3DXVECTOR3 & c_rv3Pos);
void SetCameraVertex(const D3DXVECTOR3 & rv3Up, const D3DXVECTOR3 & rv3Cross);
bool IsActivate();
void Update(float fElapsedTime, const D3DXVECTOR3 & c_rv3Pos);
void GetVerticies(SParticleVertex & rv3Vertex1, SParticleVertex & rv3Vertex2,
SParticleVertex & rv3Vertex3, SParticleVertex & rv3Vertex4);
protected:
bool m_bActivate;
bool m_bChangedSize;
float m_fHalfWidth;
float m_fHalfHeight;
D3DXVECTOR3 m_v3Velocity;
D3DXVECTOR3 m_v3Position;
D3DXVECTOR3 m_v3Up;
D3DXVECTOR3 m_v3Cross;
float m_fPeriod;
float m_fcurRadian;
float m_fAmplitude;
public:
static std::vector<CSnowParticle*> ms_kVct_SnowParticlePool;
};
+180
View File
@@ -0,0 +1,180 @@
// TerrainDecal.cpp: implementation of the CTerrainDecal class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "../EterLib/StateManager.h"
#include "../PRTerrainLib/StdAfx.h"
#include "TerrainDecal.h"
#include "MapOutdoor.h"
#include "AreaTerrain.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CTerrainDecal::CTerrainDecal(CMapOutdoor * pMapOutdoor):m_pMapOutdoor(pMapOutdoor)
{
}
CTerrainDecal::~CTerrainDecal()
{
CDecal::Clear();
}
void CTerrainDecal::Make(D3DXVECTOR3 v3Center, D3DXVECTOR3 v3Normal, D3DXVECTOR3 v3Tangent, float fWidth, float fHeight, float fDepth)
{
Clear();
m_v3Center = v3Center;
m_v3Normal = v3Normal;
D3DXVECTOR3 v3Binormal;
D3DXVec3Normalize(&v3Normal, &v3Normal);
D3DXVec3Normalize(&v3Tangent, &v3Tangent);
D3DXVec3Cross(&v3Binormal, &m_v3Normal, &v3Tangent);
D3DXVec3Normalize(&v3Binormal, &v3Binormal);
// Calculate boundary planes
float fd = D3DXVec3Dot(&m_v3Center, &v3Tangent);
m_v4LeftPlane = D3DXPLANE(v3Tangent.x, v3Tangent.y, v3Tangent.z, fWidth * 0.5f - fd);
m_v4RightPlane = D3DXPLANE(-v3Tangent.x, -v3Tangent.y, -v3Tangent.z, fWidth * 0.5f + fd);
fd = D3DXVec3Dot(&m_v3Center, &v3Binormal);
m_v4BottomPlane = D3DXPLANE(v3Binormal.x, v3Binormal.y, v3Binormal.z, fHeight * 0.5f - fd);
m_v4TopPlane = D3DXPLANE(-v3Binormal.x, -v3Binormal.y, -v3Binormal.z, fHeight * 0.5f + fd);
fd = D3DXVec3Dot(&m_v3Center, &m_v3Normal);
m_v4FrontPlane = D3DXPLANE(-m_v3Normal.x, -m_v3Normal.y, -m_v3Normal.z, fDepth + fd);
m_v4BackPlane = D3DXPLANE(m_v3Normal.x, m_v3Normal.y, m_v3Normal.z, fDepth - fd);
// Begin with empty mesh
m_dwVertexCount = 0;
m_dwPrimitiveCount = 0;
// Add this point, determine which surfaces may be affected by this decal and call ClipMesh().
float fSearchRadius = fMAX(fWidth, fHeight);// 0.75f >= sqrtf(2)/2;
float fMinX = v3Center.x - fSearchRadius;
float fMaxX = v3Center.x + fSearchRadius;
float fMinY = fabs(v3Center.y) - fSearchRadius;
float fMaxY = fabs(v3Center.y) + fSearchRadius;
DWORD dwAffectedPrimitiveCount = 0;
D3DXVECTOR3 v3AffectedVertex[MAX_SEARCH_VERTICES];
D3DXVECTOR3 v3AffectedNormal[MAX_SEARCH_VERTICES];
memset(v3AffectedVertex, 0, sizeof(v3AffectedVertex));
memset(v3AffectedNormal, 0, sizeof(v3AffectedNormal));
SearchAffectedTerrainMesh(fMinX, fMaxX, fMinY, fMaxY, &dwAffectedPrimitiveCount, v3AffectedVertex, v3AffectedNormal);
ClipMesh(dwAffectedPrimitiveCount, v3AffectedVertex, v3AffectedNormal);
// Assign texture mapping coordinates
float fOne_over_w = 1.0f / fWidth;
float fOne_over_h = 1.0f / fHeight;
for (DWORD dwi = 0; dwi < m_dwVertexCount; ++dwi)
{
D3DXVECTOR3 v3 = m_Vertices[dwi].position - m_v3Center;
float fu = -D3DXVec3Dot(&v3, &v3Binormal) * fOne_over_w + 0.5f;
float fv = -D3DXVec3Dot(&v3, &v3Tangent) * fOne_over_h + 0.5f;
m_Vertices[dwi].texCoord = D3DXVECTOR2(fu, fv);
}
}
/*
void CTerrainDecal::Update()
{
}
*/
void CTerrainDecal::Render()
{
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
CDecal::Render();
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXCOORDINDEX);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSU);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSV);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
}
void CTerrainDecal::SearchAffectedTerrainMesh(float fMinX,
float fMaxX,
float fMinY,
float fMaxY,
DWORD * pdwAffectedPrimitiveCount,
D3DXVECTOR3 * pv3AffectedVertex,
D3DXVECTOR3 * pv3AffectedNormal)
{
if (!m_pMapOutdoor)
return;
int iMinX, iMaxX, iMinY, iMaxY;
PR_FLOAT_TO_INT(fMinX, iMinX);
PR_FLOAT_TO_INT(fMaxX, iMaxX);
PR_FLOAT_TO_INT(fMinY, iMinY);
PR_FLOAT_TO_INT(fMaxY, iMaxY);
iMinX -= iMinX % CTerrainImpl::CELLSCALE;
iMaxX -= iMaxX % CTerrainImpl::CELLSCALE;
iMinY -= iMinY % CTerrainImpl::CELLSCALE;
iMaxY -= iMaxY % CTerrainImpl::CELLSCALE;
for(int iy = iMinY; iy <= iMaxY; iy += CTerrainImpl::CELLSCALE)
{
if (iy < 0)
continue;
WORD wTerrainNumY = iy / CTerrainImpl::TERRAIN_YSIZE;
for(int ix = iMinX; ix <= iMaxX; ix += CTerrainImpl::CELLSCALE)
{
if (ix < 0)
continue;
WORD wTerrainNumX = ix / CTerrainImpl::TERRAIN_YSIZE;
BYTE byTerrainNum;
if (!m_pMapOutdoor->GetTerrainNumFromCoord(wTerrainNumX, wTerrainNumY, &byTerrainNum))
continue;
CTerrain * pTerrain;
if (!m_pMapOutdoor->GetTerrainPointer(byTerrainNum, &pTerrain))
continue;
float fHeightLT = pTerrain->GetHeight(ix, iy) + m_cfDecalEpsilon;
float fHeightRT = pTerrain->GetHeight(ix + CTerrainImpl::CELLSCALE, iy) + m_cfDecalEpsilon;
float fHeightLB = pTerrain->GetHeight(ix, iy + CTerrainImpl::CELLSCALE) + m_cfDecalEpsilon;
float fHeightRB = pTerrain->GetHeight(ix + CTerrainImpl::CELLSCALE, iy + CTerrainImpl::CELLSCALE) + m_cfDecalEpsilon;
*pdwAffectedPrimitiveCount += 2;
*pv3AffectedVertex++ = D3DXVECTOR3((float)ix, (float)(-iy), fHeightLT);
*pv3AffectedVertex++ = D3DXVECTOR3((float)ix, (float)(-iy - CTerrainImpl::CELLSCALE), fHeightLB);
*pv3AffectedVertex++ = D3DXVECTOR3((float)(ix + CTerrainImpl::CELLSCALE), (float)(-iy), fHeightRT);
*pv3AffectedVertex++ = D3DXVECTOR3((float)(ix + CTerrainImpl::CELLSCALE), (float)(-iy), fHeightRT);
*pv3AffectedVertex++ = D3DXVECTOR3((float)ix, (float)(-iy - CTerrainImpl::CELLSCALE), fHeightLB);
*pv3AffectedVertex++ = D3DXVECTOR3((float)(ix + CTerrainImpl::CELLSCALE), (float)(-iy - CTerrainImpl::CELLSCALE), fHeightRB);
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
*pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
}
}
}
+240
View File
@@ -0,0 +1,240 @@
// TerrainPatch.cpp: implementation of the CTerrainPatch class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "TerrainPatch.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CTerrainPatch::SSoftwareTransformPatch::SSoftwareTransformPatch()
{
__Initialize();
}
CTerrainPatch::SSoftwareTransformPatch::~SSoftwareTransformPatch()
{
Destroy();
}
void CTerrainPatch::SSoftwareTransformPatch::Create()
{
assert(NULL==m_akTerrainVertex);
m_akTerrainVertex=new SoftwareTransformPatch_SSourceVertex[TERRAIN_VERTEX_COUNT];
}
void CTerrainPatch::SSoftwareTransformPatch::Destroy()
{
if (m_akTerrainVertex)
delete [] m_akTerrainVertex;
__Initialize();
}
void CTerrainPatch::SSoftwareTransformPatch::__Initialize()
{
m_akTerrainVertex=NULL;
}
bool CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE=TRUE;
void CTerrainPatch::Clear()
{
m_kHT.m_kVB.Destroy();
m_kST.Destroy();
m_WaterVertexBuffer.Destroy();
ClearID();
SetUse(false);
m_bWaterExist = false;
m_bNeedUpdate = true;
m_dwWaterPriCount = 0;
m_byType = PATCH_TYPE_PLAIN;
m_fMinX = m_fMaxX = m_fMinY = m_fMaxY = m_fMinZ = m_fMaxZ = 0.0f;
m_dwVersion=0;
}
void CTerrainPatch::BuildWaterVertexBuffer(SWaterVertex* akSrcVertex, UINT uWaterVertexCount)
{
CGraphicVertexBuffer& rkVB=m_WaterVertexBuffer;
if (!rkVB.Create(uWaterVertexCount, D3DFVF_XYZ | D3DFVF_DIFFUSE, D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED))
return;
SWaterVertex* akDstWaterVertex;
if (rkVB.Lock((void **) &akDstWaterVertex))
{
UINT uVBSize=sizeof(SWaterVertex)*uWaterVertexCount;
memcpy(akDstWaterVertex, akSrcVertex, uVBSize);
m_dwWaterPriCount=uWaterVertexCount/3;
rkVB.Unlock();
}
}
void CTerrainPatch::BuildTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex* akSrcVertex)
{
if (SOFTWARE_TRANSFORM_PATCH_ENABLE)
__BuildSoftwareTerrainVertexBuffer(akSrcVertex);
else
__BuildHardwareTerrainVertexBuffer(akSrcVertex);
}
void CTerrainPatch::__BuildSoftwareTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex* akSrcVertex)
{
//DWORD dwVBSize=sizeof(HardwareTransformPatch_SSourceVertex)*TERRAIN_VERTEX_COUNT;
m_kST.Create();
SoftwareTransformPatch_SSourceVertex* akDstVertex=SoftwareTransformPatch_GetTerrainVertexDataPtr();
for (UINT uIndex=0; uIndex!=TERRAIN_VERTEX_COUNT; ++uIndex)
{
*((HardwareTransformPatch_SSourceVertex*)(akDstVertex+uIndex))=*(akSrcVertex+uIndex);
akDstVertex[uIndex].dwDiffuse=0xFFFFFFFF;
}
}
void CTerrainPatch::__BuildHardwareTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex* akSrcVertex)
{
CGraphicVertexBuffer& rkVB=m_kHT.m_kVB;
if (!rkVB.Create(TERRAIN_VERTEX_COUNT, D3DFVF_XYZ | D3DFVF_NORMAL, D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED))
return;
HardwareTransformPatch_SSourceVertex* akDstVertex;
if (rkVB.Lock((void **) &akDstVertex))
{
UINT uVBSize=sizeof(HardwareTransformPatch_SSourceVertex)*TERRAIN_VERTEX_COUNT;
memcpy(akDstVertex, akSrcVertex, uVBSize);
rkVB.Unlock();
}
}
void CTerrainPatch::SoftwareTransformPatch_UpdateTerrainLighting(DWORD dwVersion, const D3DLIGHT8& c_rkLight, const D3DMATERIAL8& c_rkMtrl)
{
if (m_dwVersion==dwVersion)
return;
m_dwVersion=dwVersion;
SoftwareTransformPatch_SSourceVertex* akSrcVertex=SoftwareTransformPatch_GetTerrainVertexDataPtr();
if (!akSrcVertex)
return;
D3DXVECTOR3 kLightDir=c_rkLight.Direction;
DWORD dwDot;
DWORD dwAmbientR=(c_rkMtrl.Ambient.r*c_rkLight.Ambient.r+c_rkMtrl.Emissive.r)*255.0f;
DWORD dwAmbientG=(c_rkMtrl.Ambient.g*c_rkLight.Ambient.g+c_rkMtrl.Emissive.g)*255.0f;
DWORD dwAmbientB=(c_rkMtrl.Ambient.b*c_rkLight.Ambient.b+c_rkMtrl.Emissive.b)*255.0f;
DWORD dwDiffuseR=(c_rkMtrl.Diffuse.r*c_rkLight.Diffuse.r)*255.0f;
DWORD dwDiffuseG=(c_rkMtrl.Diffuse.g*c_rkLight.Diffuse.g)*255.0f;
DWORD dwDiffuseB=(c_rkMtrl.Diffuse.b*c_rkLight.Diffuse.b)*255.0f;
if (dwDiffuseR>255-dwAmbientR)
dwDiffuseR=255-dwAmbientR;
if (dwDiffuseG+dwAmbientG>255)
dwDiffuseG=255-dwAmbientG;
if (dwDiffuseB+dwAmbientB>255)
dwDiffuseB=255-dwAmbientB;
for (UINT uIndex=0; uIndex!=CTerrainPatch::TERRAIN_VERTEX_COUNT; ++uIndex)
{
float fDot=D3DXVec3Dot(&akSrcVertex[uIndex].kNormal, &kLightDir);
const float N=0xffffff;
const int S=24;
if (fDot<0.0f)
dwDot=(N*-fDot);
else
dwDot=(N*+fDot);
akSrcVertex[uIndex].dwDiffuse=(0xff000000)|
(((dwDiffuseR*dwDot>>S)+dwAmbientR)<<16)|
(((dwDiffuseG*dwDot>>S)+dwAmbientG)<<8)|
((dwDiffuseB*dwDot>>S)+dwAmbientB);
}
}
UINT CTerrainPatch::GetWaterFaceCount()
{
return m_dwWaterPriCount;
}
CTerrainPatchProxy::CTerrainPatchProxy()
{
Clear();
}
CTerrainPatchProxy::~CTerrainPatchProxy()
{
Clear();
}
void CTerrainPatchProxy::SetCenterPosition(const D3DXVECTOR3& c_rv3Center)
{
m_v3Center=c_rv3Center;
}
bool CTerrainPatchProxy::IsIn(const D3DXVECTOR3& c_rv3Target, float fRadius)
{
float dx=m_v3Center.x-c_rv3Target.x;
float dy=m_v3Center.y-c_rv3Target.y;
float fDist=dx*dx+dy*dy;
float fCheck=fRadius*fRadius;
if (fDist<fCheck)
return true;
return false;
}
void CTerrainPatchProxy::SoftwareTransformPatch_UpdateTerrainLighting(DWORD dwVersion, const D3DLIGHT8& c_rkLight, const D3DMATERIAL8& c_rkMtrl)
{
if (m_pTerrainPatch)
m_pTerrainPatch->SoftwareTransformPatch_UpdateTerrainLighting(dwVersion, c_rkLight, c_rkMtrl);
}
CGraphicVertexBuffer* CTerrainPatchProxy::HardwareTransformPatch_GetVertexBufferPtr()
{
if (m_pTerrainPatch)
return m_pTerrainPatch->HardwareTransformPatch_GetVertexBufferPtr();
return NULL;
}
SoftwareTransformPatch_SSourceVertex* CTerrainPatchProxy::SoftwareTransformPatch_GetTerrainVertexDataPtr()
{
if (m_pTerrainPatch)
return m_pTerrainPatch->SoftwareTransformPatch_GetTerrainVertexDataPtr();
return NULL;
}
UINT CTerrainPatchProxy::GetWaterFaceCount()
{
if (m_pTerrainPatch)
return m_pTerrainPatch->GetWaterFaceCount();
return 0;
}
void CTerrainPatchProxy::Clear()
{
m_bUsed = false;
m_sPatchNum = 0;
m_byTerrainNum = 0xFF;
m_pTerrainPatch = NULL;
}
@@ -0,0 +1,46 @@
// TerrainQuadtreeNode.cpp: implementation of the CTerrainQuadtreeNode class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "TerrainQuadtree.h"
//////////////////////////////////////////////////////////////////////
// CTerrainQuadtree
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// CTerrainQuadtreeNode
//////////////////////////////////////////////////////////////////////
CTerrainQuadtreeNode::CTerrainQuadtreeNode():NW_Node(NULL), NE_Node(NULL), SW_Node(NULL), SE_Node(NULL), center(-1.0f, -1.0f, -1.0f)
{
x0 = y0 = x1 = y1 = 0;
Size = 0;
PatchNum = 0;
radius = 0.0f;
m_byLODLevel = 0;
}
CTerrainQuadtreeNode::~CTerrainQuadtreeNode()
{
if (NW_Node)
{
delete NW_Node;
NW_Node = NULL;
}
if (NE_Node)
{
delete NE_Node;
NE_Node = NULL;
}
if (SW_Node)
{
delete SW_Node;
SW_Node = NULL;
}
if (SE_Node)
{
delete SE_Node;
SE_Node = NULL;
}
}
@@ -0,0 +1,32 @@
// TerrainQuadtreeNode.h: interface for the CTerrainQuadtreeNode class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_TERRAINQUADTREENODE_H__C788298F_1098_4CEE_B6F3_5975D618BBF3__INCLUDED_)
#define AFX_TERRAINQUADTREENODE_H__C788298F_1098_4CEE_B6F3_5975D618BBF3__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CTerrainQuadtreeNode
{
public:
CTerrainQuadtreeNode();
virtual ~CTerrainQuadtreeNode();
public:
long x0, y0, x1, y1;
CTerrainQuadtreeNode * NW_Node;
CTerrainQuadtreeNode * NE_Node;
CTerrainQuadtreeNode * SW_Node;
CTerrainQuadtreeNode * SE_Node;
long Size;
long PatchNum;
D3DXVECTOR3 center;
float radius;
BYTE m_byLODLevel;
};
#endif // !defined(AFX_TERRAINQUADTREENODE_H__C788298F_1098_4CEE_B6F3_5975D618BBF3__INCLUDED_)
+1 -2
View File
@@ -19,8 +19,7 @@
#include "../EterLib/StdAfx.h"
#include "../EterGrnLib/StdAfx.h"
// PORT: dropped #include "../ScriptLib/StdAfx.h": no PRTerrainLib file uses Python, and it would pull
// CPython headers into every terrain translation unit.
#include "../ScriptLib/StdAfx.h"
/* Fast Float<->Integer conversion */
extern float PR_FCNV;
+329
View File
@@ -0,0 +1,329 @@
#include "StdAfx.h"
#include "../EterPack/EterPackManager.h"
#include "Terrain.h"
#include <math.h>
//////////////////////////////////////////////////////////////////////////
// Texture Set
//////////////////////////////////////////////////////////////////////////
CTextureSet * CTerrainImpl::ms_pTextureSet = NULL;
void CTerrainImpl::SetTextureSet(CTextureSet * pTextureSet)
{
static CTextureSet s_EmptyTextureSet;
if (!pTextureSet)
ms_pTextureSet = &s_EmptyTextureSet;
else
ms_pTextureSet = pTextureSet;
}
CTextureSet * CTerrainImpl::GetTextureSet()
{
if (!ms_pTextureSet)
SetTextureSet(NULL);
return ms_pTextureSet;
}
CTerrainImpl::CTerrainImpl()
{
Initialize();
}
CTerrainImpl::~CTerrainImpl()
{
Clear();
}
void CTerrainImpl::Initialize()
{
memset(m_lWaterHeight, -1, sizeof(m_lWaterHeight));
m_byNumWater = 0;
memset(&m_HeightMapHeader, 0, sizeof(TGA_HEADER));
memset(&m_awShadowMap, 0xFFFF, sizeof(m_awShadowMap));
memset(&m_lpAlphaTexture, NULL, sizeof(m_lpAlphaTexture));
m_lViewRadius = 0;
m_wTileMapVersion = 8976;
m_fHeightScale = 0.0f;
m_lpShadowTexture = NULL;
m_lSplatTilesX = 0;
m_lSplatTilesY = 0;
}
void CTerrainImpl::Clear()
{
for (DWORD i = 0; i < GetTextureSet()->GetTextureCount(); ++i)
{
if (m_lpAlphaTexture[i])
{
m_lpAlphaTexture[i]->Release();
m_lpAlphaTexture[i] = NULL;
}
}
Initialize();
}
bool CTerrainImpl::LoadHeightMap(const char*c_szFileName)
{
Tracef("LoadRawHeightMapFile %s ", c_szFileName);
CMappedFile kMappedFile;
LPCVOID lpcvFileData;
if (!CEterPackManager::Instance().Get(kMappedFile, c_szFileName, &lpcvFileData))
{
Tracen("Error");
TraceError("CTerrainImpl::LoadHeightMap - %s OPEN ERROR", c_szFileName);
return false;
}
memcpy(m_awRawHeightMap, lpcvFileData, sizeof(WORD)*HEIGHTMAP_RAW_XSIZE*HEIGHTMAP_RAW_YSIZE);
return true;
}
bool CTerrainImpl::LoadAttrMap(const char *c_szFileName)
{
DWORD dwStart = ELTimer_GetMSec();
Tracef("LoadAttrMapFile %s ", c_szFileName);
CMappedFile kMappedFile;
LPCVOID lpcvFileData;
if (!CEterPackManager::Instance().Get(kMappedFile, c_szFileName, &lpcvFileData))
{
TraceError("CTerrainImpl::LoadAttrMap - %s OPEN ERROR", c_szFileName);
return false;
}
DWORD dwFileSize = kMappedFile.Size();
BYTE * abFileData = (BYTE *) lpcvFileData;
// LoadAttrMap
{
#pragma pack(push)
#pragma pack(1)
struct SAttrMapHeader
{
WORD m_wMagic;
WORD m_wWidth;
WORD m_wHeight;
};
#pragma pack(pop)
if (dwFileSize < sizeof(SAttrMapHeader))
{
TraceError(" CTerrainImpl::LoadAttrMap - %s FILE SIZE ERROR", c_szFileName);
return false;
}
SAttrMapHeader kAttrMapHeader;
memcpy(&kAttrMapHeader, abFileData, sizeof(kAttrMapHeader));
const WORD c_wAttrMapMagic = 2634;
if (c_wAttrMapMagic != kAttrMapHeader.m_wMagic)
{
TraceError("CTerrainImpl::LoadAttrMap - %s MAGIC NUMBER(%d!=MAGIC[%d]) ERROR", c_szFileName, kAttrMapHeader.m_wMagic, kAttrMapHeader.m_wMagic);
return false;
}
if (ATTRMAP_XSIZE != kAttrMapHeader.m_wWidth)
{
TraceError("CTerrainImpl::LoadAttrMap - kAttrMapHeader(%s).m_width(%d)!=ATTRMAP_XSIZE(%d)", c_szFileName, kAttrMapHeader.m_wWidth, ATTRMAP_XSIZE);
return false;
}
if (ATTRMAP_YSIZE != kAttrMapHeader.m_wHeight)
{
TraceError("CTerrainImpl::LoadAttrMap - kAttrMapHeader(%s).m_height(%d)!=ATTRMAP_YSIZE(%d)", c_szFileName, kAttrMapHeader.m_wHeight, ATTRMAP_YSIZE);
return false;
}
DWORD dwFileRestSize=dwFileSize-sizeof(kAttrMapHeader);
DWORD dwFileNeedSize=sizeof(m_abyAttrMap);
if (dwFileRestSize != dwFileNeedSize)
{
TraceError("CTerrainImpl::LoadAttrMap - %s FILE DATA SIZE(rest %d != need %d) ERROR", c_szFileName, dwFileRestSize, dwFileNeedSize);
return false;
}
BYTE* abSrcAttrData= abFileData+sizeof(kAttrMapHeader);
memcpy(m_abyAttrMap, abSrcAttrData, sizeof(m_abyAttrMap));
}
Tracef("%d\n", ELTimer_GetMSec() - dwStart);
return true;
}
bool CTerrainImpl::RAW_LoadTileMap(const char * c_szFileName)
{
Tracef("LoadSplatFile %s ", c_szFileName);
CMappedFile kMappedFile;
LPCVOID lpcvFileData;
if (!CEterPackManager::Instance().Get(kMappedFile, c_szFileName, &lpcvFileData))
{
Tracen("Error");
TraceError("CTerrainImpl::RAW_LoadTileMap - %s OPEN ERROR", c_szFileName);
return false;
}
memcpy(m_abyTileMap, lpcvFileData, sizeof(BYTE)*(TILEMAP_RAW_XSIZE)*(TILEMAP_RAW_YSIZE));
return true;
}
bool CTerrainImpl::LoadWaterMap(const char * c_szFileName)
{
DWORD dwStart = ELTimer_GetMSec();
if (!LoadWaterMapFile(c_szFileName))
{
memset(m_abyWaterMap, 0xFF, sizeof(m_abyWaterMap));
m_byNumWater = 0;
memset(m_lWaterHeight, -1, sizeof(m_lWaterHeight));
TraceError("CMapOutdoor::LoadWaterMap LoadWaterMapFile(%s) Failed", c_szFileName);
return false;
}
Tracef("LoadWaterMapFile %s %d\n", c_szFileName, ELTimer_GetMSec() - dwStart);
return true;
}
bool CTerrainImpl::LoadWaterMapFile(const char * c_szFileName)
{
CMappedFile kMappedFile;
LPCVOID lpcvFileData;
if (!CEterPackManager::Instance().Get(kMappedFile, c_szFileName, &lpcvFileData))
{
Tracen("Error");
TraceError("CTerrainImpl::LoadWaterMap - %s OPEN ERROR", c_szFileName);
return false;
}
DWORD dwFileSize = kMappedFile.Size();
BYTE* abFileData = (BYTE*)lpcvFileData;
{
#pragma pack(push)
#pragma pack(1)
struct SWaterMapHeader
{
WORD m_wMagic;
WORD m_wWidth;
WORD m_wHeight;
BYTE m_byLayerCount;
};
#pragma pack(pop)
if (dwFileSize < sizeof(SWaterMapHeader))
{
TraceError("CTerrainImpl::LoadWaterMap - %s FILE SIZE ERROR", c_szFileName);
return false;
}
SWaterMapHeader kWaterMapHeader;
memcpy(&kWaterMapHeader, abFileData, sizeof(kWaterMapHeader));
const WORD c_wWaterMapMagic = 5426;
if (c_wWaterMapMagic != kWaterMapHeader.m_wMagic)
{
TraceError("CTerrainImpl::LoadWaterMap - %s MAGIC NUMBER(%d!=MAGIC[%d]) ERROR", c_szFileName, kWaterMapHeader.m_wMagic, c_wWaterMapMagic);
return false;
}
if (WATERMAP_XSIZE != kWaterMapHeader.m_wWidth)
{
TraceError("CTerrainImpl::LoadWaterMap - kWaterMapHeader(%s).m_width(%d)!=WATERMAP_XSIZE(%d)", c_szFileName, kWaterMapHeader.m_wWidth, WATERMAP_XSIZE);
return false;
}
if (WATERMAP_YSIZE != kWaterMapHeader.m_wHeight)
{
TraceError("CTerrainImpl::LoadWaterMap - kWaterMapHeader(%s).m_height(%d)!=WATERMAP_YSIZE(%d)", c_szFileName, kWaterMapHeader.m_wHeight, WATERMAP_YSIZE);
return false;
}
m_byNumWater = kWaterMapHeader.m_byLayerCount;
DWORD dwFileRestSize = dwFileSize - sizeof(kWaterMapHeader);
DWORD dwFileNeedSize = sizeof(m_abyWaterMap) + sizeof(int32_t) * m_byNumWater; // PORT: the file's long is 32-bit
DWORD dwFileNeedSize2 = sizeof(m_abyWaterMap) + sizeof(WORD) * m_byNumWater;
if (dwFileRestSize == dwFileNeedSize2)
{
WORD wWaterHeight[MAX_WATER_NUM + 1];
BYTE * abSrcWaterData = abFileData + sizeof(kWaterMapHeader);
memcpy(m_abyWaterMap, abSrcWaterData, sizeof(m_abyWaterMap));
BYTE * abSrcWaterHeight = abSrcWaterData + sizeof(m_abyWaterMap);
m_byNumWater = MIN(MAX_WATER_NUM, m_byNumWater);
if (m_byNumWater)
{
memcpy(wWaterHeight, abSrcWaterHeight, sizeof(WORD) * m_byNumWater);
for (int i = 0; i < m_byNumWater; ++i)
m_lWaterHeight[i] = wWaterHeight[i];
}
}
else if (dwFileRestSize != dwFileNeedSize)
{
TraceError("CTerrainImpl::LoadWaterMap - %s FILE DATA SIZE(rest %d != need %d) ERROR", c_szFileName, dwFileRestSize, dwFileNeedSize);
return false;
}
BYTE * abSrcWaterData = abFileData + sizeof(kWaterMapHeader);
memcpy(m_abyWaterMap, abSrcWaterData, sizeof(m_abyWaterMap));
BYTE * abSrcWaterHeight = abSrcWaterData + sizeof(m_abyWaterMap);
if (m_byNumWater)
for (int i = 0; i < m_byNumWater; ++i) // PORT: widen the file's 32-bit longs (LP64 long is 64-bit)
{
int32_t lHeight;
memcpy(&lHeight, abSrcWaterHeight + sizeof(int32_t) * i, sizeof(int32_t));
m_lWaterHeight[i] = lHeight;
}
}
return true;
}
DWORD CTerrainImpl::GetShadowMapColor(float fx, float fy)
{
float fMapSize = (float)(TERRAIN_XSIZE);
float fooMapSize = 1.0f / fMapSize;
if (fx < 0 || fy < 0 || fx >= fMapSize || fy >= fMapSize)
return 0xFFFFFFFF;
fx = fx * fooMapSize * (float)(SHADOWMAP_XSIZE - 1);
fy = fy * fooMapSize * (float)(SHADOWMAP_YSIZE - 1);
int ix, iy;
PR_FLOAT_TO_INT(fx, ix);
PR_FLOAT_TO_INT(fy, iy);
WORD w = *(m_awShadowMap + (iy * SHADOWMAP_XSIZE) + ix);
int b = w & 0x1f; w >>= 5; b <<= 3;
int g = w & 0x1f; w >>= 5; g <<= 3;
int r = w & 0x1f; r <<= 3;
return (DWORD) (0xff << 24) | (g << 16) | (g << 8) | r;
}
@@ -0,0 +1,275 @@
#include "StdAfx.h"
#include "TextureSet.h"
CTextureSet::CTextureSet()
{
Initialize();
}
CTextureSet::~CTextureSet()
{
Clear();
}
void CTextureSet::Initialize()
{
}
void CTextureSet::Create()
{
CResource * pResource = CResourceManager::Instance().GetResourcePointer("d:/ymir work/special/error.tga");
m_ErrorTexture.ImageInstance.SetImagePointer(static_cast<CGraphicImage *> (pResource));
AddEmptyTexture(); // 지우개 텍스춰를 처음에 추가 해야 함
}
bool CTextureSet::Load(const char * c_szTextureSetFileName, float fTerrainTexCoordBase)
{
NANOBEGIN
Clear();
CTokenVectorMap stTokenVectorMap;
if (!LoadMultipleTextData(c_szTextureSetFileName, stTokenVectorMap))
{
TraceError("TextureSet::Load : cannot load %s", c_szTextureSetFileName);
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("textureset"))
{
TraceError("TextureSet::Load : syntax error, TextureSet (filename: %s)", c_szTextureSetFileName);
return false;
}
if (stTokenVectorMap.end() == stTokenVectorMap.find("texturecount"))
{
TraceError("TextureSet::Load : syntax error, TextureCount (filename: %s)", c_szTextureSetFileName);
return false;
}
Create();
const std::string & c_rstrCount = stTokenVectorMap["texturecount"][0];
long lCount = atol(c_rstrCount.c_str());
char szTextureName[32 + 1];
m_Textures.resize(lCount + 1);
for (long i = 0; i < lCount; ++i)
{
_snprintf(szTextureName, sizeof(szTextureName), "texture%03d", i + 1);
if (stTokenVectorMap.end() == stTokenVectorMap.find(szTextureName))
continue;
const CTokenVector & rVector = stTokenVectorMap[szTextureName];
const std::string & c_rstrFileName = rVector[0].c_str();
const std::string & c_rstrUScale = rVector[1].c_str();
const std::string & c_rstrVScale = rVector[2].c_str();
const std::string & c_rstrUOffset = rVector[3].c_str();
const std::string & c_rstrVOffset = rVector[4].c_str();
const std::string & c_rstrbSplat = rVector[5].c_str();
const std::string & c_rstrBegin = rVector[6].c_str();
const std::string & c_rstrEnd = rVector[7].c_str();
float fuScale, fvScale, fuOffset, fvOffset;
bool bSplat;
unsigned short usBegin, usEnd;
fuScale = atof(c_rstrUScale.c_str());
fvScale = atof(c_rstrVScale.c_str());
fuOffset = atof(c_rstrUOffset.c_str());
fvOffset = atof(c_rstrVOffset.c_str());
bSplat = 0 != atoi(c_rstrbSplat.c_str());
usBegin = static_cast<unsigned short>(atoi(c_rstrBegin.c_str()));
usEnd = static_cast<unsigned short>(atoi(c_rstrEnd.c_str()));
if (!SetTexture(i + 1, c_rstrFileName.c_str(), fuScale, fvScale, fuOffset, fvOffset, bSplat, usBegin, usEnd, fTerrainTexCoordBase))
TraceError("CTextureSet::Load : SetTexture failed : Filename: %s", c_rstrFileName.c_str());
}
m_stFileName.assign(c_szTextureSetFileName);
NANOEND
return true;
}
void CTextureSet::Clear()
{
m_ErrorTexture.ImageInstance.Destroy();
m_Textures.clear();
Initialize();
}
void CTextureSet::AddEmptyTexture()
{
TTerrainTexture eraser;
m_Textures.push_back(eraser);
}
unsigned long CTextureSet::GetTextureCount()
{
return m_Textures.size();
}
TTerrainTexture & CTextureSet::GetTexture(unsigned long ulIndex)
{
if (GetTextureCount() <= ulIndex)
return m_ErrorTexture;
return m_Textures[ulIndex];
}
bool CTextureSet::SetTexture(unsigned long ulIndex,
const char * c_szFileName,
float fuScale,
float fvScale,
float fuOffset,
float fvOffset,
bool bSplat,
unsigned short usBegin,
unsigned short usEnd,
float fTerrainTexCoordBase)
{
if (ulIndex >= m_Textures.size())
{
TraceError("CTextureSet::SetTexture : Index Error : Index(%d) is Larger than TextureSet Size(%d)", ulIndex, m_Textures.size());
return false;
}
CResource * pResource = CResourceManager::Instance().GetResourcePointer(c_szFileName);
if (!pResource->IsType(CGraphicImage::Type()))
{
TraceError("CTerrainImpl::GenerateTexture : %s is NOT Image File", pResource->GetFileName());
return false;
}
TTerrainTexture & tex = m_Textures[ulIndex];
tex.stFilename = c_szFileName;
tex.UScale = fuScale;
tex.VScale = fvScale;
tex.UOffset = fuOffset;
tex.VOffset = fvOffset;
tex.bSplat = bSplat;
tex.Begin = usBegin;
tex.End = usEnd;
tex.ImageInstance.SetImagePointer(static_cast<CGraphicImage *>(pResource));
tex.pd3dTexture = tex.ImageInstance.GetTexturePointer()->GetD3DTexture();
D3DXMatrixScaling(&tex.m_matTransform, fTerrainTexCoordBase * tex.UScale, -fTerrainTexCoordBase * tex.VScale, 0.0f);
tex.m_matTransform._41 = tex.UOffset;
tex.m_matTransform._42 = -tex.VOffset;
return true;
}
void CTextureSet::Reload(float fTerrainTexCoordBase)
{
for (DWORD dwIndex = 1; dwIndex < GetTextureCount(); ++dwIndex)
{
TTerrainTexture & tex = m_Textures[dwIndex];
tex.ImageInstance.ReloadImagePointer((CGraphicImage *) CResourceManager::Instance().GetResourcePointer(tex.stFilename.c_str()));
tex.pd3dTexture = tex.ImageInstance.GetTexturePointer()->GetD3DTexture();
D3DXMatrixScaling(&tex.m_matTransform, fTerrainTexCoordBase * tex.UScale, -fTerrainTexCoordBase * tex.VScale, 0.0f);
tex.m_matTransform._41 = tex.UOffset;
tex.m_matTransform._42 = -tex.VOffset;
}
}
bool CTextureSet::AddTexture(const char * c_szFileName,
float fuScale,
float fvScale,
float fuOffset,
float fvOffset,
bool bSplat,
unsigned short usBegin,
unsigned short usEnd,
float fTerrainTexCoordBase)
{
if (GetTextureCount() >= 256)
{
LogBox("\305\330\275\272\303\263\270\246 \264\365 \300\314\273\363 \303\337\260\241\307\322 \274\366 \276\370\275\300\264\317\264\331.", "\303\326\264\353 \305\330\275\272\303\263 \260\263\274\366 255\260\263");
return false;
}
for (unsigned long i = 1; i < GetTextureCount(); ++i)
{
if (0 == m_Textures[i].stFilename.compare(c_szFileName))
{
LogBox("\265\277\300\317\307\321 \300\314\270\247\300\307 \305\330\275\272\303\263\260\241 \300\314\271\314 \300\326\275\300\264\317\264\331.", "\301\337\272\271");
return false;
}
}
CResource * pResource = CResourceManager::Instance().GetResourcePointer(c_szFileName);
if (!pResource->IsType(CGraphicImage::Type()))
{
LogBox("CTerrainImpl::GenerateTexture : \300\314\271\314\301\366 \306\304\300\317\300\314 \276\306\264\325\264\317\264\331. %s", pResource->GetFileName());
return false;
}
m_Textures.reserve(m_Textures.size() + 1);
SetTexture(m_Textures.size() - 1,
c_szFileName,
fuScale,
fvScale,
fuOffset,
fvOffset,
bSplat,
usBegin,
usEnd,
fTerrainTexCoordBase);
return true;
}
bool CTextureSet::RemoveTexture(unsigned long ulIndex)
{
if (GetTextureCount() <= ulIndex)
return false;
TTextureVector::iterator itor = m_Textures.begin() + ulIndex;
m_Textures.erase(itor);
return true;
}
bool CTextureSet::Save(const char * c_pszFileName)
{
FILE * pFile = fopen(c_pszFileName, "w");
if (!pFile)
return false;
fprintf(pFile, "TextureSet\n");
fprintf(pFile, "\n");
fprintf(pFile, "TextureCount %ld\n", GetTextureCount() - 1); // -1 을 하는 이유는 지우개 때문임
fprintf(pFile, "\n");
for (DWORD i = 1; i < GetTextureCount(); ++i)
{
TTerrainTexture & rTex = m_Textures[i];
fprintf(pFile, "Start Texture%03d\n", i);
fprintf(pFile, " \"%s\"\n", rTex.stFilename.c_str());
fprintf(pFile, " %f\n", rTex.UScale);
fprintf(pFile, " %f\n", rTex.VScale);
fprintf(pFile, " %f\n", rTex.UOffset);
fprintf(pFile, " %f\n", rTex.VOffset);
fprintf(pFile, " %d\n", rTex.bSplat);
fprintf(pFile, " %hu\n", rTex.Begin);
fprintf(pFile, " %hu\n", rTex.End);
fprintf(pFile, "End Texture%03d\n", i);
}
fclose(pFile);
return true;
}
@@ -0,0 +1,921 @@
// PythonBackground.cpp: implementation of the CPythonBackground class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "../EterLib/CullingManager.h"
#include "../EterLib/Camera.h"
#include "../EterPack/EterPackManager.h"
#include "../GameLib/MapOutdoor.h"
#include "../GameLib/PropertyLoader.h"
#include "PythonBackground.h"
#include "PythonCharacterManager.h"
#include "PythonNetworkStream.h"
#include "PythonMiniMap.h"
#include "PythonSystem.h"
std::string g_strEffectName = "d:/ymir work/effect/etc/direction/direction_land.mse";
DWORD CPythonBackground::GetRenderShadowTime()
{
return m_dwRenderShadowTime;
}
bool CPythonBackground::SetVisiblePart(int eMapOutDoorPart, bool isVisible)
{
if (!m_pkMap)
return false;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.SetVisiblePart(eMapOutDoorPart, isVisible);
return true;
}
void CPythonBackground::EnableTerrainOnlyForHeight()
{
if (!m_pkMap)
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.EnableTerrainOnlyForHeight(TRUE);
}
bool CPythonBackground::SetSplatLimit(int iSplatNum)
{
if (!m_pkMap)
return false;
CMapOutdoor& rkMap = GetMapOutdoorRef();
rkMap.SetSplatLimit(iSplatNum);
return true;
}
void CPythonBackground::CreateCharacterShadowTexture()
{
if (!m_pkMap)
return;
CMapOutdoor& rkMap = GetMapOutdoorRef();
rkMap.CreateCharacterShadowTexture();
}
void CPythonBackground::ReleaseCharacterShadowTexture()
{
if (!m_pkMap)
return;
CMapOutdoor& rkMap = GetMapOutdoorRef();
rkMap.ReleaseCharacterShadowTexture();
}
void CPythonBackground::RefreshShadowLevel()
{
SetShadowLevel(CPythonSystem::Instance().GetShadowLevel());
}
bool CPythonBackground::SetShadowLevel(int eLevel)
{
if (!m_pkMap)
return false;
if (m_eShadowLevel == eLevel)
return true;
CMapOutdoor& rkMap = GetMapOutdoorRef();
m_eShadowLevel = eLevel;
switch (m_eShadowLevel)
{
case SHADOW_NONE:
rkMap.SetDrawShadow(false);
rkMap.SetShadowTextureSize(512);
break;
case SHADOW_GROUND:
rkMap.SetDrawShadow(true);
rkMap.SetDrawCharacterShadow(false);
rkMap.SetShadowTextureSize(512);
break;
case SHADOW_GROUND_AND_SOLO:
rkMap.SetDrawShadow(true);
rkMap.SetDrawCharacterShadow(true);
rkMap.SetShadowTextureSize(512);
break;
case SHADOW_ALL:
rkMap.SetDrawShadow(true);
rkMap.SetDrawCharacterShadow(true);
rkMap.SetShadowTextureSize(512);
break;
case SHADOW_ALL_HIGH:
rkMap.SetDrawShadow(true);
rkMap.SetDrawCharacterShadow(true);
rkMap.SetShadowTextureSize(1024);
break;
case SHADOW_ALL_MAX:
rkMap.SetDrawShadow(true);
rkMap.SetDrawCharacterShadow(true);
rkMap.SetShadowTextureSize(2048);
break;
}
return true;
}
void CPythonBackground::SelectViewDistanceNum(int eNum)
{
if (!m_pkMap)
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
if (!mc_pcurEnvironmentData)
{
TraceError("CPythonBackground::SelectViewDistanceNum(int eNum=%d) mc_pcurEnvironmentData is NULL", eNum);
return;
}
m_eViewDistanceNum = eNum;
TEnvironmentData * env = ((TEnvironmentData *) mc_pcurEnvironmentData);
// 게임 분위기를 바꿔놓을 수 있으므로 reserve로 되어있으면 고치지 않는다.
if (env->bReserve)
{
env->m_fFogNearDistance = m_ViewDistanceSet[m_eViewDistanceNum].m_fFogStart;
env->m_fFogFarDistance = m_ViewDistanceSet[m_eViewDistanceNum].m_fFogEnd;
env->v3SkyBoxScale = m_ViewDistanceSet[m_eViewDistanceNum].m_v3SkyBoxScale;
rkMap.SetEnvironmentSkyBox();
}
}
void CPythonBackground::SetViewDistanceSet(int eNum, float fFarClip)
{
if (!m_pkMap)
return;
m_ViewDistanceSet[eNum].m_fFogStart = fFarClip * 0.5f;//0.3333333f;
m_ViewDistanceSet[eNum].m_fFogEnd = fFarClip * 0.7f;//0.6666667f;
float fSkyBoxScale = fFarClip * 0.6f;//0.5773502f;
m_ViewDistanceSet[eNum].m_v3SkyBoxScale = D3DXVECTOR3(fSkyBoxScale, fSkyBoxScale, fSkyBoxScale);
m_ViewDistanceSet[eNum].m_fFarClip = fFarClip;
if (eNum == m_eViewDistanceNum)
SelectViewDistanceNum(eNum);
}
float CPythonBackground::GetFarClip()
{
if (!m_pkMap)
return 50000.0f;
if (m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip==0.0f)
{
TraceError("CPythonBackground::GetFarClip m_eViewDistanceNum=%d", m_eViewDistanceNum);
m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip=25600.0f;
}
return m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip;
}
void CPythonBackground::GetDistanceSetInfo(int * peNum, float * pfStart, float * pfEnd, float * pfFarClip)
{
if (!m_pkMap)
{
*peNum = 4;
*pfStart= 10000.0f;
*pfEnd= 15000.0f;
*pfFarClip = 50000.0f;
return;
}
*peNum = m_eViewDistanceNum;
*pfStart = m_ViewDistanceSet[m_eViewDistanceNum].m_fFogStart;
*pfEnd= m_ViewDistanceSet[m_eViewDistanceNum].m_fFogEnd;
*pfFarClip = m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPythonBackground::CPythonBackground()
{
m_dwRenderShadowTime=0;
m_eViewDistanceNum=0;
m_eViewDistanceNum=0;
m_eViewDistanceNum=0;
m_eShadowLevel=SHADOW_NONE;
m_dwBaseX=0;
m_dwBaseY=0;
m_strMapName="";
m_iDayMode = DAY_MODE_LIGHT;
m_iXMasTreeGrade = 0;
m_bVisibleGuildArea = FALSE;
SetViewDistanceSet(4, 25600.0f);
SetViewDistanceSet(3, 25600.0f);
SetViewDistanceSet(2, 25600.0f);
SetViewDistanceSet(1, 25600.0f);
SetViewDistanceSet(0, 25600.0f);
Initialize();
}
CPythonBackground::~CPythonBackground()
{
Tracen("CPythonBackground Clear");
}
void CPythonBackground::Initialize()
{
std::string stAtlasInfoFileName (LocaleService_GetLocalePath());
stAtlasInfoFileName += "/AtlasInfo.txt";
SetAtlasInfoFileName(stAtlasInfoFileName.c_str());
CMapManager::Initialize();
}
void CPythonBackground::__CreateProperty()
{
if (CEterPackManager::SEARCH_FILE_FIRST == CEterPackManager::Instance().GetSearchMode() &&
_access("property", 0) == 0)
{
m_PropertyManager.Initialize(NULL);
CPropertyLoader PropertyLoader;
PropertyLoader.SetPropertyManager(&m_PropertyManager);
PropertyLoader.Create("*.*", "Property");
}
else
{
m_PropertyManager.Initialize("pack/property");
}
}
//////////////////////////////////////////////////////////////////////
// Normal Functions
//////////////////////////////////////////////////////////////////////
bool CPythonBackground::GetPickingPoint(D3DXVECTOR3 * v3IntersectPt)
{
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetPickingPoint(v3IntersectPt);
}
bool CPythonBackground::GetPickingPointWithRay(const CRay & rRay, D3DXVECTOR3 * v3IntersectPt)
{
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetPickingPointWithRay(rRay, v3IntersectPt);
}
bool CPythonBackground::GetPickingPointWithRayOnlyTerrain(const CRay & rRay, D3DXVECTOR3 * v3IntersectPt)
{
CMapOutdoor& rkMap=GetMapOutdoorRef();
return rkMap.GetPickingPointWithRayOnlyTerrain(rRay, v3IntersectPt);
}
BOOL CPythonBackground::GetLightDirection(D3DXVECTOR3 & rv3LightDirection)
{
if (!mc_pcurEnvironmentData)
return FALSE;
rv3LightDirection.x = mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND].Direction.x;
rv3LightDirection.y = mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND].Direction.y;
rv3LightDirection.z = mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND].Direction.z;
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
void CPythonBackground::Destroy()
{
CMapManager::Destroy();
m_SnowEnvironment.Destroy();
m_bVisibleGuildArea = FALSE;
}
void CPythonBackground::Create()
{
static int s_isCreateProperty=false;
if (!s_isCreateProperty)
{
s_isCreateProperty=true;
__CreateProperty();
}
CMapManager::Create();
m_SnowEnvironment.Create();
}
struct FGetPortalID
{
float m_fRequestX, m_fRequestY;
std::set<int> m_kSet_iPortalID;
FGetPortalID(float fRequestX, float fRequestY)
{
m_fRequestX=fRequestX;
m_fRequestY=fRequestY;
}
void operator () (CGraphicObjectInstance * pObject)
{
for (int i = 0; i < PORTAL_ID_MAX_NUM; ++i)
{
int iID = pObject->GetPortal(i);
if (0 == iID)
break;
m_kSet_iPortalID.insert(iID);
}
}
};
void CPythonBackground::Update(float fCenterX, float fCenterY, float fCenterZ)
{
if (!IsMapReady())
return;
#ifdef __PERFORMANCE_CHECKER__
DWORD t1=ELTimer_GetMSec();
#endif
UpdateMap(fCenterX, fCenterY, fCenterZ);
#ifdef __PERFORMANCE_CHECKER__
DWORD t2=ELTimer_GetMSec();
#endif
UpdateAroundAmbience(fCenterX, fCenterY, fCenterZ);
#ifdef __PERFORMANCE_CHECKER__
DWORD t3=ELTimer_GetMSec();
#endif
m_SnowEnvironment.Update(D3DXVECTOR3(fCenterX, -fCenterY, fCenterZ));
#ifdef __PERFORMANCE_CHECKER__
{
static FILE* fp=fopen("perf_bg_update.txt", "w");
if (t3-t1>5)
{
fprintf(fp, "BG.Total %d (Time %f)\n", t3-t1, ELTimer_GetMSec()/1000.0f);
fprintf(fp, "BG.UpdateMap %d\n", t2-t1);
fprintf(fp, "BG.UpdateAmb %d\n", t3-t2);
fflush(fp);
}
}
#endif
// Portal Process
CMapOutdoor& rkMap=GetMapOutdoorRef();
if (rkMap.IsEnablePortal())
{
CCullingManager & rkCullingMgr = CCullingManager::Instance();
FGetPortalID kGetPortalID(fCenterX, -fCenterY);
Vector3d aVector3d;
aVector3d.Set(fCenterX, -fCenterY, fCenterZ);
Vector3d toTop;
toTop.Set(0, 0, 25000.0f);
rkCullingMgr.ForInRay(aVector3d, toTop, &kGetPortalID);
std::set<int>::iterator itor = kGetPortalID.m_kSet_iPortalID.begin();
if (!__IsSame(kGetPortalID.m_kSet_iPortalID, m_kSet_iShowingPortalID))
{
ClearPortal();
std::set<int>::iterator itor=kGetPortalID.m_kSet_iPortalID.begin();
for (; itor!=kGetPortalID.m_kSet_iPortalID.end(); ++itor)
{
AddShowingPortalID(*itor);
}
RefreshPortal();
m_kSet_iShowingPortalID = kGetPortalID.m_kSet_iPortalID;
}
}
// Target Effect Process
{
std::map<DWORD, DWORD>::iterator itor = m_kMap_dwTargetID_dwChrID.begin();
for (; itor != m_kMap_dwTargetID_dwChrID.end(); ++itor)
{
DWORD dwTargetID = itor->first;
DWORD dwChrID = itor->second;
CInstanceBase * pInstance = CPythonCharacterManager::Instance().GetInstancePtr(dwChrID);
if (!pInstance)
continue;
TPixelPosition kPixelPosition;
pInstance->NEW_GetPixelPosition(&kPixelPosition);
CreateSpecialEffect(dwTargetID,
+kPixelPosition.x,
-kPixelPosition.y,
+kPixelPosition.z,
g_strEffectName.c_str());
}
}
// Reserve Target Effect
{
std::map<DWORD, SReserveTargetEffect>::iterator itor = m_kMap_dwID_kReserveTargetEffect.begin();
for (; itor != m_kMap_dwID_kReserveTargetEffect.end();)
{
DWORD dwID = itor->first;
SReserveTargetEffect & rReserveTargetEffect = itor->second;
float ilx = float(rReserveTargetEffect.ilx);
float ily = float(rReserveTargetEffect.ily);
float fHeight = rkMap.GetHeight(ilx, ily);
if (0.0f == fHeight)
{
++itor;
continue;
}
CreateSpecialEffect(dwID, ilx, ily, fHeight, g_strEffectName.c_str());
itor = m_kMap_dwID_kReserveTargetEffect.erase(itor);
}
}
}
bool CPythonBackground::__IsSame(std::set<int> & rleft, std::set<int> & rright)
{
std::set<int>::iterator itor_l;
std::set<int>::iterator itor_r;
for (itor_l=rleft.begin(); itor_l!=rleft.end(); ++itor_l)
{
if (rright.end() == rright.find(*itor_l))
return false;
}
for (itor_r=rright.begin(); itor_r!=rright.end(); ++itor_r)
{
if (rleft.end() == rleft.find(*itor_r))
return false;
}
return true;
}
void CPythonBackground::Render()
{
if (!IsMapReady())
return;
m_SnowEnvironment.Deform();
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.Render();
if (m_bVisibleGuildArea)
rkMap.RenderMarkedArea();
}
void CPythonBackground::RenderSnow()
{
m_SnowEnvironment.Render();
}
void CPythonBackground::RenderPCBlocker()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.RenderPCBlocker();
}
void CPythonBackground::RenderCollision()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.RenderCollision();
}
void CPythonBackground::RenderCharacterShadowToTexture()
{
extern bool GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW;
if (GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW)
return;
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
DWORD t1=ELTimer_GetMSec();
if (m_eShadowLevel == SHADOW_ALL ||
m_eShadowLevel == SHADOW_ALL_HIGH ||
m_eShadowLevel == SHADOW_ALL_MAX ||
m_eShadowLevel == SHADOW_GROUND_AND_SOLO)
{
D3DXMATRIX matWorld;
STATEMANAGER.GetTransform(D3DTS_WORLD, &matWorld);
bool canRender=rkMap.BeginRenderCharacterShadowToTexture();
if (canRender)
{
CPythonCharacterManager& rkChrMgr=CPythonCharacterManager::Instance();
if (m_eShadowLevel == SHADOW_GROUND_AND_SOLO)
rkChrMgr.RenderShadowMainInstance();
else
rkChrMgr.RenderShadowAllInstances();
}
rkMap.EndRenderCharacterShadowToTexture();
STATEMANAGER.SetTransform(D3DTS_WORLD, &matWorld);
}
DWORD t2=ELTimer_GetMSec();
m_dwRenderShadowTime=t2-t1;
}
inline float Interpolate(float fStart, float fEnd, float fPercent)
{
return fStart + (fEnd - fStart) * fPercent;
}
struct CollisionChecker
{
bool isBlocked;
CInstanceBase* pInstance;
CollisionChecker(CInstanceBase* pInstance) : pInstance(pInstance), isBlocked(false) {}
void operator () (CGraphicObjectInstance* pOpponent)
{
if (isBlocked)
return;
if (!pOpponent)
return;
if (pInstance->IsBlockObject(*pOpponent))
isBlocked=true;
}
};
struct CollisionAdjustChecker
{
bool isBlocked;
CInstanceBase* pInstance;
CollisionAdjustChecker(CInstanceBase* pInstance) : pInstance(pInstance), isBlocked(false) {}
void operator () (CGraphicObjectInstance* pOpponent)
{
if (!pOpponent)
return;
if (pInstance->AvoidObject(*pOpponent))
isBlocked=true;
}
};
bool CPythonBackground::CheckAdvancing(CInstanceBase * pInstance)
{
if (!IsMapReady())
return true;
Vector3d center;
float radius;
pInstance->GetGraphicThingInstanceRef().GetBoundingSphere(center,radius);
CCullingManager & rkCullingMgr = CCullingManager::Instance();
CollisionAdjustChecker kCollisionAdjustChecker(pInstance);
rkCullingMgr.ForInRange(center, radius, &kCollisionAdjustChecker);
if (kCollisionAdjustChecker.isBlocked)
{
CollisionChecker kCollisionChecker(pInstance);
rkCullingMgr.ForInRange(center, radius, &kCollisionChecker);
if (kCollisionChecker.isBlocked)
{
pInstance->BlockMovement();
return true;
}
else
{
pInstance->NEW_MoveToDestPixelPositionDirection(pInstance->NEW_GetDstPixelPositionRef());
}
return false;
}
return false;
}
void CPythonBackground::RenderSky()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.RenderSky();
}
void CPythonBackground::RenderCloud()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.RenderCloud();
}
void CPythonBackground::RenderWater()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.RenderWater();
}
void CPythonBackground::RenderEffect()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.RenderEffect();
}
void CPythonBackground::RenderBeforeLensFlare()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.RenderBeforeLensFlare();
}
void CPythonBackground::RenderAfterLensFlare()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.RenderAfterLensFlare();
}
void CPythonBackground::ClearGuildArea()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.ClearGuildArea();
}
void CPythonBackground::RegisterGuildArea(int isx, int isy, int iex, int iey)
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.RegisterGuildArea(isx, isy, iex, iey);
}
void CPythonBackground::SetCharacterDirLight()
{
if (!IsMapReady())
return;
if (!mc_pcurEnvironmentData)
return;
STATEMANAGER.SetLight(0, &mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_CHARACTER]);
}
void CPythonBackground::SetBackgroundDirLight()
{
if (!IsMapReady())
return;
if (!mc_pcurEnvironmentData)
return;
STATEMANAGER.SetLight(0, &mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND]);
}
void CPythonBackground::GlobalPositionToLocalPosition(LONG& rGlobalX, LONG& rGlobalY)
{
rGlobalX-=m_dwBaseX;
rGlobalY-=m_dwBaseY;
}
void CPythonBackground::LocalPositionToGlobalPosition(LONG& rLocalX, LONG& rLocalY)
{
rLocalX+=m_dwBaseX;
rLocalY+=m_dwBaseY;
}
void CPythonBackground::RegisterDungeonMapName(const char * c_szMapName)
{
m_kSet_strDungeonMapName.insert(c_szMapName);
}
CPythonBackground::TMapInfo* CPythonBackground::GlobalPositionToMapInfo(DWORD dwGlobalX, DWORD dwGlobalY)
{
TMapInfoVector::iterator f = std::find_if(m_kVct_kMapInfo.begin(), m_kVct_kMapInfo.end(), FFindWarpMapName(dwGlobalX, dwGlobalY));
if (f == m_kVct_kMapInfo.end())
return NULL;
return &(*f);
}
void CPythonBackground::Warp(DWORD dwX, DWORD dwY)
{
TMapInfo* pkMapInfo = GlobalPositionToMapInfo(dwX, dwY);
if (!pkMapInfo)
{
TraceError("NOT_FOUND_GLOBAL_POSITION(%d, %d)", dwX, dwY);
return;
}
RefreshShadowLevel();
TMapInfo & rMapInfo = *pkMapInfo;
assert( (dwX >= rMapInfo.m_dwBaseX) && (dwY >= rMapInfo.m_dwBaseY) );
if (!LoadMap(rMapInfo.m_strName, float(dwX - rMapInfo.m_dwBaseX), float(dwY - rMapInfo.m_dwBaseY), 0))
{
// LOAD_MAP_ERROR_HANDLING
PostQuitMessage(0);
// END_OF_LOAD_MAP_ERROR_HANDLING
return;
}
CPythonMiniMap::Instance().LoadAtlas();
m_dwBaseX=rMapInfo.m_dwBaseX;
m_dwBaseY=rMapInfo.m_dwBaseY;
m_strMapName = rMapInfo.m_strName;
SetXMaxTree(m_iXMasTreeGrade);
if (m_kSet_strDungeonMapName.end() != m_kSet_strDungeonMapName.find(m_strMapName))
{
EnableTerrainOnlyForHeight();
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.EnablePortal(TRUE);
}
m_kSet_iShowingPortalID.clear();
m_kMap_dwTargetID_dwChrID.clear();
m_kMap_dwID_kReserveTargetEffect.clear();
}
void CPythonBackground::VisibleGuildArea()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.VisibleMarkedArea();
m_bVisibleGuildArea = TRUE;
}
void CPythonBackground::DisableGuildArea()
{
if (!IsMapReady())
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.DisableMarkedArea();
m_bVisibleGuildArea = FALSE;
}
const char * CPythonBackground::GetWarpMapName()
{
return m_strMapName.c_str();
}
void CPythonBackground::ChangeToDay()
{
m_iDayMode = DAY_MODE_LIGHT;
}
void CPythonBackground::ChangeToNight()
{
m_iDayMode = DAY_MODE_DARK;
}
void CPythonBackground::EnableSnowEnvironment()
{
m_SnowEnvironment.Enable();
}
void CPythonBackground::DisableSnowEnvironment()
{
m_SnowEnvironment.Disable();
}
const D3DXVECTOR3 c_v3TreePos = D3DXVECTOR3(76500.0f, -60900.0f, 20215.0f);
void CPythonBackground::SetXMaxTree(int iGrade)
{
if (!m_pkMap)
return;
assert(iGrade >= 0 && iGrade <= 3);
m_iXMasTreeGrade = iGrade;
CMapOutdoor& rkMap=GetMapOutdoorRef();
if ("map_n_snowm_01" != m_strMapName)
{
rkMap.XMasTree_Destroy();
return;
}
if (0 == iGrade)
{
rkMap.XMasTree_Destroy();
return;
}
//////////////////////////////////////////////////////////////////////
iGrade -= 1;
iGrade = max(iGrade, 0);
iGrade = min(iGrade, 2);
static std::string s_strTreeName[3] = {
"d:/ymir work/tree/christmastree1.spt",
"d:/ymir work/tree/christmastree2.spt",
"d:/ymir work/tree/christmastree3.spt"
};
static std::string s_strEffectName[3] = {
"d:/ymir work/effect/etc/christmas_tree/tree_1s.mse",
"d:/ymir work/effect/etc/christmas_tree/tree_2s.mse",
"d:/ymir work/effect/etc/christmas_tree/tree_3s.mse",
};
rkMap.XMasTree_Set(c_v3TreePos.x, c_v3TreePos.y, c_v3TreePos.z, s_strTreeName[iGrade].c_str(), s_strEffectName[iGrade].c_str());
}
void CPythonBackground::CreateTargetEffect(DWORD dwID, DWORD dwChrVID)
{
m_kMap_dwTargetID_dwChrID.insert(std::make_pair(dwID, dwChrVID));
}
void CPythonBackground::CreateTargetEffect(DWORD dwID, long lx, long ly)
{
if (m_kMap_dwTargetID_dwChrID.end() != m_kMap_dwTargetID_dwChrID.find(dwID))
return;
CMapOutdoor& rkMap=GetMapOutdoorRef();
DWORD dwBaseX;
DWORD dwBaseY;
rkMap.GetBaseXY(&dwBaseX, &dwBaseY);
int ilx = +(lx-int(dwBaseX));
int ily = -(ly-int(dwBaseY));
float fHeight = rkMap.GetHeight(float(ilx), float(ily));
if (0.0f == fHeight)
{
SReserveTargetEffect ReserveTargetEffect;
ReserveTargetEffect.ilx = ilx;
ReserveTargetEffect.ily = ily;
m_kMap_dwID_kReserveTargetEffect.insert(std::make_pair(dwID, ReserveTargetEffect));
return;
}
CreateSpecialEffect(dwID, ilx, ily, fHeight, g_strEffectName.c_str());
}
void CPythonBackground::DeleteTargetEffect(DWORD dwID)
{
if (m_kMap_dwID_kReserveTargetEffect.end() != m_kMap_dwID_kReserveTargetEffect.find(dwID))
{
m_kMap_dwID_kReserveTargetEffect.erase(dwID);
}
if (m_kMap_dwTargetID_dwChrID.end() != m_kMap_dwTargetID_dwChrID.find(dwID))
{
m_kMap_dwTargetID_dwChrID.erase(dwID);
}
DeleteSpecialEffect(dwID);
}
void CPythonBackground::CreateSpecialEffect(DWORD dwID, float fx, float fy, float fz, const char * c_szFileName)
{
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.SpecialEffect_Create(dwID, fx, fy, fz, c_szFileName);
}
void CPythonBackground::DeleteSpecialEffect(DWORD dwID)
{
CMapOutdoor& rkMap=GetMapOutdoorRef();
rkMap.SpecialEffect_Delete(dwID);
}
@@ -0,0 +1,619 @@
#include "StdAfx.h"
#include "PythonSystem.h"
#include "PythonBackground.h"
#include "../EterLib/StateManager.h"
#include "../GameLib/MapOutdoor.h"
PyObject * backgroundIsSoftwareTiling(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground& rkBG=CPythonBackground::Instance();
return Py_BuildValue("i", rkBG.IsSoftwareTilingEnable());
}
PyObject * backgroundEnableSoftwareTiling(PyObject * poSelf, PyObject * poArgs)
{
int nIsEnable;
if (!PyTuple_GetInteger(poArgs, 0, &nIsEnable))
return Py_BadArgument();
bool isEnable=nIsEnable ? true : false;
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.ReserveSoftwareTilingEnable(isEnable);
CPythonSystem& rkSystem=CPythonSystem::Instance();
rkSystem.SetSoftwareTiling(isEnable);
return Py_BuildNone();
}
PyObject * backgroundEnableSnow(PyObject * poSelf, PyObject * poArgs)
{
int nIsEnable;
if (!PyTuple_GetInteger(poArgs, 0, &nIsEnable))
return Py_BadArgument();
CPythonBackground& rkBG=CPythonBackground::Instance();
if (nIsEnable)
rkBG.EnableSnowEnvironment();
else
rkBG.DisableSnowEnvironment();
return Py_BuildNone();
}
PyObject * backgroundLoadMap(PyObject * poSelf, PyObject * poArgs)
{
char * pszMapPathName;
if (!PyTuple_GetString(poArgs, 0, &pszMapPathName))
return Py_BadArgument();
float x, y, z;
if (!PyTuple_GetFloat(poArgs, 1, &x))
return Py_BadArgument();
if (!PyTuple_GetFloat(poArgs, 2, &y))
return Py_BadArgument();
if (!PyTuple_GetFloat(poArgs, 3, &z))
return Py_BadArgument();
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.LoadMap(pszMapPathName, x, y, z);
//#ifdef _DEBUG
// CMapOutdoor& rkMap=rkBG.GetMapOutdoorRef();
// rkMap.EnablePortal(TRUE);
// rkBG.EnableTerrainOnlyForHeight();
//#endif
return Py_BuildNone();
}
PyObject * backgroundDestroy(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.SetShadowLevel(CPythonBackground::SHADOW_NONE);
rkBG.Destroy();
return Py_BuildNone();
}
PyObject * backgroundRegisterEnvironmentData(PyObject * poSelf, PyObject * poArgs)
{
int iIndex;
if (!PyTuple_GetInteger(poArgs, 0, &iIndex))
return Py_BadArgument();
char * pszEnvironmentFileName;
if (!PyTuple_GetString(poArgs, 1, &pszEnvironmentFileName))
return Py_BadArgument();
CPythonBackground& rkBG=CPythonBackground::Instance();
if (!rkBG.RegisterEnvironmentData(iIndex, pszEnvironmentFileName))
{
TraceError("background.RegisterEnvironmentData(iIndex=%d, szEnvironmentFileName=%s)", iIndex, pszEnvironmentFileName);
// TODO:
// 디폴트 환경 설정 작업을 해주자
}
return Py_BuildNone();
}
PyObject * backgroundSetEnvironmentData(PyObject * poSelf, PyObject * poArgs)
{
int iIndex;
if (!PyTuple_GetInteger(poArgs, 0, &iIndex))
return Py_BadArgument();
const TEnvironmentData * c_pEnvironmenData;
CPythonBackground& rkBG=CPythonBackground::Instance();
if (rkBG.GetEnvironmentData(iIndex, &c_pEnvironmenData))
rkBG.ResetEnvironmentDataPtr(c_pEnvironmenData);
return Py_BuildNone();
}
PyObject * backgroundGetCurrentMapName(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground& rkBG=CPythonBackground::Instance();
return Py_BuildValue("s", rkBG.GetWarpMapName());
}
PyObject * backgroundGetPickingPoint(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground& rkBG=CPythonBackground::Instance();
TPixelPosition kPPosPicked(0.0f, 0.0f, 0.0f);
if (rkBG.GetPickingPoint(&kPPosPicked))
{
kPPosPicked.y=-kPPosPicked.y;
}
return Py_BuildValue("fff", kPPosPicked.x, kPPosPicked.y, kPPosPicked.z);
}
PyObject * backgroundBeginEnvironment(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.BeginEnvironment();
return Py_BuildNone();
}
PyObject * backgroundEndEnvironemt(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.EndEnvironment();
return Py_BuildNone();
}
PyObject * backgroundSetCharacterDirLight(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground& rkBG = CPythonBackground::Instance();
rkBG.SetCharacterDirLight();
return Py_BuildNone();
}
PyObject * backgroundSetBackgroundDirLight(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground& rkBG = CPythonBackground::Instance();
rkBG.SetBackgroundDirLight();
return Py_BuildNone();
}
PyObject * backgroundInitialize(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.Create();
return Py_BuildNone();
}
PyObject * backgroundUpdate(PyObject * poSelf, PyObject * poArgs)
{
float fCameraX;
if (!PyTuple_GetFloat(poArgs, 0, &fCameraX))
return Py_BadArgument();
float fCameraY;
if (!PyTuple_GetFloat(poArgs, 1, &fCameraY))
return Py_BadArgument();
float fCameraZ;
if (!PyTuple_GetFloat(poArgs, 2, &fCameraZ))
return Py_BadArgument();
CPythonBackground::Instance().Update(fCameraX, fCameraY, fCameraZ);
return Py_BuildNone();
}
PyObject * backgroundRender(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().Render();
return Py_BuildNone();
}
PyObject * backgroundRenderPCBlocker(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().RenderPCBlocker();
return Py_BuildNone();
}
PyObject * backgroundRenderCollision(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().RenderCollision();
return Py_BuildNone();
}
PyObject * backgroundRenderSky(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().RenderSky();
return Py_BuildNone();
}
PyObject * backgroundRenderCloud(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().RenderCloud();
return Py_BuildNone();
}
PyObject * backgroundRenderWater(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().RenderWater();
return Py_BuildNone();
}
PyObject * backgroundRenderEffect(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().RenderEffect();
return Py_BuildNone();
}
PyObject * backgroundRenderBeforeLensFlare(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().RenderBeforeLensFlare();
return Py_BuildNone();
}
PyObject * backgroundRenderAfterLensFlare(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().RenderAfterLensFlare();
return Py_BuildNone();
}
PyObject * backgroundRenderCharacterShadowToTexture(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().RenderCharacterShadowToTexture();
return Py_BuildNone();
}
PyObject * backgroundRenderDungeon(PyObject * poSelf, PyObject * poArgs)
{
assert(!"background.RenderDungeon() - \273\347\277\353\307\317\301\366 \276\312\264\302 \307\324\274\366\300\324\264\317\264\331 - [levites]");
return Py_BuildNone();
}
PyObject * backgroundGetHeight(PyObject * poSelf, PyObject * poArgs)
{
float fx;
if (!PyTuple_GetFloat(poArgs, 0, &fx))
return Py_BadArgument();
float fy;
if (!PyTuple_GetFloat(poArgs, 1, &fy))
return Py_BadArgument();
float fz = CPythonBackground::Instance().GetHeight(fx, fy);
return Py_BuildValue("f", fz);
}
PyObject * backgroundGetRenderedSplatNum(PyObject * poSelf, PyObject * poArgs)
{
int iPatch;
int iSplat;
float fSplatRatio;
std::vector<int> & aTextureNumVector = CPythonBackground::Instance().GetRenderedSplatNum(&iPatch, &iSplat, &fSplatRatio);
char szOutput[MAX_PATH] = "";
int iOutput = 0;
for( std::vector<int>::iterator it = aTextureNumVector.begin(); it != aTextureNumVector.end(); it++ ) {
iOutput += snprintf(szOutput + iOutput, sizeof(szOutput) - iOutput, "%d ", *it);
}
//std::copy(aTextureNumVector.begin(),aTextureNumVector.end(),std::ostream_iterator<int>(ostr," "));
return Py_BuildValue("iifs", iPatch, iSplat, fSplatRatio, szOutput);
}
PyObject * backgroundGetRenderedGTINum(PyObject * poSelf, PyObject * poArgs)
{
DWORD dwGraphicThingInstanceNum;
DWORD dwCRCNum;
/*CArea::TCRCWithNumberVector & rCRCWithNumberVector = */
CPythonBackground::Instance().GetRenderedGraphicThingInstanceNum(&dwGraphicThingInstanceNum, &dwCRCNum);
/*
std::ostringstream ostr;
std::for_each(rCRCWithNumberVector.begin(),rCRCWithNumberVector.end(),std::ostream_iterator<CArea::TCRCWithNumberVector>(ostr," "));
*/
return Py_BuildValue("ii", dwGraphicThingInstanceNum, dwCRCNum);
}
PyObject * backgroundGetRenderShadowTime(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground& rkBG=CPythonBackground::Instance();
return Py_BuildValue("i", rkBG.GetRenderShadowTime());
}
PyObject * backgroundGetShadowMapcolor(PyObject * poSelf, PyObject * poArgs)
{
float fx;
if (!PyTuple_GetFloat(poArgs, 0, &fx))
return Py_BadArgument();
float fy;
if (!PyTuple_GetFloat(poArgs, 1, &fy))
return Py_BadArgument();
DWORD dwColor = CPythonBackground::Instance().GetShadowMapColor(fx, fy);
return Py_BuildValue("i", dwColor);
}
PyObject * backgroundSetShadowLevel(PyObject * poSelf, PyObject * poArgs)
{
int iLevel;
if (!PyTuple_GetInteger(poArgs, 0, &iLevel))
return Py_BadArgument();
CPythonBackground& rkBG = CPythonBackground::Instance();
rkBG.SetShadowLevel(iLevel);
return Py_BuildNone();
}
PyObject * backgroundSetVisiblePart(PyObject * poSelf, PyObject * poArgs)
{
int ePart;
if (!PyTuple_GetInteger(poArgs, 0, &ePart))
return Py_BadArgument();
int isVisible;
if (!PyTuple_GetInteger(poArgs, 1, &isVisible))
return Py_BadArgument();
if (ePart>=CMapOutdoor::PART_NUM)
return Py_BuildException("ePart(%d)<background.PART_NUM(%d)", ePart, CMapOutdoor::PART_NUM);
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.SetVisiblePart(ePart, isVisible ? true : false);
return Py_BuildNone();
}
PyObject * backgroundSetSpaltLimit(PyObject * poSelf, PyObject * poArgs)
{
int iSplatNum;
if (!PyTuple_GetInteger(poArgs, 0, &iSplatNum))
return Py_BadArgument();
if (iSplatNum<0)
return Py_BuildException("background.SetSplatLimit(iSplatNum(%d)>=0)", iSplatNum);
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.SetSplatLimit(iSplatNum);
return Py_BuildNone();
}
PyObject * backgroundSelectViewDistanceNum(PyObject * poSelf, PyObject * poArgs)
{
int iNum;
if (!PyTuple_GetInteger(poArgs, 0, &iNum))
return Py_BadArgument();
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.SelectViewDistanceNum(iNum);
return Py_BuildNone();
}
PyObject * backgroundSetViewDistanceSet(PyObject * poSelf, PyObject * poArgs)
{
int iNum;
if (!PyTuple_GetInteger(poArgs, 0, &iNum))
return Py_BadArgument();
float fFarClip;
if (!PyTuple_GetFloat(poArgs, 1, &fFarClip))
return Py_BadArgument();
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.SetViewDistanceSet(iNum, fFarClip);
return Py_BuildNone();
}
PyObject * backgroundGetFarClip(PyObject * poSelf, PyObject * poArgs)
{
float fFarClip = CPythonBackground::Instance().GetFarClip();
return Py_BuildValue("f", fFarClip);
}
PyObject * backgroundGetDistanceSetInfo(PyObject * poSelf, PyObject * poArgs)
{
int iNum;
float fStart, fEnd, fFarClip;
CPythonBackground::Instance().GetDistanceSetInfo(&iNum, &fStart, &fEnd, &fFarClip);
return Py_BuildValue("ifff", iNum, fStart, fEnd, fFarClip);
}
PyObject * backgroundSetBGLoading(PyObject * poSelf, PyObject * poArgs)
{
bool bBGLoading;
if (!PyTuple_GetBoolean(poArgs, 0, &bBGLoading))
return Py_BadArgument();
//CPythonBackground::Instance().BGLoadingEnable(bBGLoading);
return Py_BuildNone();
}
PyObject * backgroundSetRenderSort(PyObject * poSelf, PyObject * poArgs)
{
int eSort;
if (!PyTuple_GetInteger(poArgs, 0, &eSort))
return Py_BadArgument();
CPythonBackground::Instance().SetTerrainRenderSort((CMapOutdoor::ETerrainRenderSort) eSort);
return Py_BuildNone();
}
PyObject * backgroundSetTransparentTree(PyObject * poSelf, PyObject * poArgs)
{
int bTransparent;
if (!PyTuple_GetInteger(poArgs, 0, &bTransparent))
return Py_BadArgument();
CPythonBackground::Instance().SetTransparentTree(bTransparent ? true : false);
return Py_BuildNone();
}
PyObject * backgroundGlobalPositionToLocalPosition(PyObject * poSelf, PyObject * poArgs)
{
int iX;
if (!PyTuple_GetInteger(poArgs, 0, &iX))
return Py_BadArgument();
int iY;
if (!PyTuple_GetInteger(poArgs, 1, &iY))
return Py_BadArgument();
LONG lX=iX;
LONG lY=iY;
CPythonBackground& rkBG=CPythonBackground::Instance();
rkBG.GlobalPositionToLocalPosition(lX, lY);
return Py_BuildValue("ii", lX, lY);
}
PyObject * backgroundGlobalPositionToMapInfo(PyObject * poSelf, PyObject * poArgs)
{
int iX;
if (!PyTuple_GetInteger(poArgs, 0, &iX))
return Py_BadArgument();
int iY;
if (!PyTuple_GetInteger(poArgs, 1, &iY))
return Py_BadArgument();
CPythonBackground& rkBG=CPythonBackground::Instance();
CPythonBackground::TMapInfo* pkMapInfo=rkBG.GlobalPositionToMapInfo(iX, iY);
if (pkMapInfo)
return Py_BuildValue("sii", pkMapInfo->m_strName.c_str(), pkMapInfo->m_dwBaseX, pkMapInfo->m_dwBaseY);
else
return Py_BuildValue("sii", "", 0, 0);
}
PyObject * backgroundWarpTest(PyObject * poSelf, PyObject * poArgs)
{
int iX;
if (!PyTuple_GetInteger(poArgs, 0, &iX))
return Py_BadArgument();
int iY;
if (!PyTuple_GetInteger(poArgs, 1, &iY))
return Py_BadArgument();
CPythonBackground::Instance().Warp((DWORD)iX * 100 , (DWORD)iY * 100);
return Py_BuildNone();
}
PyObject * backgroundSetXMasTree(PyObject * poSelf, PyObject * poArgs)
{
int iGrade;
if (!PyTuple_GetInteger(poArgs, 0, &iGrade))
return Py_BadArgument();
CPythonBackground::Instance().SetXMaxTree(iGrade);
return Py_BuildNone();
}
PyObject * backgroundRegisterDungeonMapName(PyObject * poSelf, PyObject * poArgs)
{
char * szName;
if (!PyTuple_GetString(poArgs, 0, &szName))
return Py_BadArgument();
CPythonBackground::Instance().RegisterDungeonMapName(szName);
return Py_BuildNone();
}
PyObject * backgroundVisibleGuildArea(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().VisibleGuildArea();
return Py_BuildNone();
}
PyObject * backgroundDisableGuildArea(PyObject * poSelf, PyObject * poArgs)
{
CPythonBackground::Instance().DisableGuildArea();
return Py_BuildNone();
}
void initBackground()
{
static PyMethodDef s_methods[] =
{
{ "IsSoftwareTiling", backgroundIsSoftwareTiling, METH_VARARGS },
{ "EnableSoftwareTiling", backgroundEnableSoftwareTiling, METH_VARARGS },
{ "EnableSnow", backgroundEnableSnow, METH_VARARGS },
{ "GlobalPositionToLocalPosition", backgroundGlobalPositionToLocalPosition, METH_VARARGS },
{ "GlobalPositionToMapInfo", backgroundGlobalPositionToMapInfo, METH_VARARGS },
{ "GetRenderShadowTime", backgroundGetRenderShadowTime, METH_VARARGS },
{ "LoadMap", backgroundLoadMap, METH_VARARGS },
{ "Destroy", backgroundDestroy, METH_VARARGS },
{ "RegisterEnvironmentData", backgroundRegisterEnvironmentData, METH_VARARGS },
{ "SetEnvironmentData", backgroundSetEnvironmentData, METH_VARARGS },
{ "GetCurrentMapName", backgroundGetCurrentMapName, METH_VARARGS },
{ "GetPickingPoint", backgroundGetPickingPoint, METH_VARARGS },
{ "BeginEnvironment", backgroundBeginEnvironment, METH_VARARGS },
{ "EndEnvironment", backgroundEndEnvironemt, METH_VARARGS },
{ "SetCharacterDirLight", backgroundSetCharacterDirLight, METH_VARARGS },
{ "SetBackgroundDirLight", backgroundSetBackgroundDirLight, METH_VARARGS },
{ "Initialize", backgroundInitialize, METH_VARARGS },
{ "Update", backgroundUpdate, METH_VARARGS },
{ "Render", backgroundRender, METH_VARARGS },
{ "RenderPCBlocker", backgroundRenderPCBlocker, METH_VARARGS },
{ "RenderCollision", backgroundRenderCollision, METH_VARARGS },
{ "RenderSky", backgroundRenderSky, METH_VARARGS },
{ "RenderCloud", backgroundRenderCloud, METH_VARARGS },
{ "RenderWater", backgroundRenderWater, METH_VARARGS },
{ "RenderEffect", backgroundRenderEffect, METH_VARARGS },
{ "RenderBeforeLensFlare", backgroundRenderBeforeLensFlare, METH_VARARGS },
{ "RenderAfterLensFlare", backgroundRenderAfterLensFlare, METH_VARARGS },
{ "RenderCharacterShadowToTexture", backgroundRenderCharacterShadowToTexture, METH_VARARGS },
{ "RenderDungeon", backgroundRenderDungeon, METH_VARARGS },
{ "GetHeight", backgroundGetHeight, METH_VARARGS },
{ "SetShadowLevel", backgroundSetShadowLevel, METH_VARARGS },
{ "SetVisiblePart", backgroundSetVisiblePart, METH_VARARGS },
{ "GetShadowMapColor", backgroundGetShadowMapcolor, METH_VARARGS },
{ "SetSplatLimit", backgroundSetSpaltLimit, METH_VARARGS },
{ "GetRenderedSplatNum", backgroundGetRenderedSplatNum, METH_VARARGS },
{ "GetRenderedGraphicThingInstanceNum", backgroundGetRenderedGTINum, METH_VARARGS },
{ "SelectViewDistanceNum", backgroundSelectViewDistanceNum, METH_VARARGS },
{ "SetViewDistanceSet", backgroundSetViewDistanceSet, METH_VARARGS },
{ "GetFarClip", backgroundGetFarClip, METH_VARARGS },
{ "GetDistanceSetInfo", backgroundGetDistanceSetInfo, METH_VARARGS },
{ "SetBGLoading", backgroundSetBGLoading, METH_VARARGS },
{ "SetRenderSort", backgroundSetRenderSort, METH_VARARGS },
{ "SetTransparentTree", backgroundSetTransparentTree, METH_VARARGS },
{ "SetXMasTree", backgroundSetXMasTree, METH_VARARGS },
{ "RegisterDungeonMapName", backgroundRegisterDungeonMapName, METH_VARARGS },
{ "VisibleGuildArea", backgroundVisibleGuildArea, METH_VARARGS },
{ "DisableGuildArea", backgroundDisableGuildArea, METH_VARARGS },
{ "WarpTest", backgroundWarpTest, METH_VARARGS },
{ NULL, NULL, NULL },
};
PyObject * poModule = Py_InitModule("background", s_methods);
PyModule_AddIntConstant(poModule, "PART_SKY", CMapOutdoor::PART_SKY);
PyModule_AddIntConstant(poModule, "PART_TREE", CMapOutdoor::PART_TREE);
PyModule_AddIntConstant(poModule, "PART_CLOUD", CMapOutdoor::PART_CLOUD);
PyModule_AddIntConstant(poModule, "PART_WATER", CMapOutdoor::PART_WATER);
PyModule_AddIntConstant(poModule, "PART_OBJECT", CMapOutdoor::PART_OBJECT);
PyModule_AddIntConstant(poModule, "PART_TERRAIN", CMapOutdoor::PART_TERRAIN);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_DEFAULT", CSkyObject::SKY_RENDER_MODE_DEFAULT);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_DIFFUSE", CSkyObject::SKY_RENDER_MODE_DIFFUSE);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_TEXTURE", CSkyObject::SKY_RENDER_MODE_TEXTURE);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE", CSkyObject::SKY_RENDER_MODE_MODULATE);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE2X", CSkyObject::SKY_RENDER_MODE_MODULATE2X);
PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE4X", CSkyObject::SKY_RENDER_MODE_MODULATE4X);
PyModule_AddIntConstant(poModule, "SHADOW_NONE", CPythonBackground::SHADOW_NONE);
PyModule_AddIntConstant(poModule, "SHADOW_GROUND", CPythonBackground::SHADOW_GROUND);
PyModule_AddIntConstant(poModule, "SHADOW_GROUND_AND_SOLO", CPythonBackground::SHADOW_GROUND_AND_SOLO);
PyModule_AddIntConstant(poModule, "SHADOW_ALL", CPythonBackground::SHADOW_ALL);
PyModule_AddIntConstant(poModule, "SHADOW_ALL_HIGH", CPythonBackground::SHADOW_ALL_HIGH);
PyModule_AddIntConstant(poModule, "SHADOW_ALL_MAX", CPythonBackground::SHADOW_ALL_MAX);
PyModule_AddIntConstant(poModule, "DISTANCE0", CPythonBackground::DISTANCE0);
PyModule_AddIntConstant(poModule, "DISTANCE1", CPythonBackground::DISTANCE1);
PyModule_AddIntConstant(poModule, "DISTANCE2", CPythonBackground::DISTANCE2);
PyModule_AddIntConstant(poModule, "DISTANCE3", CPythonBackground::DISTANCE3);
PyModule_AddIntConstant(poModule, "DISTANCE4", CPythonBackground::DISTANCE4);
PyModule_AddIntConstant(poModule, "DISTANCE_SORT", CMapOutdoor::DISTANCE_SORT);
PyModule_AddIntConstant(poModule, "TEXTURE_SORT", CMapOutdoor::TEXTURE_SORT);
}
@@ -58,6 +58,7 @@ void initnet();
void initeffect();
void initfly();
void initskill();
void initBackground();
void initServerStateChecker();
extern const std::string& ApplicationStringTable_GetString(DWORD dwID);
+74 -4
View File
@@ -662,10 +662,71 @@ typedef struct _D3DCAPS8
// upcasts 40250 relies on (texture -> base texture) compile; of the resources only the buffers carry
// methods (Lock/Unlock, platform/EterLib/CpuBuffer.h).
struct IDirect3D8;
struct IDirect3DResource8 {};
struct IDirect3DBaseTexture8 : IDirect3DResource8 {};
struct IDirect3DTexture8 : IDirect3DBaseTexture8 {};
struct IDirect3DSurface8 : IDirect3DResource8 {};
typedef enum _D3DRESOURCETYPE
{
D3DRTYPE_SURFACE = 1,
D3DRTYPE_VOLUME = 2,
D3DRTYPE_TEXTURE = 3,
D3DRTYPE_VOLUMETEXTURE = 4,
D3DRTYPE_CUBETEXTURE = 5,
D3DRTYPE_VERTEXBUFFER = 6,
D3DRTYPE_INDEXBUFFER = 7,
D3DRTYPE_FORCE_DWORD = 0x7fffffff
} D3DRESOURCETYPE;
typedef struct _D3DLOCKED_RECT
{
INT Pitch;
void* pBits;
} D3DLOCKED_RECT;
typedef struct _D3DSURFACE_DESC
{
D3DFORMAT Format;
D3DRESOURCETYPE Type;
DWORD Usage;
D3DPOOL Pool;
UINT Size;
D3DMULTISAMPLE_TYPE MultiSampleType;
UINT Width;
UINT Height;
} D3DSURFACE_DESC;
typedef struct _D3DRECT
{
LONG x1, y1, x2, y2;
} D3DRECT;
#define D3DCLEAR_TARGET 0x00000001l
#define D3DCLEAR_ZBUFFER 0x00000002l
#define D3DCLEAR_STENCIL 0x00000004l
// PORT: the resource interfaces carry virtual defaults so the platform's texture handles
// (GrpImageTexture's MemoryTexture/FileTexture, owned by their own registries) need not implement
// them; device-created resources (RecordingDevice CreateTexture/...) override AddRef/Release.
struct IDirect3DResource8
{
virtual ~IDirect3DResource8() = default;
virtual ULONG AddRef() { return 1; }
virtual ULONG Release() { return 1; }
};
struct IDirect3DSurface8 : IDirect3DResource8
{
virtual HRESULT GetDesc(D3DSURFACE_DESC* pDesc) { return E_FAIL; }
virtual HRESULT LockRect(D3DLOCKED_RECT* pLockedRect, const RECT* pRect, DWORD Flags) { return E_FAIL; }
virtual HRESULT UnlockRect() { return E_FAIL; }
};
struct IDirect3DBaseTexture8 : IDirect3DResource8
{
virtual DWORD GetLevelCount() { return 1; }
};
struct IDirect3DTexture8 : IDirect3DBaseTexture8
{
virtual HRESULT GetLevelDesc(UINT Level, D3DSURFACE_DESC* pDesc) { return E_FAIL; }
virtual HRESULT GetSurfaceLevel(UINT Level, IDirect3DSurface8** ppSurfaceLevel) { return E_FAIL; }
virtual HRESULT LockRect(UINT Level, D3DLOCKED_RECT* pLockedRect, const RECT* pRect, DWORD Flags) { return E_FAIL; }
virtual HRESULT UnlockRect(UINT Level) { return E_FAIL; }
};
struct IDirect3DVertexBuffer8 : IDirect3DResource8
{
virtual ~IDirect3DVertexBuffer8() = default;
@@ -695,6 +756,15 @@ struct IDirect3DDevice8
virtual HRESULT GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) = 0;
virtual HRESULT SetMaterial(const D3DMATERIAL8* pMaterial) = 0;
virtual HRESULT SetLight(DWORD Index, const D3DLIGHT8* pLight) = 0;
virtual HRESULT LightEnable(DWORD Index, BOOL Enable) = 0;
virtual HRESULT CreateTexture(UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) = 0;
virtual HRESULT CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) = 0;
virtual HRESULT CreateIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) = 0;
virtual HRESULT CreateDepthStencilSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) = 0;
virtual HRESULT GetRenderTarget(IDirect3DSurface8** ppRenderTarget) = 0;
virtual HRESULT GetDepthStencilSurface(IDirect3DSurface8** ppZStencilSurface) = 0;
virtual HRESULT SetRenderTarget(IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) = 0;
virtual HRESULT Clear(DWORD Count, const D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) = 0;
virtual HRESULT SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) = 0;
virtual HRESULT SetTexture(DWORD Stage, IDirect3DBaseTexture8* pTexture) = 0;
virtual HRESULT SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) = 0;
+10
View File
@@ -411,6 +411,16 @@ inline FLOAT D3DXPlaneDotCoord(const D3DXPLANE* pP, const D3DXVECTOR3* pV)
{
return pP->a * pV->x + pP->b * pV->y + pP->c * pV->z + pP->d;
}
inline D3DXPLANE* D3DXPlaneNormalize(D3DXPLANE* pOut, const D3DXPLANE* pP)
{
const FLOAT length = sqrtf(pP->a * pP->a + pP->b * pP->b + pP->c * pP->c);
const FLOAT inv = length > 0.0f ? 1.0f / length : 0.0f;
pOut->a = pP->a * inv;
pOut->b = pP->b * inv;
pOut->c = pP->c * inv;
pOut->d = pP->d * inv;
return pOut;
}
// --- ID3DXMatrixStack --- (the D3DX8 interface, as a plain class: the Local variants pre-multiply)
struct ID3DXMatrixStack
+28
View File
@@ -65,9 +65,37 @@ void fill_find_data(const std::string& path, WIN32_FIND_DATA* data)
const size_t slash = path.find_last_of('/');
const std::string name = path.substr(slash == std::string::npos ? 0 : slash + 1);
std::snprintf(data->cFileName, sizeof(data->cFileName), "%s", name.c_str());
struct stat st{};
data->dwFileAttributes = stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode) ? FILE_ATTRIBUTE_DIRECTORY
: FILE_ATTRIBUTE_NORMAL;
}
}
BOOL CopyFile(LPCSTR existing_path, LPCSTR new_path, BOOL fail_if_exists)
{
if (!existing_path || !new_path)
return FALSE;
if (fail_if_exists && _access(new_path, 0) == 0)
return FALSE;
FILE* in = std::fopen(existing_path, "rb");
if (!in)
return FALSE;
FILE* out = std::fopen(new_path, "wb");
if (!out)
{
std::fclose(in);
return FALSE;
}
char buffer[65536];
size_t n;
bool ok = true;
while ((n = std::fread(buffer, 1, sizeof(buffer), in)) > 0)
ok = ok && std::fwrite(buffer, 1, n, out) == n;
std::fclose(in);
ok = std::fclose(out) == 0 && ok;
return ok ? TRUE : FALSE;
}
HANDLE FindFirstFile(const char* pattern, WIN32_FIND_DATA* data)
{
if (!pattern || !data)
+6 -1
View File
@@ -61,8 +61,11 @@ int _snprintf(char* buf, size_t count, const char* fmt, ...)
// the MSVC modes 0 (exists), 2 (write), 4 (read), 6 (read/write).
BOOL CreateDirectory(LPCSTR path, void* security_attributes);
BOOL DeleteFile(LPCSTR path);
BOOL CopyFile(LPCSTR existing_path, LPCSTR new_path, BOOL fail_if_exists);
int _access(const char* path, int mode);
struct WIN32_FIND_DATA { char cFileName[MAX_PATH]; };
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
#define FILE_ATTRIBUTE_NORMAL 0x00000080
struct WIN32_FIND_DATA { DWORD dwFileAttributes; char cFileName[MAX_PATH]; };
#define INVALID_HANDLE_VALUE (reinterpret_cast<HANDLE>(static_cast<intptr_t>(-1)))
HANDLE FindFirstFile(const char* pattern, WIN32_FIND_DATA* data);
BOOL FindNextFile(HANDLE handle, WIN32_FIND_DATA* data);
@@ -72,6 +75,8 @@ void Sleep(DWORD milliseconds);
// winmm `timeGetTime`: milliseconds since system start, wrapping at 2^32.
DWORD timeGetTime();
DWORD GetTickCount();
// winbase.h: #define GetCurrentTime() GetTickCount()
#define GetCurrentTime() GetTickCount()
// Recursive, like the Win32 critical section. Storage holds a std::recursive_mutex.
struct CRITICAL_SECTION
+7
View File
@@ -99,6 +99,13 @@ Array Metin2PythonHost::ui_render_commands() {
item["uv"] = PackedVector2Array({Vector2(command.su, command.sv), Vector2(command.eu, command.sv),
Vector2(command.su, command.ev), Vector2(command.eu, command.ev)});
item["blend"] = command.blend;
if (!command.mask.empty()) {
item["mask"] = String::utf8(command.mask.c_str());
PackedVector2Array mask_uv;
for (int i = 0; i < 4; ++i)
mask_uv.push_back(Vector2(command.mu[i], command.mv[i]));
item["mask_uv"] = mask_uv;
}
}
out.push_back(item);
}
+8 -5
View File
@@ -542,13 +542,16 @@ int main(int argc, char** argv)
"assert _icon != 0\n"
"skill.DeleteIconInstance(_icon)"));
// miniMap module (PythonMiniMapModule.cpp): uiminimap.MiniMap created and showed it. CMapOutdoor is not
// ported, so CMapManager::IsMapOutdoor() is false and the atlas reports "not loaded" as 40250 does off an
// outdoor map.
CHECK(py("import miniMap\n"
// miniMap module (PythonMiniMapModule.cpp): uiminimap.MiniMap created and showed it. The warp loaded the
// outdoor map through CPythonBackground::Warp -> CMapManager::LoadMap -> CMapOutdoor, so the map is outdoor
// and CPythonMiniMap::LoadAtlas found the map's atlas image (its size is the atlas bitmap's).
CHECK(CPythonBackground::Instance().IsMapOutdoor());
CHECK(py("import miniMap, background\n"
"assert miniMap.isShow()\n"
"(bGet, x, y) = miniMap.GetAtlasSize()\n"
"assert not bGet, (bGet, x, y)"));
"assert bGet and x > 0 and y > 0, (bGet, x, y)\n"
"print 'port_login_flow_test: atlas %dx%d' % (x, y)\n"
"assert background.GetCurrentMapName() != '', background.GetCurrentMapName()"));
// Ground items (CPythonItem): the fake server put vnum 19 next to the actor at entergame (GC_ITEM_GROUND_ADD
// + GC_ITEM_OWNERSHIP). player.PickCloseItem finds it within __GetPickableDistance, sends CG_ITEM_PICKUP,