Code Restructuring to make mega-glest more standard

This commit is contained in:
Mark Vejvoda
2010-03-12 05:20:53 +00:00
parent 7cb4f99ec4
commit 43c3f2457e
399 changed files with 0 additions and 73357 deletions

View File

@@ -1,55 +0,0 @@
#include "buffer.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class VertexBuffer
// =====================================================
VertexBuffer::VertexBuffer(){
positionPointer= NULL;
normalPointer= NULL;
for(int i= 0; i<texCoordCount; ++i){
texCoordPointers[i]= NULL;
texCoordCoordCounts[i]= -1;
}
for(int i= 0; i<attribCount; ++i){
attribPointers[i]= NULL;
attribCoordCounts[i]= -1;
}
}
void VertexBuffer::setPositionPointer(void *pointer){
positionPointer= pointer;
}
void VertexBuffer::setNormalPointer(void *pointer){
normalPointer= pointer;
}
void VertexBuffer::setTexCoordPointer(void *pointer, int texCoordIndex, int coordCount){
texCoordPointers[texCoordIndex]= pointer;
texCoordCoordCounts[texCoordIndex]= coordCount;
}
void VertexBuffer::setAttribPointer(void *pointer, int attribIndex, int coordCount, const string &name){
attribPointers[attribIndex]= pointer;
attribCoordCounts[attribIndex]= coordCount;
attribNames[attribIndex]= name;
}
// =====================================================
// class IndexBuffer
// =====================================================
IndexBuffer::IndexBuffer(){
indexPointer= NULL;
}
void IndexBuffer::setIndexPointer(void *pointer){
indexPointer= pointer;
}
}}//end namespace

View File

@@ -1,53 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "camera.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class Camera
// =====================================================
Camera::Camera(){
position= Vec3f(0.0f);
}
void Camera::moveLocalX(float amount){
position= position + orientation.getLocalXAxis()*amount;
}
void Camera::moveLocalY(float amount){
position= position + orientation.getLocalYAxis()*amount;
}
void Camera::moveLocalZ(float amount){
position= position + orientation.getLocalZAxis()*amount;
}
void Camera::addYaw(float amount){
Quaternion q(EulerAngles(0, amount, 0));
orientation*= q;
}
void Camera::addPitch(float amount){
Quaternion q(EulerAngles(amount, 0, 0));
orientation*= q;
}
void Camera::addRoll(float amount){
Quaternion q(EulerAngles(0, 0, amount));
orientation*= q;
}
}}//end namespace

View File

@@ -1,28 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "context.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class Context
// =====================================================
Context::Context(){
colorBits= 32;
depthBits= 24;
stencilBits= 0;
}
}}//end namespace

View File

@@ -1,73 +0,0 @@
#include "context_d3d9.h"
#include <cassert>
#include <stdexcept>
#include "d3d9_util.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Graphics{ namespace D3d9{
// ===============================================
// class ContextD3d9
// ===============================================
ContextD3d9::ContextD3d9(){
windowed= true;
hardware= true;
}
void ContextD3d9::init(){
//create object
d3dObject= Direct3DCreate9(D3D_SDK_VERSION);
if(d3dObject==NULL){
throw runtime_error("Direct3DCreate9==NULL");
}
//present parameters
memset(&d3dPresentParameters, 0, sizeof(d3dPresentParameters));
d3dPresentParameters.Windowed = TRUE;
d3dPresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dPresentParameters.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dPresentParameters.EnableAutoDepthStencil= TRUE;
d3dPresentParameters.AutoDepthStencilFormat= D3DFMT_D24X8;
d3dPresentParameters.PresentationInterval= D3DPRESENT_INTERVAL_IMMEDIATE;
//create device
D3DCALL(d3dObject->CreateDevice(
D3DADAPTER_DEFAULT,
hardware? D3DDEVTYPE_HAL: D3DDEVTYPE_REF,
GetActiveWindow(),
hardware? D3DCREATE_HARDWARE_VERTEXPROCESSING: D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dPresentParameters,
&d3dDevice));
//get caps
D3DCALL(d3dDevice->GetDeviceCaps(&caps));
}
void ContextD3d9::end(){
D3DCALL(d3dDevice->Release());
D3DCALL(d3dObject->Release());
}
void ContextD3d9::makeCurrent(){
}
void ContextD3d9::swapBuffers(){
D3DCALL(d3dDevice->Present(NULL, NULL, NULL, NULL));
}
void ContextD3d9::reset(){
d3dPresentParameters.BackBufferWidth= 0;
d3dPresentParameters.BackBufferHeight= 0;
D3DCALL(d3dDevice->Reset(&d3dPresentParameters));
}
}}}//end namespace

View File

@@ -1,21 +0,0 @@
#include "d3d9_util.h"
namespace Shared{ namespace Graphics{ namespace D3d9{
string d3dErrorToStr(HRESULT result){
switch(result){
case D3D_OK: return "D3D_OK";
case D3DERR_DEVICELOST: return "D3DERR_DEVICELOST";
case D3DERR_DEVICENOTRESET: return "D3DERR_DEVICENOTRESET";
case D3DERR_DRIVERINTERNALERROR: return "D3DERR_DRIVERINTERNALERROR";
case D3DERR_INVALIDCALL: return "D3DERR_INVALIDCALL";
case D3DERR_MOREDATA: return "D3DERR_MOREDATA";
case D3DERR_NOTFOUND: return "D3DERR_NOTFOUND";
case D3DERR_OUTOFVIDEOMEMORY: return "D3DERR_OUTOFVIDEOMEMORY";
case E_OUTOFMEMORY: return "E_OUTOFMEMORY";
default:
return "Unkown D3D error";
}
}
}}}//end namespace

View File

@@ -1,38 +0,0 @@
#include "font_d3d9.h"
#include <stdexcept>
#include <d3d9.h>
#include "graphics_interface.h"
#include "context_d3d9.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Graphics{ namespace D3d9{
// ===============================================
// class Font2DD3d9
// ===============================================
void Font2DD3d9::init(){
GraphicsInterface &gi= GraphicsInterface::getInstance();
IDirect3DDevice9 *d3dDevice= static_cast<ContextD3d9*>(gi.getCurrentContext())->getD3dDevice();
HFONT hFont=CreateFont(size, 0, 0, 0, width, 0, FALSE, FALSE, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DRAFT_QUALITY, DEFAULT_PITCH, type.c_str());
HRESULT result= D3DXCreateFont(d3dDevice, hFont, &d3dFont);
if(result!=D3D_OK){
throw runtime_error("FontD3d9::init() -> Can't create D3D font");
}
DeleteObject(hFont);
}
void Font2DD3d9::end(){
d3dFont->Release();
}
}}}//end namespace

View File

@@ -1,173 +0,0 @@
#include "model_renderer_d3d9.h"
#include <cassert>
#include "graphics_interface.h"
#include "context_d3d9.h"
#include "texture_d3d9.h"
#include "interpolation.h"
#include "d3d9_util.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{ namespace D3d9{
// ===============================================
// class ModelRendererD3d9
// ===============================================
D3DVERTEXELEMENT9 d3dVertexElementsPNT[]=
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
D3DVERTEXELEMENT9 d3dVertexElementsPNTT[]=
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{0, 32, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
D3DDECL_END()
};
ModelRendererD3d9::ModelRendererD3d9(){
rendering= false;
GraphicsInterface &gi= GraphicsInterface::getInstance();
d3dDevice= static_cast<ContextD3d9*>(gi.getCurrentContext())->getD3dDevice();
bufferPointCount= 0;
bufferIndexCount= 0;
D3DCALL(d3dDevice->CreateVertexDeclaration(d3dVertexElementsPNT, &d3dVertexDeclarationPNT));
D3DCALL(d3dDevice->CreateVertexDeclaration(d3dVertexElementsPNTT, &d3dVertexDeclarationPNTT));
readyBuffers(defBufferPointCount, defBufferIndexCount);
}
ModelRendererD3d9::~ModelRendererD3d9(){
d3dVertexBuffer->Release();
}
void ModelRendererD3d9::begin(bool renderNormals, bool renderTextures, bool renderColors){
rendering= true;
}
void ModelRendererD3d9::end(){
rendering= false;
}
void ModelRendererD3d9::render(const Model *model){
assert(rendering);
//render every mesh
for(uint32 i=0; i<model->getMeshCount(); ++i){
renderMesh(model->getMesh(i));
}
}
void ModelRendererD3d9::renderNormalsOnly(const Model *model){
}
// ====================== Private ===============================================
void ModelRendererD3d9::renderMesh(const Mesh *mesh){
CustomVertexPNTT *vertices;
uint32 *indices;
readyBuffers(mesh->getVertexCount(), mesh->getIndexCount());
//lock vertex buffer
D3DCALL(d3dVertexBuffer->Lock(0, mesh->getVertexCount()*sizeof(CustomVertexPNTT), (void**) &vertices, 0));
//copy data vertex buffer
const InterpolationData *interpolationData= mesh->getInterpolationData();
for(int i=0; i<mesh->getVertexCount(); ++i){
vertices[i].vertex= interpolationData->getVertices()[i];
vertices[i].normal= interpolationData->getNormals()[i];
Vec2f texCoord= mesh->getTexCoords()[i];
vertices[i].texCoord= Vec2f(texCoord.x, texCoord.y);
}
if(mesh->getTangents()!=NULL){
for(int i=0; i<mesh->getVertexCount(); ++i){
vertices[i].tangent= mesh->getTangents()[i];
}
}
//unlock vertex buffer
D3DCALL(d3dVertexBuffer->Unlock());
//lock index buffer
D3DCALL(d3dIndexBuffer->Lock(0, mesh->getIndexCount()*sizeof(uint32), (void**) &indices, 0));
//copy data
for(int i=0; i<mesh->getIndexCount(); i+=3){
indices[i]= mesh->getIndices()[i];
indices[i+1]= mesh->getIndices()[i+2];
indices[i+2]= mesh->getIndices()[i+1];
}
//unlock
D3DCALL(d3dIndexBuffer->Unlock());
//set stream data
D3DCALL(d3dDevice->SetStreamSource(0, d3dVertexBuffer, 0, sizeof(CustomVertexPNTT)));
D3DCALL(d3dDevice->SetVertexDeclaration(mesh->getTangents()==NULL? d3dVertexDeclarationPNT: d3dVertexDeclarationPNTT));
D3DCALL(d3dDevice->SetIndices(d3dIndexBuffer));
//set textures
int textureUnit= 0;
for(int i=0; i<meshTextureCount; ++i){
if(mesh->getTexture(i)!=NULL){
const Texture2DD3d9* texture2DD3d9= static_cast<const Texture2DD3d9*>(mesh->getTexture(i));
D3DCALL(d3dDevice->SetTexture(textureUnit, texture2DD3d9->getD3dTexture()));
++textureUnit;
}
}
//render
D3DCALL(d3dDevice->BeginScene());
D3DCALL(d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mesh->getVertexCount(), 0, mesh->getIndexCount()/3));
D3DCALL(d3dDevice->EndScene());
//reset textures
for(int i=0; i<meshTextureCount; ++i){
D3DCALL(d3dDevice->SetTexture(i, NULL));
}
}
void ModelRendererD3d9::readyBuffers(int newPointCount, int newIndexCount){
//vertices, if the buffer is to small allocate a new buffer
if(bufferPointCount<newPointCount){
bufferPointCount= newPointCount;
D3DCALL(d3dDevice->CreateVertexBuffer(
bufferPointCount*sizeof(CustomVertexPNTT),
0,
0,
D3DPOOL_MANAGED,
&d3dVertexBuffer,
NULL));
}
//indices
if(bufferIndexCount<newIndexCount){
bufferIndexCount= newIndexCount;
D3DCALL(d3dDevice->CreateIndexBuffer(
bufferIndexCount*sizeof(uint32),
0,
D3DFMT_INDEX32,
D3DPOOL_MANAGED,
&d3dIndexBuffer,
NULL));
}
}
}}}//end namespace

View File

@@ -1,253 +0,0 @@
#include "shader_d3d9.h"
#include <fstream>
#include "graphics_interface.h"
#include "context_d3d9.h"
#include "texture_d3d9.h"
#include "d3d9_util.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Graphics{ namespace D3d9{
// ===============================================
// class ShaderD3d9
// ===============================================
ShaderProgramD3d9::ShaderProgramD3d9(){
GraphicsInterface &gi= GraphicsInterface::getInstance();
d3dDevice= static_cast<ContextD3d9*>(gi.getCurrentContext())->getD3dDevice();
vertexShader= NULL;
pixelShader= NULL;
}
void ShaderProgramD3d9::attach(VertexShader *vs, FragmentShader *fs){
vertexShader= static_cast<VertexShaderD3d9*>(vs);
pixelShader= static_cast<PixelShaderD3d9*>(fs);
}
bool ShaderProgramD3d9::link(string &messages){
d3dVsConstantTable= vertexShader->getD3dConstantTable();
d3dPsConstantTable= pixelShader->getD3dConstantTable();
return true;
}
void ShaderProgramD3d9::activate(){
d3dDevice->SetVertexShader(vertexShader->getD3dVertexShader());
d3dDevice->SetPixelShader(pixelShader->getD3dPixelShader());
}
void ShaderProgramD3d9::setUniform(const string &name, int value){
D3DXHANDLE vsHandle= d3dVsConstantTable->GetConstantByName(NULL, name.c_str());
D3DXHANDLE psHandle= d3dPsConstantTable->GetConstantByName(NULL, name.c_str());
HRESULT vsResult= d3dVsConstantTable->SetInt(d3dDevice, vsHandle, value);
HRESULT psResult= d3dPsConstantTable->SetInt(d3dDevice, psHandle, value);
if(vsResult!=D3D_OK && psResult!=D3D_OK){
throw runtime_error("Error setting shader uniform: "+string(name));
}
}
void ShaderProgramD3d9::setUniform(const string &name, float value){
D3DXHANDLE vsHandle= d3dVsConstantTable->GetConstantByName(NULL, name.c_str());
D3DXHANDLE psHandle= d3dPsConstantTable->GetConstantByName(NULL, name.c_str());
HRESULT vsResult= d3dVsConstantTable->SetFloat(d3dDevice, vsHandle, value);
HRESULT psResult= d3dPsConstantTable->SetFloat(d3dDevice, psHandle, value);
if(vsResult!=D3D_OK && psResult!=D3D_OK){
throw runtime_error("Error setting shader uniform: "+string(name));
}
}
void ShaderProgramD3d9::setUniform(const string &name, const Vec2f &value){
setUniform(name, Vec4f(value.x, value.y, 0.0f, 0.0f));
}
void ShaderProgramD3d9::setUniform(const string &name, const Vec3f &value){
setUniform(name, Vec4f(value.x, value.y, value.z, 0.0f));
}
void ShaderProgramD3d9::setUniform(const string &name, const Vec4f &value){
D3DXVECTOR4 v;
memcpy(&v, &value, sizeof(float)*4);
D3DXHANDLE vsHandle= d3dVsConstantTable->GetConstantByName(NULL, name.c_str());
D3DXHANDLE psHandle= d3dPsConstantTable->GetConstantByName(NULL, name.c_str());
HRESULT vsResult= d3dVsConstantTable->SetVector(d3dDevice, vsHandle, &v);
HRESULT psResult= d3dPsConstantTable->SetVector(d3dDevice, psHandle, &v);
if(vsResult!=D3D_OK && psResult!=D3D_OK){
throw runtime_error("Error setting shader uniform: "+string(name));
}
}
void ShaderProgramD3d9::setUniform(const string &name, const Matrix3f &value){
throw runtime_error("Not implemented");
}
void ShaderProgramD3d9::setUniform(const string &name, const Matrix4f &value){
D3DXMATRIX m;
memcpy(&m, &value, sizeof(float)*16);
D3DXHANDLE vsHandle= d3dVsConstantTable->GetConstantByName(NULL, name.c_str());
D3DXHANDLE psHandle= d3dPsConstantTable->GetConstantByName(NULL, name.c_str());
HRESULT vsResult= d3dVsConstantTable->SetMatrix(d3dDevice, vsHandle, &m);
HRESULT psResult= d3dPsConstantTable->SetMatrix(d3dDevice, psHandle, &m);
if(vsResult!=D3D_OK && psResult!=D3D_OK){
throw runtime_error("Error setting shader uniform: "+string(name));
}
}
/*void ShaderD3d9::setUniform(const string &name, const Texture *value){
D3DXHANDLE handle= d3dConstantTable->GetConstantByName(NULL, name);
D3DXCONSTANT_DESC d3dDesc;
UINT i=1;
IDirect3DTexture9 *d3dTexture= static_cast<const Texture2DD3d9*>(value)->getD3dTexture();
HRESULT result= d3dConstantTable->GetConstantDesc(handle, &d3dDesc, &i);
if(result==D3D_OK)
d3dDevice->SetTexture(d3dDesc.RegisterIndex, d3dTexture);
else
throw runtime_error("Error setting shader uniform sampler: "+string(name));
}
bool ShaderD3d9::isUniform(char *name){
D3DXCONSTANT_DESC d3dDesc;
UINT i=1;
D3DXHANDLE handle= d3dConstantTable->GetConstantByName(NULL, name);
HRESULT result= d3dConstantTable->GetConstantDesc(handle, &d3dDesc, &i);
return result==D3D_OK;
}*/
// ===============================================
// class ShaderD3d9
// ===============================================
ShaderD3d9::ShaderD3d9(){
GraphicsInterface &gi= GraphicsInterface::getInstance();
d3dDevice= static_cast<ContextD3d9*>(gi.getCurrentContext())->getD3dDevice();
d3dConstantTable= NULL;
}
void ShaderD3d9::end(){
if(d3dConstantTable!=NULL){
d3dConstantTable->Release();
d3dConstantTable= NULL;
}
}
void ShaderD3d9::load(const string &path){
source.load(path);
}
// ===============================================
// class VertexShaderD3d9
// ===============================================
VertexShaderD3d9::VertexShaderD3d9(){
target= "vs_2_0";
d3dVertexShader= NULL;
}
void VertexShaderD3d9::end(){
ShaderD3d9::end();
if(d3dVertexShader!=NULL){
d3dVertexShader->Release();
d3dVertexShader= NULL;
}
}
bool VertexShaderD3d9::compile(string &messages){
//compile shader
ID3DXBuffer *code= NULL;
ID3DXBuffer *errors= NULL;
HRESULT result= D3DXCompileShader(
source.getCode().c_str(), source.getCode().size(), NULL, NULL,
"main", target.c_str(), 0, &code, &errors,
&d3dConstantTable);
if(errors!=NULL){
messages+= reinterpret_cast<char*>(errors->GetBufferPointer());
}
if(FAILED(result)){
return false;
}
//create shader
D3DCALL(d3dDevice->CreateVertexShader((DWORD*) code->GetBufferPointer(), &d3dVertexShader));
//release
if(code!=NULL){
code->Release();
}
if(errors!=NULL){
errors->Release();
}
//set defaults
if(d3dConstantTable!=NULL){
d3dConstantTable->SetDefaults(d3dDevice);
}
return true;
}
// ===============================================
// class PixelShaderD3d9
// ===============================================
PixelShaderD3d9::PixelShaderD3d9(){
target= "ps_2_0";
d3dPixelShader= NULL;
}
void PixelShaderD3d9::end(){
ShaderD3d9::end();
if(d3dPixelShader!=NULL){
d3dPixelShader->Release();
d3dPixelShader= NULL;
}
}
bool PixelShaderD3d9::compile(string &messages){
messages+= "Compiling shader: " + source.getPathInfo() + "\n";
//compile shader
ID3DXBuffer *code= NULL;
ID3DXBuffer *errors= NULL;
HRESULT result= D3DXCompileShader(
source.getCode().c_str(), source.getCode().size(), NULL, NULL,
"main", target.c_str(), 0, &code, &errors,
&d3dConstantTable);
if(errors!=NULL){
messages+= reinterpret_cast<char*>(errors->GetBufferPointer());
}
if(FAILED(result)){
return false;
}
//create shader
D3DCALL(d3dDevice->CreatePixelShader((DWORD*) code->GetBufferPointer(), &d3dPixelShader));
//release
if(code!=NULL){
code->Release();
}
if(errors!=NULL){
errors->Release();
}
//set defaults
if(d3dConstantTable!=NULL){
d3dConstantTable->SetDefaults(d3dDevice);
}
return true;
}
}}}//end namespace

View File

@@ -1,40 +0,0 @@
#include "text_renderer_d3d9.h"
#include <d3d9.h>
#include <d3d9types.h>
#include "font_d3d9.h"
#include "d3d9_util.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{ namespace D3d9{
// ===============================================
// class TextRenderer2DD3d9
// ===============================================
void TextRenderer2DD3d9::begin(const Font2D *font){
this->font= font;
this->color= Vec4f(1.0f);
}
void TextRenderer2DD3d9::render(const string &text, int x, int y, bool centered){
RECT rect;
rect.bottom= y;
rect.left= x;
rect.top= y;
rect.right= x;
D3DCOLOR d3dColor= D3DCOLOR_ARGB(
static_cast<int>(color.w*255),
static_cast<int>(color.x*255),
static_cast<int>(color.y*255),
static_cast<int>(color.z*255));
static_cast<const Font2DD3d9*>(font)->getD3dFont()->DrawText(text.c_str(), -1, &rect, DT_NOCLIP, d3dColor);
}
void TextRenderer2DD3d9::end(){
}
}}}//end namespace

View File

@@ -1,192 +0,0 @@
#include "texture_d3d9.h"
#include <stdexcept>
#include <cassert>
#include "graphics_interface.h"
#include "context_d3d9.h"
#include "d3d9_util.h"
#include "leak_dumper.h"
using namespace std;
using namespace Shared::Graphics;
namespace Shared{ namespace Graphics{ namespace D3d9{
// ===============================================
// class Texture2DD3d9
// ===============================================
D3DFORMAT toFormatD3d(Texture::Format format, int components){
switch(format){
case Texture::fAuto:
switch(components){
case 1:
return D3DFMT_L8;
case 3:
return D3DFMT_X8R8G8B8;
case 4:
return D3DFMT_A8R8G8B8;
default:
assert(false);
return D3DFMT_A8R8G8B8;
}
break;
case Texture::fLuminance:
return D3DFMT_L8;
case Texture::fAlpha:
return D3DFMT_A8;
case Texture::fRgb:
return D3DFMT_X8R8G8B8;
case Texture::fRgba:
return D3DFMT_A8R8G8B8;
default:
assert(false);
return D3DFMT_A8R8G8B8;
}
}
void fillPixels(uint8 *texturePixels, const Pixmap2D *pixmap){
for(int i=0; i<pixmap->getW(); ++i){
for(int j=0; j<pixmap->getH(); ++j){
int k= j*pixmap->getW()+i;
Vec4<uint8> pixel;
pixmap->getPixel(i, j, pixel.ptr());
switch(pixmap->getComponents()){
case 1:
texturePixels[k]= pixel.x;
break;
case 3:
texturePixels[k*4]= pixel.z;
texturePixels[k*4+1]= pixel.y;
texturePixels[k*4+2]= pixel.x;
break;
case 4:
texturePixels[k*4]= pixel.z;
texturePixels[k*4+1]= pixel.y;
texturePixels[k*4+2]= pixel.x;
texturePixels[k*4+3]= pixel.w;
break;
default:
assert(false);
}
}
}
}
void Texture2DD3d9::init(Filter textureFilter, int maxAnisotropy){
if(!inited){
//get device
GraphicsInterface &gi= GraphicsInterface::getInstance();
ContextD3d9 *context= static_cast<ContextD3d9*>(gi.getCurrentContext());
IDirect3DDevice9 *d3dDevice= context->getD3dDevice();
bool mipmapCaps= (context->getCaps()->TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP) != 0;
bool autogenMipmap= mipmapCaps && mipmap;
int w= pixmapInit? pixmap.getW(): defaultSize;
int h= pixmapInit? pixmap.getH(): defaultSize;
//create texture
D3DCALL(d3dDevice->CreateTexture(
w,
h,
autogenMipmap? 0: 1,
autogenMipmap? D3DUSAGE_AUTOGENMIPMAP: 0,
toFormatD3d(format, pixmap.getComponents()),
D3DPOOL_MANAGED,
&d3dTexture,
NULL));
if(pixmapInit){
//lock
D3DLOCKED_RECT lockedRect;
D3DCALL(d3dTexture->LockRect(0, &lockedRect, NULL, 0));
//copy
fillPixels(reinterpret_cast<uint8*>(lockedRect.pBits), &pixmap);
//unlock
D3DCALL(d3dTexture->UnlockRect(0));
}
inited= true;
}
}
void Texture2DD3d9::end(){
if(inited){
d3dTexture->Release();
}
}
// ===============================================
// class TextureCubeD3d9
// ===============================================
void TextureCubeD3d9::init(Filter textureFilter, int maxAnisotropy){
//get device
if(!inited){
GraphicsInterface &gi= GraphicsInterface::getInstance();
ContextD3d9 *context= static_cast<ContextD3d9*>(gi.getCurrentContext());
IDirect3DDevice9 *d3dDevice= context->getD3dDevice();
const Pixmap2D *face0= pixmap.getFace(0);
int l= pixmapInit? face0->getW(): defaultSize;
int components= face0->getComponents();
//check dimensions and face components
if(pixmapInit){
for(int i=0; i<6; ++i){
const Pixmap2D *currentFace= pixmap.getFace(i);
if(currentFace->getW()!=l || currentFace->getH()!=l){
throw runtime_error("Can't create Direct3D cube texture: dimensions don't agree");
}
if(currentFace->getComponents()!=components){
throw runtime_error("Can't create Direct3D cube texture: components don't agree");
}
}
}
bool mipmapCaps= (context->getCaps()->TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP) != 0;
bool autogenMipmap= mipmapCaps && mipmap;
//create texture
D3DCALL(d3dDevice->CreateCubeTexture(
l,
autogenMipmap? 0: 1,
autogenMipmap? D3DUSAGE_AUTOGENMIPMAP: 0,
toFormatD3d(format, components),
D3DPOOL_MANAGED,
&d3dCubeTexture,
NULL));
if(pixmapInit){
for(int i=0; i<6; ++i){
//lock
D3DLOCKED_RECT lockedRect;
D3DCALL(d3dCubeTexture->LockRect(static_cast<D3DCUBEMAP_FACES>(i), 0, &lockedRect, NULL, 0));
//copy
fillPixels(reinterpret_cast<uint8*>(lockedRect.pBits), pixmap.getFace(i));
//unlock
D3DCALL(d3dCubeTexture->UnlockRect(static_cast<D3DCUBEMAP_FACES>(i), 0));
}
}
inited= true;
}
}
void TextureCubeD3d9::end(){
if(inited){
d3dCubeTexture->Release();
}
}
}}}//end namespace

View File

@@ -1,75 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2007 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "font.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class FontMetrics
// =====================================================
FontMetrics::FontMetrics(){
widths= new float[Font::charCount];
height= 0;
for(int i=0; i<Font::charCount; ++i){
widths[i]= 0;
}
}
FontMetrics::~FontMetrics(){
delete [] widths;
}
float FontMetrics::getTextWidth(const string &str) const{
float width= 0.f;
for(int i=0; i<str.size(); ++i){
width+= widths[str[i]];
}
return width;
}
float FontMetrics::getHeight() const{
return height;
}
// ===============================================
// class Font
// ===============================================
const int Font::charCount= 256;
Font::Font(){
inited= false;
type= "Times New Roman";
width= 400;
}
// ===============================================
// class Font2D
// ===============================================
Font2D::Font2D(){
size= 10;
}
// ===============================================
// class Font3D
// ===============================================
Font3D::Font3D(){
depth= 10.f;
}
}}//end namespace

View File

@@ -1,55 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "font_manager.h"
#include "graphics_interface.h"
#include "graphics_factory.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class FontManager
// =====================================================
FontManager::~FontManager(){
end();
}
Font2D *FontManager::newFont2D(){
Font2D *font= GraphicsInterface::getInstance().getFactory()->newFont2D();
fonts.push_back(font);
return font;
}
Font3D *FontManager::newFont3D(){
Font3D *font= GraphicsInterface::getInstance().getFactory()->newFont3D();
fonts.push_back(font);
return font;
}
void FontManager::init(){
for(size_t i=0; i<fonts.size(); ++i){
fonts[i]->init();
}
}
void FontManager::end(){
for(size_t i=0; i<fonts.size(); ++i){
fonts[i]->end();
delete fonts[i];
}
fonts.clear();
}
}}//end namespace

View File

@@ -1,44 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "context_gl.h"
#include <cassert>
#include <stdexcept>
#include "opengl.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Graphics{ namespace Gl{
// =====================================================
// class ContextGl
// =====================================================
void ContextGl::init(){
pcgl.init(colorBits, depthBits, stencilBits);
}
void ContextGl::end(){
pcgl.end();
}
void ContextGl::makeCurrent(){
pcgl.makeCurrent();
}
void ContextGl::swapBuffers(){
pcgl.swapBuffers();
}
}}}//end namespace

View File

@@ -1,77 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "font_gl.h"
#include "opengl.h"
#include "gl_wrap.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{ namespace Gl{
using namespace Platform;
// =====================================================
// class Font2DGl
// =====================================================
void Font2DGl::init(){
assertGl();
if(!inited){
handle= glGenLists(charCount);
createGlFontBitmaps(handle, type, size, width, charCount, metrics);
inited= true;
}
assertGl();
}
void Font2DGl::end(){
assertGl();
if(inited){
assert(glIsList(handle));
glDeleteLists(handle, 1);
inited= false;
}
assertGl();
}
// =====================================================
// class Font3DGl
// =====================================================
void Font3DGl::init(){
assertGl();
if(!inited){
handle= glGenLists(charCount);
createGlFontOutlines(handle, type, width, depth, charCount, metrics);
inited= true;
}
assertGl();
}
void Font3DGl::end(){
assertGl();
if(inited){
assert(glIsList(handle));
glDeleteLists(handle, 1);
}
assertGl();
}
}}}//end namespace

View File

@@ -1,217 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "model_renderer_gl.h"
#include "opengl.h"
#include "gl_wrap.h"
#include "texture_gl.h"
#include "interpolation.h"
#include "leak_dumper.h"
using namespace Shared::Platform;
namespace Shared{ namespace Graphics{ namespace Gl{
// =====================================================
// class MyClass
// =====================================================
// ===================== PUBLIC ========================
ModelRendererGl::ModelRendererGl(){
rendering= false;
duplicateTexCoords= false;
secondaryTexCoordUnit= 1;
}
void ModelRendererGl::begin(bool renderNormals, bool renderTextures, bool renderColors, MeshCallback *meshCallback){
//assertions
assert(!rendering);
assertGl();
this->renderTextures= renderTextures;
this->renderNormals= renderNormals;
this->renderColors= renderColors;
this->meshCallback= meshCallback;
rendering= true;
lastTexture= 0;
glBindTexture(GL_TEXTURE_2D, 0);
//push attribs
glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT | GL_CURRENT_BIT | GL_TEXTURE_BIT);
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
//init opengl
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, 0);
glFrontFace(GL_CCW);
glEnable(GL_NORMALIZE);
glEnable(GL_BLEND);
glEnableClientState(GL_VERTEX_ARRAY);
if(renderNormals){
glEnableClientState(GL_NORMAL_ARRAY);
}
if(renderTextures){
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
//assertions
assertGl();
}
void ModelRendererGl::end(){
//assertions
assert(rendering);
assertGl();
//set render state
rendering= false;
//pop
glPopAttrib();
glPopClientAttrib();
//assertions
assertGl();
}
void ModelRendererGl::render(const Model *model){
//assertions
assert(rendering);
assertGl();
//render every mesh
for(uint32 i=0; i<model->getMeshCount(); ++i){
renderMesh(model->getMesh(i));
}
//assertions
assertGl();
}
void ModelRendererGl::renderNormalsOnly(const Model *model){
//assertions
assert(rendering);
assertGl();
//render every mesh
for(uint32 i=0; i<model->getMeshCount(); ++i){
renderMeshNormals(model->getMesh(i));
}
//assertions
assertGl();
}
// ===================== PRIVATE =======================
void ModelRendererGl::renderMesh(const Mesh *mesh){
//assertions
assertGl();
//set cull face
if(mesh->getTwoSided()){
glDisable(GL_CULL_FACE);
}
else{
glEnable(GL_CULL_FACE);
}
//set color
if(renderColors){
Vec4f color(mesh->getDiffuseColor(), mesh->getOpacity());
glColor4fv(color.ptr());
}
//texture state
const Texture2DGl *texture= static_cast<const Texture2DGl*>(mesh->getTexture(mtDiffuse));
if(texture != NULL && renderTextures){
if(lastTexture != texture->getHandle()){
assert(glIsTexture(texture->getHandle()));
glBindTexture(GL_TEXTURE_2D, texture->getHandle());
lastTexture= texture->getHandle();
}
}
else{
glBindTexture(GL_TEXTURE_2D, 0);
lastTexture= 0;
}
if(meshCallback!=NULL){
meshCallback->execute(mesh);
}
//misc vars
uint32 vertexCount= mesh->getVertexCount();
uint32 indexCount= mesh->getIndexCount();
//assertions
assertGl();
//vertices
glVertexPointer(3, GL_FLOAT, 0, mesh->getInterpolationData()->getVertices());
//normals
if(renderNormals){
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, mesh->getInterpolationData()->getNormals());
}
else{
glDisableClientState(GL_NORMAL_ARRAY);
}
//tex coords
if(renderTextures && mesh->getTexture(mtDiffuse)!=NULL ){
if(duplicateTexCoords){
glActiveTexture(GL_TEXTURE0 + secondaryTexCoordUnit);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, mesh->getTexCoords());
}
glActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, mesh->getTexCoords());
}
else{
if(duplicateTexCoords){
glActiveTexture(GL_TEXTURE0 + secondaryTexCoordUnit);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
//draw model
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, mesh->getIndices());
//assertions
assertGl();
}
void ModelRendererGl::renderMeshNormals(const Mesh *mesh){
glBegin(GL_LINES);
for(int i= 0; i<mesh->getIndexCount(); ++i){
Vec3f vertex= mesh->getInterpolationData()->getVertices()[mesh->getIndices()[i]];
Vec3f normal= vertex + mesh->getInterpolationData()->getNormals()[mesh->getIndices()[i]];
glVertex3fv(vertex.ptr());
glVertex3fv(normal.ptr());
}
glEnd();
}
}}}//end namespace

View File

@@ -1,150 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "opengl.h"
#include <stdexcept>
#include "graphics_interface.h"
#include "context_gl.h"
#include "gl_wrap.h"
#include "leak_dumper.h"
using namespace Shared::Platform;
using namespace std;
namespace Shared{ namespace Graphics{ namespace Gl{
// =====================================================
// class Globals
// =====================================================
bool isGlExtensionSupported(const char *extensionName){
const char *s;
GLint len;
const GLubyte *extensionStr= glGetString(GL_EXTENSIONS);
s= reinterpret_cast<const char *>(extensionStr);
len= strlen(extensionName);
while ((s = strstr (s, extensionName)) != NULL) {
s+= len;
if((*s == ' ') || (*s == '\0')) {
return true;
}
}
return false;
}
bool isGlVersionSupported(int major, int minor, int release){
const char *strVersion= getGlVersion();
//major
const char *majorTok= strVersion;
int majorSupported= atoi(majorTok);
if(majorSupported<major){
return false;
}
else if(majorSupported>major){
return true;
}
//minor
int i=0;
while(strVersion[i]!='.'){
++i;
}
const char *minorTok= &strVersion[i]+1;
int minorSupported= atoi(minorTok);
if(minorSupported<minor){
return false;
}
else if(minorSupported>minor){
return true;
}
//release
++i;
while(strVersion[i]!='.'){
++i;
}
const char *releaseTok= &strVersion[i]+1;
if(atoi(releaseTok)<release){
return false;
}
return true;
}
const char *getGlVersion(){
return reinterpret_cast<const char *>(glGetString(GL_VERSION));
}
const char *getGlRenderer(){
return reinterpret_cast<const char *>(glGetString(GL_RENDERER));
}
const char *getGlVendor(){
return reinterpret_cast<const char *>(glGetString(GL_VENDOR));
}
const char *getGlExtensions(){
return reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
}
const char *getGlPlatformExtensions(){
Context *c= GraphicsInterface::getInstance().getCurrentContext();
return getPlatformExtensions(static_cast<ContextGl*>(c)->getPlatformContextGl());
}
int getGlMaxLights(){
int i;
glGetIntegerv(GL_MAX_LIGHTS, &i);
return i;
}
int getGlMaxTextureSize(){
int i;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &i);
return i;
}
int getGlMaxTextureUnits(){
int i;
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &i);
return i;
}
int getGlModelviewMatrixStackDepth(){
int i;
glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &i);
return i;
}
int getGlProjectionMatrixStackDepth(){
int i;
glGetIntegerv(GL_MAX_PROJECTION_STACK_DEPTH, &i);
return i;
}
void checkGlExtension(const char *extensionName){
if(!isGlExtensionSupported(extensionName)){
throw runtime_error("OpenGL extension not supported: " + string(extensionName));
}
}
}}}// end namespace

View File

@@ -1,294 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "particle_renderer_gl.h"
#include "opengl.h"
#include "texture_gl.h"
#include "model_renderer.h"
#include "math_util.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{ namespace Gl{
// =====================================================
// class ParticleRendererGl
// =====================================================
// ===================== PUBLIC ========================
ParticleRendererGl::ParticleRendererGl(){
assert(bufferSize%4 == 0);
rendering= false;
// init texture coordinates for quads
for(int i= 0; i<bufferSize; i+=4){
texCoordBuffer[i]= Vec2f(0.0f, 1.0f);
texCoordBuffer[i+1]= Vec2f(0.0f, 0.0f);
texCoordBuffer[i+2]= Vec2f(1.0f, 0.0f);
texCoordBuffer[i+3]= Vec2f(1.0f, 1.0f);
}
}
void ParticleRendererGl::renderManager(ParticleManager *pm, ModelRenderer *mr){
//assertions
assertGl();
//push state
glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_DEPTH_BUFFER_BIT | GL_POLYGON_BIT | GL_CURRENT_BIT | GL_LINE_BIT);
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
//init state
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
glDisable(GL_STENCIL_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
//render
rendering= true;
pm->render(this, mr);
rendering= false;
//pop state
glPopClientAttrib();
glPopAttrib();
//assertions
assertGl();
}
void ParticleRendererGl::renderSystem(ParticleSystem *ps){
assertGl();
assert(rendering);
Vec3f rightVector;
Vec3f upVector;
float modelview[16];
//render particles
setBlendMode(ps->getBlendMode());
// get the current modelview state
glGetFloatv(GL_MODELVIEW_MATRIX , modelview);
rightVector= Vec3f(modelview[0], modelview[4], modelview[8]);
upVector= Vec3f(modelview[1], modelview[5], modelview[9]);
// set state
if(ps->getTexture()!=NULL){
glBindTexture(GL_TEXTURE_2D, static_cast<Texture2DGl*>(ps->getTexture())->getHandle());
}
else{
glBindTexture(GL_TEXTURE_2D, 0);
}
glDisable(GL_ALPHA_TEST);
glDisable(GL_FOG);
glAlphaFunc(GL_GREATER, 0.0f);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
//fill vertex buffer with billboards
int bufferIndex= 0;
for(int i=0; i<ps->getAliveParticleCount(); ++i){
const Particle *particle= ps->getParticle(i);
float size= particle->getSize()/2.0f;
Vec3f pos= particle->getPos();
Vec4f color= particle->getColor();
vertexBuffer[bufferIndex] = pos - (rightVector - upVector) * size;
vertexBuffer[bufferIndex+1] = pos - (rightVector + upVector) * size;
vertexBuffer[bufferIndex+2] = pos + (rightVector - upVector) * size;
vertexBuffer[bufferIndex+3] = pos + (rightVector + upVector) * size;
colorBuffer[bufferIndex]= color;
colorBuffer[bufferIndex+1]= color;
colorBuffer[bufferIndex+2]= color;
colorBuffer[bufferIndex+3]= color;
bufferIndex+= 4;
if(bufferIndex >= bufferSize){
bufferIndex= 0;
renderBufferQuads(bufferSize);
}
}
renderBufferQuads(bufferIndex);
assertGl();
}
void ParticleRendererGl::renderSystemLine(ParticleSystem *ps){
assertGl();
assert(rendering);
if(!ps->isEmpty()){
const Particle *particle= ps->getParticle(0);
setBlendMode(ps->getBlendMode());
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
//fill vertex buffer with lines
int bufferIndex= 0;
glLineWidth(particle->getSize());
for(int i=0; i<ps->getAliveParticleCount(); ++i){
particle= ps->getParticle(i);
Vec4f color= particle->getColor();
vertexBuffer[bufferIndex] = particle->getPos();
vertexBuffer[bufferIndex+1] = particle->getLastPos();
colorBuffer[bufferIndex]= color;
colorBuffer[bufferIndex+1]= color;
bufferIndex+= 2;
if(bufferIndex >= bufferSize){
bufferIndex= 0;
renderBufferLines(bufferSize);
}
}
renderBufferLines(bufferIndex);
}
assertGl();
}
void ParticleRendererGl::renderSystemLineAlpha(ParticleSystem *ps){
assertGl();
assert(rendering);
if(!ps->isEmpty()){
const Particle *particle= ps->getParticle(0);
setBlendMode(ps->getBlendMode());
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
//fill vertex buffer with lines
int bufferIndex= 0;
glLineWidth(particle->getSize());
for(int i=0; i<ps->getAliveParticleCount(); ++i){
particle= ps->getParticle(i);
Vec4f color= particle->getColor();
vertexBuffer[bufferIndex] = particle->getPos();
vertexBuffer[bufferIndex+1] = particle->getLastPos();
colorBuffer[bufferIndex]= color;
colorBuffer[bufferIndex+1]= color;
colorBuffer[bufferIndex+1].w= 0.0f;
bufferIndex+= 2;
if(bufferIndex >= bufferSize){
bufferIndex= 0;
renderBufferLines(bufferSize);
}
}
renderBufferLines(bufferIndex);
}
assertGl();
}
void ParticleRendererGl::renderSingleModel(AttackParticleSystem *ps, ModelRenderer *mr){
//render model
if(ps->getModel()!=NULL){
//init
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glColor3f(1.f, 1.f, 1.f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
//translate
Vec3f pos= ps->getPos();
glTranslatef(pos.x, pos.y, pos.z);
//rotate
Vec3f direction= ps->getDirection();
Vec3f flatDirection= Vec3f(direction.x, 0.f, direction.z);
Vec3f rotVector= Vec3f(0.f, 1.f, 0.f).cross(flatDirection);
float angleV= radToDeg(atan2(flatDirection.length(), direction.y)) - 90.f;
glRotatef(angleV, rotVector.x, rotVector.y, rotVector.z);
float angleH= radToDeg(atan2(direction.x, direction.z));
glRotatef(angleH, 0.f, 1.f, 0.f);
//render
mr->begin(true, true, false);
mr->render(ps->getModel());
mr->end();
//end
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
}
}
// ============== PRIVATE =====================================
void ParticleRendererGl::renderBufferQuads(int quadCount){
glVertexPointer(3, GL_FLOAT, 0, vertexBuffer);
glTexCoordPointer(2, GL_FLOAT, 0, texCoordBuffer);
glColorPointer(4, GL_FLOAT, 0, colorBuffer);
glDrawArrays(GL_QUADS, 0, quadCount);
}
void ParticleRendererGl::renderBufferLines(int lineCount){
glVertexPointer(3, GL_FLOAT, 0, vertexBuffer);
glColorPointer(4, GL_FLOAT, 0, colorBuffer);
glDrawArrays(GL_LINES, 0, lineCount);
}
void ParticleRendererGl::setBlendMode(ParticleSystem::BlendMode blendMode){
switch(blendMode){
case ParticleSystem::bmOne:
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
break;
case ParticleSystem::bmOneMinusAlpha:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
default:
assert(false);
}
}
}}} //end namespace

View File

@@ -1,246 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "shader_gl.h"
#include <fstream>
#include "opengl.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Graphics{ namespace Gl{
// =====================================================
// class ShaderProgramGl
// =====================================================
ShaderProgramGl::ShaderProgramGl(){
inited= false;
}
void ShaderProgramGl::init(){
if(!inited){
assertGl();
handle= glCreateProgramObjectARB();
assertGl();
inited= true;
}
}
void ShaderProgramGl::end(){
if(inited){
assertGl();
glDeleteObjectARB(handle);
assertGl();
inited= false;
}
}
void ShaderProgramGl::attach(VertexShader *vertexShader, FragmentShader *fragmentShader){
this->vertexShader= vertexShader;
this->fragmentShader= fragmentShader;
}
bool ShaderProgramGl::link(string &messages){
assertGl();
VertexShaderGl *vertexShaderGl= static_cast<VertexShaderGl*>(vertexShader);
FragmentShaderGl *fragmentShaderGl= static_cast<FragmentShaderGl*>(fragmentShader);
const ShaderSource *vss= vertexShaderGl->getSource();
const ShaderSource *fss= fragmentShaderGl->getSource();
messages= "Linking program: " + vss->getPathInfo() + ", " + fss->getPathInfo() + "\n";
//attach
glAttachObjectARB(handle, vertexShaderGl->getHandle());
glAttachObjectARB(handle, fragmentShaderGl->getHandle());
assertGl();
//bind attributes
for(int i=0; i<attributes.size(); ++i){
int a= attributes[i].second;
string s= attributes[i].first;
glBindAttribLocationARB(handle, attributes[i].second, attributes[i].first.c_str());
}
assertGl();
//link
glLinkProgramARB(handle);
glValidateProgramARB(handle);
assertGl();
//log
GLint logLength= 0;
glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);
char *buffer= new char[logLength+1];
glGetInfoLogARB(handle, logLength+1, NULL, buffer);
messages+= buffer;
delete [] buffer;
assertGl();
//status
GLint status= false;
glGetObjectParameterivARB(handle, GL_OBJECT_LINK_STATUS_ARB, &status);
assertGl();
return status!=0;
}
void ShaderProgramGl::activate(){
assertGl();
glUseProgramObjectARB(handle);
assertGl();
}
void ShaderProgramGl::deactivate(){
assertGl();
glUseProgramObjectARB(0);
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, int value){
assertGl();
glUniform1iARB(getLocation(name), value);
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, float value){
assertGl();
glUniform1fARB(getLocation(name), value);
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Vec2f &value){
assertGl();
glUniform2fvARB(getLocation(name), 1, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Vec3f &value){
assertGl();
glUniform3fvARB(getLocation(name), 1, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Vec4f &value){
assertGl();
glUniform4fvARB(getLocation(name), 1, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Matrix3f &value){
assertGl();
glUniformMatrix3fvARB(getLocation(name), 1, GL_FALSE, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Matrix4f &value){
assertGl();
glUniformMatrix4fvARB(getLocation(name), 1, GL_FALSE, value.ptr());
assertGl();
}
void ShaderProgramGl::bindAttribute(const string &name, int index){
attributes.push_back(AttributePair(name, index));
}
GLint ShaderProgramGl::getLocation(const string &name){
GLint location= glGetUniformLocationARB(handle, name.c_str());
if(location==-1){
throw runtime_error("Can't locate uniform: "+ name);
}
return location;
}
// ===============================================
// class ShaderGl
// ===============================================
ShaderGl::ShaderGl(){
inited= false;
}
void ShaderGl::load(const string &path){
source.load(path);
}
bool ShaderGl::compile(string &messages){
assertGl();
messages= "Compiling shader: " + source.getPathInfo() + "\n";
//load source
GLint length= source.getCode().size();
const GLcharARB *csource= source.getCode().c_str();
glShaderSourceARB(handle, 1, &csource, &length);
//compile
glCompileShaderARB(handle);
//log
GLint logLength= 0;
glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);
char *buffer= new char[logLength+1];
glGetInfoLogARB(handle, logLength+1, NULL, buffer);
messages+= buffer;
delete [] buffer;
//status
GLint status= false;
glGetObjectParameterivARB(handle, GL_OBJECT_COMPILE_STATUS_ARB, &status);
assertGl();
return status!=0;
}
void ShaderGl::end(){
if(inited){
assertGl();
glDeleteObjectARB(handle);
assertGl();
}
}
// ===============================================
// class VertexShaderGl
// ===============================================
void VertexShaderGl::init(){
if(!inited){
assertGl();
handle= glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
assertGl();
inited= true;
}
}
// ===============================================
// class FragmentShaderGl
// ===============================================
void FragmentShaderGl::init(){
if(!inited){
assertGl();
handle= glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
assertGl();
inited= true;
}
}
}}}//end namespace

View File

@@ -1,142 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "text_renderer_gl.h"
#include "opengl.h"
#include "font_gl.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{ namespace Gl{
// =====================================================
// class TextRenderer2DGl
// =====================================================
TextRenderer2DGl::TextRenderer2DGl(){
rendering= false;
}
void TextRenderer2DGl::begin(const Font2D *font){
assert(!rendering);
rendering= true;
this->font= static_cast<const Font2DGl*>(font);
}
void TextRenderer2DGl::render(const string &text, int x, int y, bool centered){
assert(rendering);
assertGl();
int line=0;
int size= font->getSize();
const unsigned char *utext= reinterpret_cast<const unsigned char*>(text.c_str());
Vec2f rasterPos;
const FontMetrics *metrics= font->getMetrics();
if(centered){
rasterPos.x= x-metrics->getTextWidth(text)/2.f;
rasterPos.y= y+metrics->getHeight()/2.f;
}
else{
rasterPos= Vec2f(static_cast<float>(x), static_cast<float>(y));
}
glRasterPos2f(rasterPos.x, rasterPos.y);
for (int i=0; utext[i]!='\0'; ++i) {
switch(utext[i]){
case '\t':
rasterPos= Vec2f((rasterPos.x/size+3.f)*size, y-(size+1.f)*line);
glRasterPos2f(rasterPos.x, rasterPos.y);
break;
case '\n':
line++;
rasterPos= Vec2f(static_cast<float>(x), y-(metrics->getHeight()*2.f)*line);
glRasterPos2f(rasterPos.x, rasterPos.y);
break;
default:
glCallList(font->getHandle()+utext[i]);
}
}
assertGl();
}
void TextRenderer2DGl::end(){
assert(rendering);
rendering= false;
}
// =====================================================
// class TextRenderer3DGl
// =====================================================
TextRenderer3DGl::TextRenderer3DGl(){
rendering= false;
}
void TextRenderer3DGl::begin(const Font3D *font){
assert(!rendering);
rendering= true;
this->font= static_cast<const Font3DGl*>(font);
assertGl();
//load color
glPushAttrib(GL_TRANSFORM_BIT);
assertGl();
}
void TextRenderer3DGl::render(const string &text, float x, float y, float size, bool centered){
assert(rendering);
assertGl();
const unsigned char *utext= reinterpret_cast<const unsigned char*>(text.c_str());
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glPushAttrib(GL_POLYGON_BIT);
float scale= size/10.f;
if(centered){
const FontMetrics *metrics= font->getMetrics();
glTranslatef(x-scale*metrics->getTextWidth(text)/2.f, y-scale*metrics->getHeight()/2.f, 0);
}
else{
glTranslatef(x-scale, y-scale, 0);
}
glScalef(scale, scale, scale);
for (int i=0; utext[i]!='\0'; ++i) {
glCallList(font->getHandle()+utext[i]);
}
glPopMatrix();
glPopAttrib();
assertGl();
}
void TextRenderer3DGl::end(){
assert(rendering);
rendering= false;
assertGl();
glPopAttrib();
assertGl();
}
}}}//end namespace

View File

@@ -1,373 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "texture_gl.h"
#include <stdexcept>
#include "opengl.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Graphics{ namespace Gl{
using namespace Platform;
GLint toWrapModeGl(Texture::WrapMode wrapMode){
switch(wrapMode){
case Texture::wmClamp:
return GL_CLAMP;
case Texture::wmRepeat:
return GL_REPEAT;
case Texture::wmClampToEdge:
return GL_CLAMP_TO_EDGE;
default:
assert(false);
return GL_CLAMP;
}
}
GLint toFormatGl(Texture::Format format, int components){
switch(format){
case Texture::fAuto:
switch(components){
case 1:
return GL_LUMINANCE;
case 3:
return GL_RGB;
case 4:
return GL_RGBA;
default:
assert(false);
return GL_RGBA;
}
break;
case Texture::fLuminance:
return GL_LUMINANCE;
case Texture::fAlpha:
return GL_ALPHA;
case Texture::fRgb:
return GL_RGB;
case Texture::fRgba:
return GL_RGBA;
default:
assert(false);
return GL_RGB;
}
}
GLint toInternalFormatGl(Texture::Format format, int components){
switch(format){
case Texture::fAuto:
switch(components){
case 1:
return GL_LUMINANCE8;
case 3:
return GL_RGB8;
case 4:
return GL_RGBA8;
default:
assert(false);
return GL_RGBA8;
}
break;
case Texture::fLuminance:
return GL_LUMINANCE8;
case Texture::fAlpha:
return GL_ALPHA8;
case Texture::fRgb:
return GL_RGB8;
case Texture::fRgba:
return GL_RGBA8;
default:
assert(false);
return GL_RGB8;
}
}
// =====================================================
// class Texture1DGl
// =====================================================
void Texture1DGl::init(Filter filter, int maxAnisotropy){
assertGl();
if(!inited){
//params
GLint wrap= toWrapModeGl(wrapMode);
GLint glFormat= toFormatGl(format, pixmap.getComponents());
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
//pixel init var
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_1D, handle);
//wrap params
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, wrap);
//maxAnisotropy
if(isGlExtensionSupported("GL_EXT_texture_filter_anisotropic")){
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
}
if(mipmap){
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
//build mipmaps
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, glFilter);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int error= gluBuild1DMipmaps(
GL_TEXTURE_1D, glInternalFormat, pixmap.getW(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error!=0){
throw runtime_error("Error building texture 1D mipmaps");
}
}
else{
//build single texture
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage1D(
GL_TEXTURE_1D, 0, glInternalFormat, pixmap.getW(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error= glGetError();
if(error!=GL_NO_ERROR){
throw runtime_error("Error creating texture 1D");
}
}
inited= true;
}
assertGl();
}
void Texture1DGl::end(){
if(inited){
assertGl();
glDeleteTextures(1, &handle);
assertGl();
}
}
// =====================================================
// class Texture2DGl
// =====================================================
void Texture2DGl::init(Filter filter, int maxAnisotropy){
assertGl();
if(!inited){
//params
GLint wrap= toWrapModeGl(wrapMode);
GLint glFormat= toFormatGl(format, pixmap.getComponents());
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
//pixel init var
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_2D, handle);
//wrap params
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
//maxAnisotropy
if(isGlExtensionSupported("GL_EXT_texture_filter_anisotropic")){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
}
if(mipmap){
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
//build mipmaps
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int error= gluBuild2DMipmaps(
GL_TEXTURE_2D, glInternalFormat,
pixmap.getW(), pixmap.getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error!=0){
throw runtime_error("Error building texture 2D mipmaps");
}
}
else{
//build single texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(
GL_TEXTURE_2D, 0, glInternalFormat,
pixmap.getW(), pixmap.getH(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error= glGetError();
if(error!=GL_NO_ERROR){
throw runtime_error("Error creating texture 2D");
}
}
inited= true;
}
assertGl();
}
void Texture2DGl::end(){
if(inited){
assertGl();
glDeleteTextures(1, &handle);
assertGl();
}
}
// =====================================================
// class Texture3DGl
// =====================================================
void Texture3DGl::init(Filter filter, int maxAnisotropy){
assertGl();
if(!inited){
//params
GLint wrap= toWrapModeGl(wrapMode);
GLint glFormat= toFormatGl(format, pixmap.getComponents());
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
//pixel init var
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_3D, handle);
//wrap params
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrap);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrap);
//build single texture
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage3D(
GL_TEXTURE_3D, 0, glInternalFormat,
pixmap.getW(), pixmap.getH(), pixmap.getD(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error= glGetError();
if(error!=GL_NO_ERROR){
throw runtime_error("Error creating texture 3D");
}
inited= true;
}
assertGl();
}
void Texture3DGl::end(){
if(inited){
assertGl();
glDeleteTextures(1, &handle);
assertGl();
}
}
// =====================================================
// class TextureCubeGl
// =====================================================
void TextureCubeGl::init(Filter filter, int maxAnisotropy){
assertGl();
if(!inited){
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_CUBE_MAP, handle);
//wrap
GLint wrap= toWrapModeGl(wrapMode);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrap);
//filter
if(mipmap){
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, glFilter);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else{
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
for(int i=0; i<6; ++i){
//params
const Pixmap2D *currentPixmap= pixmap.getFace(i);
GLint glFormat= toFormatGl(format, currentPixmap->getComponents());
GLint glInternalFormat= toInternalFormatGl(format, currentPixmap->getComponents());
//pixel init var
const uint8* pixels= pixmapInit? currentPixmap->getPixels(): NULL;
GLenum target= GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
if(mipmap){
int error= gluBuild2DMipmaps(
target, glInternalFormat,
currentPixmap->getW(), currentPixmap->getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error!=0){
throw runtime_error("Error building texture cube mipmaps");
}
}
else{
glTexImage2D(
target, 0, glInternalFormat,
currentPixmap->getW(), currentPixmap->getH(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
}
if(glGetError()!=GL_NO_ERROR){
throw runtime_error("Error creating texture cube");
}
}
inited= true;
}
assertGl();
}
void TextureCubeGl::end(){
if(inited){
assertGl();
glDeleteTextures(1, &handle);
assertGl();
}
}
}}}//end namespace

View File

@@ -1,240 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2005 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "shader_gl.h"
#include <fstream>
#include "opengl.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Graphics{ namespace Gl{
// =====================================================
// class ShaderProgramGl
// =====================================================
ShaderProgramGl::ShaderProgramGl(){
inited= false;
}
void ShaderProgramGl::init(){
if(!inited){
assertGl();
handle= glCreateProgramObjectARB();
assertGl();
inited= true;
}
}
void ShaderProgramGl::end(){
if(inited){
assertGl();
glDeleteObjectARB(handle);
assertGl();
inited= false;
}
}
void ShaderProgramGl::attach(VertexShader *vertexShader, FragmentShader *fragmentShader){
this->vertexShader= vertexShader;
this->fragmentShader= fragmentShader;
}
bool ShaderProgramGl::link(string &messages){
assertGl();
VertexShaderGl *vertexShaderGl= static_cast<VertexShaderGl*>(vertexShader);
FragmentShaderGl *fragmentShaderGl= static_cast<FragmentShaderGl*>(fragmentShader);
const ShaderSource *vss= vertexShaderGl->getSource();
const ShaderSource *fss= fragmentShaderGl->getSource();
messages= "Linking program: " + vss->getPathInfo() + ", " + fss->getPathInfo() + "\n";
//attach
glAttachObjectARB(handle, vertexShaderGl->getHandle());
glAttachObjectARB(handle, fragmentShaderGl->getHandle());
assertGl();
//bind attributes
for(int i=0; i<attributes.size(); ++i){
int a= attributes[i].second;
string s= attributes[i].first;
glBindAttribLocationARB(handle, attributes[i].second, attributes[i].first.c_str());
}
assertGl();
//link
glLinkProgramARB(handle);
glValidateProgramARB(handle);
assertGl();
//log
GLint logLength= 0;
glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);
char *buffer= new char[logLength+1];
glGetInfoLogARB(handle, logLength+1, NULL, buffer);
messages+= buffer;
delete [] buffer;
assertGl();
//status
GLint status= false;
glGetObjectParameterivARB(handle, GL_OBJECT_LINK_STATUS_ARB, &status);
assertGl();
return status!=0;
}
void ShaderProgramGl::activate(){
assertGl();
glUseProgramObjectARB(handle);
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, int value){
assertGl();
glUniform1iARB(getLocation(name), value);
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, float value){
assertGl();
glUniform1fARB(getLocation(name), value);
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Vec2f &value){
assertGl();
glUniform2fvARB(getLocation(name), 1, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Vec3f &value){
assertGl();
glUniform3fvARB(getLocation(name), 1, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Vec4f &value){
assertGl();
glUniform4fvARB(getLocation(name), 1, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Matrix3f &value){
assertGl();
glUniformMatrix3fvARB(getLocation(name), 1, GL_FALSE, value.ptr());
assertGl();
}
void ShaderProgramGl::setUniform(const string &name, const Matrix4f &value){
assertGl();
glUniformMatrix4fvARB(getLocation(name), 1, GL_FALSE, value.ptr());
assertGl();
}
void ShaderProgramGl::bindAttribute(const string &name, int index){
attributes.push_back(AttributePair(name, index));
}
GLint ShaderProgramGl::getLocation(const string &name){
GLint location= glGetUniformLocationARB(handle, name.c_str());
if(location==-1){
throw runtime_error("Can't locate uniform: "+ name);
}
return location;
}
// ===============================================
// class ShaderGl
// ===============================================
ShaderGl::ShaderGl(){
inited= false;
}
void ShaderGl::load(const string &path){
source.load(path);
}
bool ShaderGl::compile(string &messages){
assertGl();
messages= "Compiling shader: " + source.getPathInfo() + "\n";
//load source
GLint length= source.getCode().size();
const GLcharARB *csource= source.getCode().c_str();
glShaderSourceARB(handle, 1, &csource, &length);
//compile
glCompileShaderARB(handle);
//log
GLint logLength= 0;
glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);
char *buffer= new char[logLength+1];
glGetInfoLogARB(handle, logLength+1, NULL, buffer);
messages+= buffer;
delete [] buffer;
//status
GLint status= false;
glGetObjectParameterivARB(handle, GL_OBJECT_COMPILE_STATUS_ARB, &status);
assertGl();
return status!=0;
}
void ShaderGl::end(){
if(inited){
assertGl();
glDeleteObjectARB(handle);
assertGl();
}
}
// ===============================================
// class VertexShaderGl
// ===============================================
void VertexShaderGl::init(){
if(!inited){
assertGl();
handle= glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
assertGl();
inited= true;
}
}
// ===============================================
// class FragmentShaderGl
// ===============================================
void FragmentShaderGl::init(){
if(!inited){
assertGl();
handle= glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
assertGl();
inited= true;
}
}
}}}//end namespace

View File

@@ -1,45 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "graphics_interface.h"
#include <cstddef>
#include "context.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class GraphicsInterface
// =====================================================
GraphicsInterface::GraphicsInterface(){
graphicsFactory= NULL;
currentContext= NULL;
}
GraphicsInterface &GraphicsInterface::getInstance(){
static GraphicsInterface graphicsInterface;
return graphicsInterface;
}
void GraphicsInterface::setFactory(GraphicsFactory *graphicsFactory){
this->graphicsFactory= graphicsFactory;
}
void GraphicsInterface::setCurrentContext(Context *context){
this->currentContext= context;
currentContext->makeCurrent();
}
}}//end namespace

View File

@@ -1,102 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "interpolation.h"
#include <cassert>
#include <algorithm>
#include "model.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Graphics{
// =====================================================
// class InterpolationData
// =====================================================
InterpolationData::InterpolationData(const Mesh *mesh){
vertices= NULL;
normals= NULL;
this->mesh= mesh;
if(mesh->getFrameCount()>1){
vertices= new Vec3f[mesh->getVertexCount()];
normals= new Vec3f[mesh->getVertexCount()];
}
}
InterpolationData::~InterpolationData(){
delete [] vertices;
delete [] normals;
}
void InterpolationData::update(float t, bool cycle){
updateVertices(t, cycle);
updateNormals(t, cycle);
}
void InterpolationData::updateVertices(float t, bool cycle){
assert(t>=0.0f && t<=1.0f);
uint32 frameCount= mesh->getFrameCount();
uint32 vertexCount= mesh->getVertexCount();
const Vec3f *meshVertices= mesh->getVertices();
if(frameCount>1){
//misc vars
uint32 prevFrame= min<uint32>(static_cast<uint32>(t*frameCount), frameCount-1);
uint32 nextFrame= cycle? (prevFrame+1) % frameCount: min(prevFrame+1, frameCount-1);
float localT= t*frameCount - prevFrame;
uint32 prevFrameBase= prevFrame*vertexCount;
uint32 nextFrameBase= nextFrame*vertexCount;
//assertions
assert(prevFrame<frameCount);
assert(nextFrame<frameCount);
//interpolate vertices
for(uint32 j=0; j<vertexCount; ++j){
vertices[j]= meshVertices[prevFrameBase+j].lerp(localT, meshVertices[nextFrameBase+j]);
}
}
}
void InterpolationData::updateNormals(float t, bool cycle){
assert(t>=0.0f && t<=1.0f);
uint32 frameCount= mesh->getFrameCount();
uint32 vertexCount= mesh->getVertexCount();
const Vec3f *meshNormals= mesh->getNormals();
if(frameCount>1){
//misc vars
uint32 prevFrame= min<uint32>(static_cast<uint32>(t*frameCount), frameCount-1);
uint32 nextFrame= cycle? (prevFrame+1) % frameCount: min(prevFrame+1, frameCount-1);
float localT= t*frameCount - prevFrame;
uint32 prevFrameBase= prevFrame*vertexCount;
uint32 nextFrameBase= nextFrame*vertexCount;
//assertions
assert(prevFrame<frameCount);
assert(nextFrame<frameCount);
//interpolate vertices
for(uint32 j=0; j<vertexCount; ++j){
normals[j]= meshNormals[prevFrameBase+j].lerp(localT, meshNormals[nextFrameBase+j]);
}
}
}
}}//end namespace

View File

@@ -1,523 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "model.h"
#include <cstdio>
#include <cassert>
#include <stdexcept>
#include "interpolation.h"
#include "conversion.h"
#include "util.h"
#include "leak_dumper.h"
using namespace Shared::Platform;
using namespace std;
namespace Shared{ namespace Graphics{
using namespace Util;
// =====================================================
// class Mesh
// =====================================================
// ==================== constructor & destructor ====================
Mesh::Mesh(){
frameCount= 0;
vertexCount= 0;
indexCount= 0;
vertices= NULL;
normals= NULL;
texCoords= NULL;
tangents= NULL;
indices= NULL;
interpolationData= NULL;
for(int i=0; i<meshTextureCount; ++i){
textures[i]= NULL;
}
twoSided= false;
customColor= false;
}
Mesh::~Mesh(){
end();
}
void Mesh::init(){
vertices= new Vec3f[frameCount*vertexCount];
normals= new Vec3f[frameCount*vertexCount];
texCoords= new Vec2f[vertexCount];
indices= new uint32[indexCount];
}
void Mesh::end(){
delete [] vertices;
delete [] normals;
delete [] texCoords;
delete [] tangents;
delete [] indices;
delete interpolationData;
}
// ========================== shadows & interpolation =========================
void Mesh::buildInterpolationData(){
interpolationData= new InterpolationData(this);
}
void Mesh::updateInterpolationData(float t, bool cycle) const{
interpolationData->update(t, cycle);
}
void Mesh::updateInterpolationVertices(float t, bool cycle) const{
interpolationData->updateVertices(t, cycle);
}
// ==================== load ====================
void Mesh::loadV2(const string &dir, FILE *f, TextureManager *textureManager){
//read header
MeshHeaderV2 meshHeader;
fread(&meshHeader, sizeof(MeshHeaderV2), 1, f);
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
throw runtime_error("Old model: vertex frame count different from normal frame count");
}
if(meshHeader.texCoordFrameCount!=1){
throw runtime_error("Old model: texture coord frame count is not 1");
}
//init
frameCount= meshHeader.vertexFrameCount;
vertexCount= meshHeader.pointCount;
indexCount= meshHeader.indexCount;
init();
//misc
twoSided= false;
customColor= false;
//texture
if(meshHeader.hasTexture && textureManager!=NULL){
texturePaths[mtDiffuse]= toLower(reinterpret_cast<char*>(meshHeader.texName));
string texPath= dir+"/"+texturePaths[mtDiffuse];
textures[mtDiffuse]= static_cast<Texture2D*>(textureManager->getTexture(texPath));
if(textures[mtDiffuse]==NULL){
textures[mtDiffuse]= textureManager->newTexture2D();
textures[mtDiffuse]->load(texPath);
}
}
//read data
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
if(textures[mtDiffuse]!=NULL){
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
}
fread(&diffuseColor, sizeof(Vec3f), 1, f);
fread(&opacity, sizeof(float32), 1, f);
fseek(f, sizeof(Vec4f)*(meshHeader.colorFrameCount-1), SEEK_CUR);
fread(indices, sizeof(uint32)*indexCount, 1, f);
}
void Mesh::loadV3(const string &dir, FILE *f, TextureManager *textureManager){
//read header
MeshHeaderV3 meshHeader;
fread(&meshHeader, sizeof(MeshHeaderV3), 1, f);
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
throw runtime_error("Old model: vertex frame count different from normal frame count");
}
//init
frameCount= meshHeader.vertexFrameCount;
vertexCount= meshHeader.pointCount;
indexCount= meshHeader.indexCount;
init();
//misc
twoSided= (meshHeader.properties & mp3TwoSided) != 0;
customColor= (meshHeader.properties & mp3CustomColor) != 0;
//texture
if(!(meshHeader.properties & mp3NoTexture) && textureManager!=NULL){
texturePaths[mtDiffuse]= toLower(reinterpret_cast<char*>(meshHeader.texName));
string texPath= dir+"/"+texturePaths[mtDiffuse];
textures[mtDiffuse]= static_cast<Texture2D*>(textureManager->getTexture(texPath));
if(textures[mtDiffuse]==NULL){
textures[mtDiffuse]= textureManager->newTexture2D();
textures[mtDiffuse]->load(texPath);
}
}
//read data
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
if(textures[mtDiffuse]!=NULL){
for(int i=0; i<meshHeader.texCoordFrameCount; ++i){
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
}
}
fread(&diffuseColor, sizeof(Vec3f), 1, f);
fread(&opacity, sizeof(float32), 1, f);
fseek(f, sizeof(Vec4f)*(meshHeader.colorFrameCount-1), SEEK_CUR);
fread(indices, sizeof(uint32)*indexCount, 1, f);
}
void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager){
//read header
MeshHeader meshHeader;
fread(&meshHeader, sizeof(MeshHeader), 1, f);
//init
frameCount= meshHeader.frameCount;
vertexCount= meshHeader.vertexCount;
indexCount= meshHeader.indexCount;
init();
//properties
customColor= (meshHeader.properties & mpfCustomColor) != 0;
twoSided= (meshHeader.properties & mpfTwoSided) != 0;
//material
diffuseColor= Vec3f(meshHeader.diffuseColor);
specularColor= Vec3f(meshHeader.specularColor);
specularPower= meshHeader.specularPower;
opacity= meshHeader.opacity;
//maps
uint32 flag= 1;
for(int i=0; i<meshTextureCount; ++i){
if((meshHeader.textures & flag) && textureManager!=NULL){
uint8 cMapPath[mapPathSize];
fread(cMapPath, mapPathSize, 1, f);
string mapPath= toLower(reinterpret_cast<char*>(cMapPath));
string mapFullPath= dir + "/" + mapPath;
textures[i]= static_cast<Texture2D*>(textureManager->getTexture(mapFullPath));
if(textures[i]==NULL){
textures[i]= textureManager->newTexture2D();
if(meshTextureChannelCount[i]!=-1){
textures[i]->getPixmap()->init(meshTextureChannelCount[i]);
}
textures[i]->load(mapFullPath);
}
}
flag*= 2;
}
//read data
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
if(meshHeader.textures!=0){
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
}
fread(indices, sizeof(uint32)*indexCount, 1, f);
//tangents
if(textures[mtNormal]!=NULL){
computeTangents();
}
}
void Mesh::save(const string &dir, FILE *f){
/*MeshHeader meshHeader;
meshHeader.vertexFrameCount= vertexFrameCount;
meshHeader.normalFrameCount= normalFrameCount;
meshHeader.texCoordFrameCount= texCoordFrameCount;
meshHeader.colorFrameCount= colorFrameCount;
meshHeader.pointCount= pointCount;
meshHeader.indexCount= indexCount;
meshHeader.properties= 0;
if(twoSided) meshHeader.properties|= mpTwoSided;
if(customTexture) meshHeader.properties|= mpCustomTexture;
if(texture==NULL){
meshHeader.properties|= mpNoTexture;
meshHeader.texName[0]= '\0';
}
else{
strcpy(reinterpret_cast<char*>(meshHeader.texName), texName.c_str());
texture->getPixmap()->saveTga(dir+"/"+texName);
}
fwrite(&meshHeader, sizeof(MeshHeader), 1, f);
fwrite(vertices, sizeof(Vec3f)*vertexFrameCount*pointCount, 1, f);
fwrite(normals, sizeof(Vec3f)*normalFrameCount*pointCount, 1, f);
fwrite(texCoords, sizeof(Vec2f)*texCoordFrameCount*pointCount, 1, f);
fwrite(colors, sizeof(Vec4f)*colorFrameCount, 1, f);
fwrite(indices, sizeof(uint32)*indexCount, 1, f);*/
}
void Mesh::computeTangents(){
delete [] tangents;
tangents= new Vec3f[vertexCount];
for(int i=0; i<vertexCount; ++i){
tangents[i]= Vec3f(0.f);
}
for(int i=0; i<indexCount; i+=3){
for(int j=0; j<3; ++j){
uint32 i0= indices[i+j];
uint32 i1= indices[i+(j+1)%3];
uint32 i2= indices[i+(j+2)%3];
Vec3f p0= vertices[i0];
Vec3f p1= vertices[i1];
Vec3f p2= vertices[i2];
float u0= texCoords[i0].x;
float u1= texCoords[i1].x;
float u2= texCoords[i2].x;
float v0= texCoords[i0].y;
float v1= texCoords[i1].y;
float v2= texCoords[i2].y;
tangents[i0]+=
((p2-p0)*(v1-v0)-(p1-p0)*(v2-v0))/
((u2-u0)*(v1-v0)-(u1-u0)*(v2-v0));
}
}
for(int i=0; i<vertexCount; ++i){
/*Vec3f binormal= normals[i].cross(tangents[i]);
tangents[i]+= binormal.cross(normals[i]);*/
tangents[i].normalize();
}
}
// ===============================================
// class Model
// ===============================================
// ==================== constructor & destructor ====================
Model::Model(){
meshCount= 0;
meshes= NULL;
textureManager= NULL;
}
Model::~Model(){
delete [] meshes;
}
// ==================== data ====================
void Model::buildInterpolationData() const{
for(int i=0; i<meshCount; ++i){
meshes[i].buildInterpolationData();
}
}
void Model::updateInterpolationData(float t, bool cycle) const{
for(int i=0; i<meshCount; ++i){
meshes[i].updateInterpolationData(t, cycle);
}
}
void Model::updateInterpolationVertices(float t, bool cycle) const{
for(int i=0; i<meshCount; ++i){
meshes[i].updateInterpolationVertices(t, cycle);
}
}
// ==================== get ====================
uint32 Model::getTriangleCount() const{
uint32 triangleCount= 0;
for(uint32 i=0; i<meshCount; ++i){
triangleCount+= meshes[i].getIndexCount()/3;
}
return triangleCount;
}
uint32 Model::getVertexCount() const{
uint32 vertexCount= 0;
for(uint32 i=0; i<meshCount; ++i){
vertexCount+= meshes[i].getVertexCount();
}
return vertexCount;
}
// ==================== io ====================
void Model::load(const string &path){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="g3d" || extension=="G3D"){
loadG3d(path);
}
else{
throw runtime_error("Unknown model format: " + extension);
}
}
void Model::save(const string &path){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="g3d" ||extension=="G3D" || extension=="s3d" || extension=="S3D"){
saveS3d(path);
}
else{
throw runtime_error("Unknown model format: " + extension);
}
}
/*void Model::loadG3dOld(const string &path){
try{
FILE *f=fopen(path.c_str(),"rb");
if (f==NULL){
throw runtime_error("Error opening 3d model file");
}
string dir= cutLastFile(path);
//read header
ModelHeaderOld modelHeader;
fread(&modelHeader, sizeof(ModelHeader), 1, f);
meshCount= modelHeader.meshCount;
if(modelHeader.id[0]!='G' || modelHeader.id[1]!='3' || modelHeader.id[2]!='D'){
throw runtime_error("Model: "+path+": is not a valid G3D model");
}
switch(modelHeader.version){
case 3:{
meshes= new Mesh[meshCount];
for(uint32 i=0; i<meshCount; ++i){
meshes[i].load(dir, f, textureManager);
meshes[i].buildInterpolationData();
}
break;
}
default:
throw runtime_error("Unknown model version");
}
fclose(f);
}
catch(exception &e){
throw runtime_error("Exception caught loading 3d file: " + path +"\n"+ e.what());
}
}*/
//load a model from a g3d file
void Model::loadG3d(const string &path){
try{
FILE *f=fopen(path.c_str(),"rb");
if (f==NULL){
throw runtime_error("Error opening 3d model file");
}
string dir= cutLastFile(path);
//file header
FileHeader fileHeader;
fread(&fileHeader, sizeof(FileHeader), 1, f);
if(strncmp(reinterpret_cast<char*>(fileHeader.id), "G3D", 3)!=0){
throw runtime_error("Not a valid S3D model");
}
fileVersion= fileHeader.version;
//version 4
if(fileHeader.version==4){
//model header
ModelHeader modelHeader;
fread(&modelHeader, sizeof(ModelHeader), 1, f);
meshCount= modelHeader.meshCount;
if(modelHeader.type!=mtMorphMesh){
throw runtime_error("Invalid model type");
}
//load meshes
meshes= new Mesh[meshCount];
for(uint32 i=0; i<meshCount; ++i){
meshes[i].load(dir, f, textureManager);
meshes[i].buildInterpolationData();
}
}
//version 3
else if(fileHeader.version==3){
fread(&meshCount, sizeof(meshCount), 1, f);
meshes= new Mesh[meshCount];
for(uint32 i=0; i<meshCount; ++i){
meshes[i].loadV3(dir, f, textureManager);
meshes[i].buildInterpolationData();
}
}
//version 2
else if(fileHeader.version==2){
fread(&meshCount, sizeof(meshCount), 1, f);
meshes= new Mesh[meshCount];
for(uint32 i=0; i<meshCount; ++i){
meshes[i].loadV2(dir, f, textureManager);
meshes[i].buildInterpolationData();
}
}
else{
throw runtime_error("Invalid model version: "+ intToStr(fileHeader.version));
}
fclose(f);
}
catch(exception &e){
throw runtime_error("Exception caught loading 3d file: " + path +"\n"+ e.what());
}
}
//save a model to a g3d file
void Model::saveS3d(const string &path){
/*FILE *f= fopen(path.c_str(), "wb");
if(f==NULL){
throw runtime_error("Cant open file for writting: "+path);
}
ModelHeader modelHeader;
modelHeader.id[0]= 'G';
modelHeader.id[1]= '3';
modelHeader.id[2]= 'D';
modelHeader.version= 3;
modelHeader.meshCount= meshCount;
string dir= cutLastFile(path);
fwrite(&modelHeader, sizeof(ModelHeader), 1, f);
for(int i=0; i<meshCount; ++i){
meshes[i].save(dir, f);
}
fclose(f);*/
}
}}//end namespace

View File

@@ -1,54 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "model_manager.h"
#include "graphics_interface.h"
#include "graphics_factory.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class ModelManager
// =====================================================
ModelManager::ModelManager(){
textureManager= NULL;
}
ModelManager::~ModelManager(){
end();
}
Model *ModelManager::newModel(){
Model *model= GraphicsInterface::getInstance().getFactory()->newModel();
model->setTextureManager(textureManager);
models.push_back(model);
return model;
}
void ModelManager::init(){
for(size_t i=0; i<models.size(); ++i){
models[i]->init();
}
}
void ModelManager::end(){
for(size_t i=0; i<models.size(); ++i){
models[i]->end();
delete models[i];
}
models.clear();
}
}}//end namespace

View File

@@ -1,856 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "particle.h"
#include <cassert>
#include <algorithm>
#include "util.h"
#include "particle_renderer.h"
#include "math_util.h"
#include "leak_dumper.h"
using namespace Shared::Util;
namespace Shared{ namespace Graphics{
// =====================================================
// class ParticleSystem
// =====================================================
ParticleSystem::ParticleSystem(int particleCount){
//init particle vector
blendMode = bmOne;
particles= new Particle[particleCount];
state= sPlay;
aliveParticleCount=0;
active= true;
visible= true;
//vars
texture= NULL;
particleObserver= NULL;
//params
this->particleCount= particleCount;
maxParticleEnergy= 250;
varParticleEnergy= 50;
pos= Vec3f(0.0f);
color= Vec4f(1.0f);
colorNoEnergy= Vec4f(0.0f);
emissionRate= 15;
speed= 1.0f;
teamcolorNoEnergy=false;
teamcolorEnergy=false;
}
ParticleSystem::~ParticleSystem(){
delete [] particles;
}
// =============== VIRTUAL ======================
//updates all living particles and creates new ones
void ParticleSystem::update(){
if(state!=sPause){
for(int i=0; i<aliveParticleCount; ++i){
updateParticle(&particles[i]);
if(deathTest(&particles[i])){
//kill the particle
killParticle(&particles[i]);
//mantain alive particles at front of the array
if(aliveParticleCount>0){
particles[i]= particles[aliveParticleCount];
}
}
}
if(state!=sFade){
for(int i=0; i<emissionRate; ++i){
Particle *p= createParticle();
initParticle(p, i);
}
}
}
}
void ParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
if(active){
pr->renderSystem(this);
}
}
ParticleSystem::BlendMode ParticleSystem::strToBlendMode(const string &str){
if(str=="normal"){
return bmOne;
}
else if(str=="black"){
return bmOneMinusAlpha;
}
else{
throw "Unknown particle mode: " + str;
}
}
// =============== SET ==========================
void ParticleSystem::setState(State state){
this->state= state;
}
void ParticleSystem::setTexture(Texture *texture){
this->texture= texture;
}
void ParticleSystem::setPos(Vec3f pos){
this->pos= pos;
}
void ParticleSystem::setColor(Vec4f color){
this->color= color;
}
void ParticleSystem::setColorNoEnergy(Vec4f colorNoEnergy){
this->colorNoEnergy= colorNoEnergy;
}
void ParticleSystem::setEmissionRate(int emissionRate){
this->emissionRate= emissionRate;
}
void ParticleSystem::setMaxParticleEnergy(int maxParticleEnergy){
this->maxParticleEnergy= maxParticleEnergy;
}
void ParticleSystem::setVarParticleEnergy(int varParticleEnergy){
this->varParticleEnergy= varParticleEnergy;
}
void ParticleSystem::setParticleSize(float particleSize){
this->particleSize= particleSize;
}
void ParticleSystem::setSpeed(float speed){
this->speed= speed;
}
void ParticleSystem::setActive(bool active){
this->active= active;
}
void ParticleSystem::setObserver(ParticleObserver *particleObserver){
this->particleObserver= particleObserver;
}
void ParticleSystem::setVisible(bool visible){
this->visible= visible;
}
// =============== MISC =========================
void ParticleSystem::fade(){
assert(state==sPlay);
state= sFade;
if(particleObserver!=NULL){
particleObserver->update(this);
}
}
int ParticleSystem::isEmpty() const{
assert(aliveParticleCount>=0);
return aliveParticleCount==0 && state!=sPause;
}
// =============== PROTECTED =========================
// if there is one dead particle it returns it else, return the particle with
// less energy
Particle * ParticleSystem::createParticle(){
//if any dead particles
if(aliveParticleCount<particleCount){
++aliveParticleCount;
return &particles[aliveParticleCount-1];
}
//if not
int minEnergy= particles[0].energy;
int minEnergyParticle= 0;
for(int i=0; i<particleCount; ++i){
if(particles[i].energy<minEnergy){
minEnergy= particles[i].energy;
minEnergyParticle= i;
}
}
return &particles[minEnergyParticle];
}
void ParticleSystem::initParticle(Particle *p, int particleIndex){
p->pos= pos;
p->lastPos= p->pos;
p->speed= Vec3f(0.0f);
p->accel= Vec3f(0.0f);
p->color= Vec4f(1.0f, 1.0f, 1.0f, 1.0);
p->size= particleSize;
p->energy= maxParticleEnergy + random.randRange(-varParticleEnergy, varParticleEnergy);
}
void ParticleSystem::updateParticle(Particle *p){
p->lastPos= p->pos;
p->pos= p->pos + p->speed;
p->speed= p->speed + p->accel;
p->energy--;
}
bool ParticleSystem::deathTest(Particle *p){
return p->energy <= 0;
}
void ParticleSystem::killParticle(Particle *p){
aliveParticleCount--;
}
void ParticleSystem::setFactionColor(Vec3f factionColor){
this->factionColor=factionColor;
Vec3f tmpCol;
if(teamcolorEnergy)
{
this->color=Vec4f(factionColor.x,factionColor.y,factionColor.z,this->color.w);
}
if(teamcolorNoEnergy)
{
this->colorNoEnergy=Vec4f(factionColor.x,factionColor.y,factionColor.z,this->colorNoEnergy.w);
}
}
// ===========================================================================
// FireParticleSystem
// ===========================================================================
FireParticleSystem::FireParticleSystem(int particleCount): ParticleSystem(particleCount){
radius= 0.5f;
speed= 0.01f;
windSpeed= Vec3f(0.0f);
setParticleSize(0.6f);
setColorNoEnergy(Vec4f(1.0f, 0.5f, 0.0f, 1.0f));
}
void FireParticleSystem::initParticle(Particle *p, int particleIndex){
ParticleSystem::initParticle(p, particleIndex);
float ang= random.randRange(-2.0f*pi, 2.0f*pi);
float mod= fabsf(random.randRange(-radius, radius));
float x= sinf(ang)*mod;
float y= cosf(ang)*mod;
float radRatio= sqrtf(sqrtf(mod/radius));
p->color= colorNoEnergy*0.5f + colorNoEnergy*0.5f*radRatio;
p->energy= static_cast<int>(maxParticleEnergy*radRatio) + random.randRange(-varParticleEnergy, varParticleEnergy);
p->pos= Vec3f(pos.x+x, pos.y+random.randRange(-radius/2, radius/2), pos.z+y);
p->lastPos= pos;
p->size= particleSize;
p->speed= Vec3f(0, speed+speed*random.randRange(-0.5f, 0.5f), 0) + windSpeed;
}
void FireParticleSystem::updateParticle(Particle *p){
p->lastPos= p->pos;
p->pos= p->pos+p->speed;
p->energy--;
if(p->color.x>0.0f)
p->color.x*= 0.98f;
if(p->color.y>0.0f)
p->color.y*= 0.98f;
if(p->color.w>0.0f)
p->color.w*= 0.98f;
p->speed.x*=1.001f;
}
// ================= SET PARAMS ====================
void FireParticleSystem::setRadius(float radius){
this->radius= radius;
}
void FireParticleSystem::setWind(float windAngle, float windSpeed){
this->windSpeed.x= sinf(degToRad(windAngle))*windSpeed;
this->windSpeed.y= 0.0f;
this->windSpeed.z= cosf(degToRad(windAngle))*windSpeed;
}
// ===========================================================================
// UnitParticleSystem
// ===========================================================================
UnitParticleSystem::UnitParticleSystem(int particleCount): ParticleSystem(particleCount){
radius= 0.5f;
speed= 0.01f;
windSpeed= Vec3f(0.0f);
setParticleSize(0.6f);
setColorNoEnergy(Vec4f(1.0f, 0.5f, 0.0f, 1.0f));
primitive= pQuad;
offset= Vec3f(0.0f);
direction= Vec3f(0.0f,1.0f,0.0f);
gravity= 0.0f;
fixed=false;
rotation=0.0f;
cRotation= Vec3f(1.0f,1.0f,1.0f);
fixedAddition = Vec3f(0.0f,0.0f,0.0f);
}
void UnitParticleSystem::render(ParticleRenderer *pr,ModelRenderer *mr){
//if(active){
switch(primitive){
case pQuad:
pr->renderSystem(this);
break;
case pLine:
pr->renderSystemLine(this);
break;
default:
assert(false);
}
//}
}
UnitParticleSystem::Primitive UnitParticleSystem::strToPrimitive(const string &str){
if(str=="quad"){
return pQuad;
}
else if(str=="line"){
return pLine;
}
else{
throw "Unknown particle primitive: " + str;
}
}
void UnitParticleSystem::initParticle(Particle *p, int particleIndex){
ParticleSystem::initParticle(p, particleIndex);
float ang= random.randRange(-2.0f*pi, 2.0f*pi);
float mod= fabsf(random.randRange(-radius, radius));
float x= sinf(ang)*mod;
float y= cosf(ang)*mod;
float radRatio= sqrtf(sqrtf(mod/radius));
//p->color= color*0.5f + color*0.5f*radRatio;
p->color=color;
p->energy= static_cast<int>(maxParticleEnergy*radRatio) + random.randRange(-varParticleEnergy, varParticleEnergy);
p->lastPos= pos;
oldPosition=pos;
p->size= particleSize;
p->speed= Vec3f(direction.x+direction.x*random.randRange(-0.5f, 0.5f),
direction.y+direction.y*random.randRange(-0.5f, 0.5f),
direction.z+direction.z*random.randRange(-0.5f, 0.5f));
p->speed= p->speed * speed;
p->accel= Vec3f(0.0f, -gravity, 0.0f);
if(!relative){
p->pos= Vec3f(pos.x+x+offset.x, pos.y+random.randRange(-radius/2, radius/2)+offset.y, pos.z+y+offset.z);
}
else
{// rotate it according to rotation
float rad=degToRad(rotation);
p->pos= Vec3f(pos.x+x+offset.z*sinf(rad)+offset.x*cosf(rad), pos.y+random.randRange(-radius/2, radius/2)+offset.y, pos.z+y+(offset.z*cosf(rad)-offset.x*sinf(rad)));
p->speed=Vec3f(p->speed.z*sinf(rad)+p->speed.x*cosf(rad),p->speed.y,(p->speed.z*cosf(rad)-p->speed.x*sinf(rad)));
}
}
void UnitParticleSystem::update(){
if(fixed)
{
fixedAddition= Vec3f(pos.x-oldPosition.x,pos.y-oldPosition.y,pos.z-oldPosition.z);
oldPosition=pos;
}
ParticleSystem::update();
}
void UnitParticleSystem::updateParticle(Particle *p){
float energyRatio= clamp(static_cast<float>(p->energy)/maxParticleEnergy, 0.f, 1.f);
p->lastPos+= p->speed;
p->pos+= p->speed;
if(fixed)
{
p->lastPos+= fixedAddition;
p->pos+= fixedAddition;
}
p->speed+= p->accel;
p->color = color * energyRatio + colorNoEnergy * (1.0f-energyRatio);
p->size = particleSize * energyRatio + sizeNoEnergy * (1.0f-energyRatio);
p->energy--;
/*
p->lastPos= p->pos;
p->pos= p->pos+p->speed;
p->energy--;
if(p->color.x>0.0f)
p->color.x*= 0.98f;
if(p->color.y>0.0f)
p->color.y*= 0.98f;
if(p->color.w>0.0f)
p->color.w*= 0.98f;
p->speed.x*=1.001f;
*/
}
// ================= SET PARAMS ====================
void UnitParticleSystem::setRadius(float radius){
this->radius= radius;
}
void UnitParticleSystem::setWind(float windAngle, float windSpeed){
this->windSpeed.x= sinf(degToRad(windAngle))*windSpeed;
this->windSpeed.y= 0.0f;
this->windSpeed.z= cosf(degToRad(windAngle))*windSpeed;
}
// ===========================================================================
// RainParticleSystem
// ===========================================================================
RainParticleSystem::RainParticleSystem(int particleCount):ParticleSystem(particleCount){
setWind(0.0f, 0.0f);
setRadius(20.0f);
setEmissionRate(25);
setParticleSize(3.0f);
setColor(Vec4f(0.5f, 0.5f, 0.5f, 0.3f));
setSpeed(0.2f);
}
void RainParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
pr->renderSystemLineAlpha(this);
}
void RainParticleSystem::initParticle(Particle *p, int particleIndex){
ParticleSystem::initParticle(p, particleIndex);
float x= random.randRange(-radius, radius);
float y= random.randRange(-radius, radius);
p->color= color;
p->energy= 10000;
p->pos= Vec3f(pos.x+x, pos.y, pos.z+y);
p->lastPos= p->pos;
p->speed= Vec3f(random.randRange(-speed/10, speed/10), -speed, random.randRange(-speed/10, speed/10)) + windSpeed;
}
bool RainParticleSystem::deathTest(Particle *p){
return p->pos.y<0;
}
void RainParticleSystem::setRadius(float radius){
this->radius= radius;
}
void RainParticleSystem::setWind(float windAngle, float windSpeed){
this->windSpeed.x= sinf(degToRad(windAngle))*windSpeed;
this->windSpeed.y= 0.0f;
this->windSpeed.z= cosf(degToRad(windAngle))*windSpeed;
}
// ===========================================================================
// SnowParticleSystem
// ===========================================================================
SnowParticleSystem::SnowParticleSystem(int particleCount):ParticleSystem(particleCount){
setWind(0.0f, 0.0f);
setRadius(30.0f);
setEmissionRate(2);
setParticleSize(0.2f);
setColor(Vec4f(0.8f, 0.8f, 0.8f, 0.8f));
setSpeed(0.05f);
}
void SnowParticleSystem::initParticle(Particle *p, int particleIndex){
ParticleSystem::initParticle(p, particleIndex);
float x= random.randRange(-radius, radius);
float y= random.randRange(-radius, radius);
p->color= color;
p->energy= 10000;
p->pos= Vec3f(pos.x+x, pos.y, pos.z+y);
p->lastPos= p->pos;
p->speed= Vec3f(0.0f, -speed, 0.0f) + windSpeed;
p->speed.x+= random.randRange(-0.005f, 0.005f);
p->speed.y+= random.randRange(-0.005f, 0.005f);
}
bool SnowParticleSystem::deathTest(Particle *p){
return p->pos.y<0;
}
void SnowParticleSystem::setRadius(float radius){
this->radius= radius;
}
void SnowParticleSystem::setWind(float windAngle, float windSpeed){
this->windSpeed.x= sinf(degToRad(windAngle))*windSpeed;
this->windSpeed.y= 0.0f;
this->windSpeed.z= cosf(degToRad(windAngle))*windSpeed;
}
// ===========================================================================
// AttackParticleSystem
// ===========================================================================
AttackParticleSystem::AttackParticleSystem(int particleCount): ParticleSystem(particleCount){
model= NULL;
primitive= pQuad;
offset= Vec3f(0.0f);
gravity= 0.0f;
direction= Vec3f(1.0f, 0.0f, 0.0f);
}
void AttackParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
if(active){
if(model!=NULL){
pr->renderSingleModel(this, mr);
}
switch(primitive){
case pQuad:
pr->renderSystem(this);
break;
case pLine:
pr->renderSystemLine(this);
break;
default:
assert(false);
}
}
}
AttackParticleSystem::Primitive AttackParticleSystem::strToPrimitive(const string &str){
if(str=="quad"){
return pQuad;
}
else if(str=="line"){
return pLine;
}
else{
throw "Unknown particle primitive: " + str;
}
}
// ===========================================================================
// ProjectileParticleSystem
// ===========================================================================
ProjectileParticleSystem::ProjectileParticleSystem(int particleCount): AttackParticleSystem(particleCount){
setEmissionRate(20);
setColor(Vec4f(1.0f, 0.3f, 0.0f, 0.5f));
setMaxParticleEnergy(100);
setVarParticleEnergy(50);
setParticleSize(0.4f);
setSpeed(0.14f);
trajectory= tLinear;
trajectorySpeed= 1.0f;
trajectoryScale= 1.0f;
trajectoryFrequency = 1.0f;
nextParticleSystem= NULL;
}
ProjectileParticleSystem::~ProjectileParticleSystem(){
if(nextParticleSystem!=NULL){
nextParticleSystem->prevParticleSystem= NULL;
}
}
void ProjectileParticleSystem::link(SplashParticleSystem *particleSystem){
nextParticleSystem= particleSystem;
nextParticleSystem->setState(sPause);
nextParticleSystem->prevParticleSystem= this;
}
void ProjectileParticleSystem::update(){
if(state==sPlay){
lastPos= pos;
flatPos+= zVector * trajectorySpeed;
Vec3f targetVector= endPos - startPos;
Vec3f currentVector= flatPos - startPos;
// ratio
float t= clamp(currentVector.length() / targetVector.length(), 0.0f, 1.0f);
// trajectory
switch(trajectory){
case tLinear:
{
pos= flatPos;
}
break;
case tParabolic:
{
float scaledT= 2.0f * (t-0.5f);
float paraboleY= (1.0f-scaledT*scaledT) * trajectoryScale;
pos = flatPos;
pos.y+= paraboleY;
}
break;
case tSpiral:
{
pos= flatPos;
pos+= xVector * cos(t*trajectoryFrequency*targetVector.length())*trajectoryScale;
pos+= yVector * sin(t*trajectoryFrequency*targetVector.length())*trajectoryScale;
}
break;
default:
assert(false);
}
direction= pos - lastPos;
direction.normalize();
//arrive destination
if( flatPos.dist(endPos)<0.5f ){
state= sFade;
model= NULL;
if(particleObserver!=NULL){
particleObserver->update(this);
}
if(nextParticleSystem!=NULL){
nextParticleSystem->setState(sPlay);
nextParticleSystem->setPos(endPos);
}
}
}
ParticleSystem::update();
}
void ProjectileParticleSystem::initParticle(Particle *p, int particleIndex){
ParticleSystem::initParticle(p, particleIndex);
float t= static_cast<float>(particleIndex)/emissionRate;
p->pos= pos + (lastPos - pos) * t;
p->lastPos= lastPos;
p->speed= Vec3f(random.randRange(-0.1f, 0.1f), random.randRange(-0.1f, 0.1f), random.randRange(-0.1f, 0.1f)) * speed;
p->accel= Vec3f(0.0f, -gravity, 0.0f);
updateParticle(p);
}
void ProjectileParticleSystem::updateParticle(Particle *p){
float energyRatio= clamp(static_cast<float>(p->energy)/maxParticleEnergy, 0.f, 1.f);
p->lastPos+= p->speed;
p->pos+= p->speed;
p->speed+= p->accel;
p->color = color * energyRatio + colorNoEnergy * (1.0f-energyRatio);
p->size = particleSize * energyRatio + sizeNoEnergy * (1.0f-energyRatio);
p->energy--;
}
void ProjectileParticleSystem::setPath(Vec3f startPos, Vec3f endPos){
//compute axis
zVector= endPos - startPos;
zVector.normalize();
yVector= Vec3f(0.0f, 1.0f, 0.0f);
xVector= zVector.cross(yVector);
//apply offset
startPos+= xVector * offset.x;
startPos+= yVector * offset.y;
startPos+= zVector * offset.z;
pos= startPos;
lastPos= startPos;
flatPos= startPos;
//recompute axis
zVector= endPos - startPos;
zVector.normalize();
yVector= Vec3f(0.0f, 1.0f, 0.0f);
xVector= zVector.cross(yVector);
// set members
this->startPos= startPos;
this->endPos= endPos;
}
ProjectileParticleSystem::Trajectory ProjectileParticleSystem::strToTrajectory(const string &str){
if(str=="linear"){
return tLinear;
}
else if(str=="parabolic"){
return tParabolic;
}
else if(str=="spiral"){
return tSpiral;
}
else{
throw "Unknown particle system trajectory: " + str;
}
}
// ===========================================================================
// SplashParticleSystem
// ===========================================================================
SplashParticleSystem::SplashParticleSystem(int particleCount): AttackParticleSystem(particleCount){
setColor(Vec4f(1.0f, 0.3f, 0.0f, 0.8f));
setMaxParticleEnergy(100);
setVarParticleEnergy(50);
setParticleSize(1.0f);
setSpeed(0.003f);
prevParticleSystem= NULL;
emissionRateFade= 1;
verticalSpreadA= 1.0f;
verticalSpreadB= 0.0f;
horizontalSpreadA= 1.0f;
horizontalSpreadB= 0.0f;
}
SplashParticleSystem::~SplashParticleSystem(){
if(prevParticleSystem!=NULL){
prevParticleSystem->nextParticleSystem= NULL;
}
}
void SplashParticleSystem::update(){
ParticleSystem::update();
if(state!=sPause){
emissionRate-= emissionRateFade;
}
}
void SplashParticleSystem::initParticle(Particle *p, int particleIndex){
p->pos= pos;
p->lastPos= p->pos;
p->energy= maxParticleEnergy;
p->size= particleSize;
p->color= color;
p->speed= Vec3f(
horizontalSpreadA * random.randRange(-1.0f, 1.0f) + horizontalSpreadB,
verticalSpreadA * random.randRange(-1.0f, 1.0f) + verticalSpreadB,
horizontalSpreadA * random.randRange(-1.0f, 1.0f) + horizontalSpreadB);
p->speed.normalize();
p->speed= p->speed * speed;
p->accel= Vec3f(0.0f, -gravity, 0.0f);
}
void SplashParticleSystem::updateParticle(Particle *p){
float energyRatio= clamp(static_cast<float>(p->energy)/maxParticleEnergy, 0.f, 1.f);
p->lastPos= p->pos;
p->pos= p->pos + p->speed;
p->speed= p->speed + p->accel;
p->energy--;
p->color = color * energyRatio + colorNoEnergy * (1.0f-energyRatio);
p->size = particleSize * energyRatio + sizeNoEnergy * (1.0f-energyRatio);
}
// ===========================================================================
// ParticleManager
// ===========================================================================
ParticleManager::~ParticleManager(){
end();
}
void ParticleManager::render(ParticleRenderer *pr, ModelRenderer *mr) const{
list<ParticleSystem*>::const_iterator it;
for (it=particleSystems.begin(); it!=particleSystems.end(); it++){
if((*it)->getVisible()){
(*it)->render(pr, mr);
}
}
}
void ParticleManager::update(){
list<ParticleSystem*>::iterator it;
for (it=particleSystems.begin(); it!=particleSystems.end(); it++){
(*it)->update();
if((*it)->isEmpty()){
delete *it;
*it= NULL;
}
}
particleSystems.remove(NULL);
}
void ParticleManager::manage(ParticleSystem *ps){
particleSystems.push_back(ps);
}
void ParticleManager::end(){
while(!particleSystems.empty()){
delete particleSystems.front();
particleSystems.pop_front();
}
}
}}//end namespace

View File

@@ -1,876 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "pixmap.h"
#include <stdexcept>
#include <cstdio>
#include <cassert>
#include "util.h"
#include "math_util.h"
#include "random.h"
#include "leak_dumper.h"
using namespace Shared::Util;
using namespace std;
namespace Shared{ namespace Graphics{
using namespace Util;
// =====================================================
// file structs
// =====================================================
#pragma pack(push, 1)
struct BitmapFileHeader{
uint8 type1;
uint8 type2;
uint32 size;
uint16 reserved1;
uint16 reserved2;
uint32 offsetBits;
};
struct BitmapInfoHeader{
uint32 size;
int32 width;
int32 height;
uint16 planes;
uint16 bitCount;
uint32 compression;
uint32 sizeImage;
int32 xPelsPerMeter;
int32 yPelsPerMeter;
uint32 clrUsed;
uint32 clrImportant;
};
struct TargaFileHeader{
int8 idLength;
int8 colourMapType;
int8 dataTypeCode;
int16 colourMapOrigin;
int16 colourMapLength;
int8 colourMapDepth;
int16 xOrigin;
int16 yOrigin;
int16 width;
int16 height;
int8 bitsPerPixel;
int8 imageDescriptor;
};
#pragma pack(pop)
const int tgaUncompressedRgb= 2;
const int tgaUncompressedBw= 3;
// =====================================================
// class PixmapIoTga
// =====================================================
PixmapIoTga::PixmapIoTga(){
file= NULL;
}
PixmapIoTga::~PixmapIoTga(){
if(file!=NULL){
fclose(file);
}
}
void PixmapIoTga::openRead(const string &path){
file= fopen(path.c_str(),"rb");
if (file==NULL){
throw runtime_error("Can't open TGA file: "+ path);
}
//read header
TargaFileHeader fileHeader;
fread(&fileHeader, sizeof(TargaFileHeader), 1, file);
//check that we can load this tga file
if(fileHeader.idLength!=0){
throw runtime_error(path + ": id field is not 0");
}
if(fileHeader.dataTypeCode!=tgaUncompressedRgb && fileHeader.dataTypeCode!=tgaUncompressedBw){
throw runtime_error(path + ": only uncompressed BW and RGB targa images are supported");
}
//check bits per pixel
if(fileHeader.bitsPerPixel!=8 && fileHeader.bitsPerPixel!=24 && fileHeader.bitsPerPixel!=32){
throw runtime_error(path + ": only 8, 24 and 32 bit targa images are supported");
}
h= fileHeader.height;
w= fileHeader.width;
components= fileHeader.bitsPerPixel/8;
}
void PixmapIoTga::read(uint8 *pixels){
read(pixels, components);
}
void PixmapIoTga::read(uint8 *pixels, int components){
for(int i=0; i<h*w*components; i+=components){
uint8 r, g, b, a, l;
if(this->components==1){
fread(&l, 1, 1, file);
r= l;
g= l;
b= l;
a= 255;
}
else{
fread(&b, 1, 1, file);
fread(&g, 1, 1, file);
fread(&r, 1, 1, file);
if(this->components==4){
fread(&a, 1, 1, file);
}
else{
a= 255;
}
l= (r+g+b)/3;
}
switch(components){
case 1:
pixels[i]= l;
break;
case 3:
pixels[i]= r;
pixels[i+1]= g;
pixels[i+2]= b;
break;
case 4:
pixels[i]= r;
pixels[i+1]= g;
pixels[i+2]= b;
pixels[i+3]= a;
break;
}
}
}
void PixmapIoTga::openWrite(const string &path, int w, int h, int components){
this->w= w;
this->h= h;
this->components= components;
file= fopen(path.c_str(),"wb");
if (file==NULL){
throw runtime_error("Can't open TGA file: "+ path);
}
TargaFileHeader fileHeader;
memset(&fileHeader, 0, sizeof(TargaFileHeader));
fileHeader.dataTypeCode= components==1? tgaUncompressedBw: tgaUncompressedRgb;
fileHeader.bitsPerPixel= components*8;
fileHeader.width= w;
fileHeader.height= h;
fileHeader.imageDescriptor= components==4? 8: 0;
fwrite(&fileHeader, sizeof(TargaFileHeader), 1, file);
}
void PixmapIoTga::write(uint8 *pixels){
if(components==1){
fwrite(pixels, h*w, 1, file);
}
else{
for(int i=0; i<h*w*components; i+=components){
fwrite(&pixels[i+2], 1, 1, file);
fwrite(&pixels[i+1], 1, 1, file);
fwrite(&pixels[i], 1, 1, file);
if(components==4){
fwrite(&pixels[i+3], 1, 1, file);
}
}
}
}
// =====================================================
// class PixmapIoBmp
// =====================================================
PixmapIoBmp::PixmapIoBmp(){
file= NULL;
}
PixmapIoBmp::~PixmapIoBmp(){
if(file!=NULL){
fclose(file);
}
}
void PixmapIoBmp::openRead(const string &path){
file= fopen(path.c_str(),"rb");
if (file==NULL){
throw runtime_error("Can't open BMP file: "+ path);
}
//read file header
BitmapFileHeader fileHeader;
fread(&fileHeader, sizeof(BitmapFileHeader), 1, file);
if(fileHeader.type1!='B' || fileHeader.type2!='M'){
throw runtime_error(path +" is not a bitmap");
}
//read info header
BitmapInfoHeader infoHeader;
fread(&infoHeader, sizeof(BitmapInfoHeader), 1, file);
if(infoHeader.bitCount!=24){
throw runtime_error(path+" is not a 24 bit bitmap");
}
h= infoHeader.height;
w= infoHeader.width;
components= 3;
}
void PixmapIoBmp::read(uint8 *pixels){
read(pixels, 3);
}
void PixmapIoBmp::read(uint8 *pixels, int components){
for(int i=0; i<h*w*components; i+=components){
uint8 r, g, b;
fread(&b, 1, 1, file);
fread(&g, 1, 1, file);
fread(&r, 1, 1, file);
switch(components){
case 1:
pixels[i]= (r+g+b)/3;
break;
case 3:
pixels[i]= r;
pixels[i+1]= g;
pixels[i+2]= b;
break;
case 4:
pixels[i]= r;
pixels[i+1]= g;
pixels[i+2]= b;
pixels[i+3]= 255;
break;
}
}
}
void PixmapIoBmp::openWrite(const string &path, int w, int h, int components){
this->w= w;
this->h= h;
this->components= components;
file= fopen(path.c_str(),"wb");
if (file==NULL){
throw runtime_error("Can't open BMP file for writting: "+ path);
}
BitmapFileHeader fileHeader;
fileHeader.type1='B';
fileHeader.type2='M';
fileHeader.offsetBits=sizeof(BitmapFileHeader)+sizeof(BitmapInfoHeader);
fileHeader.size=sizeof(BitmapFileHeader)+sizeof(BitmapInfoHeader)+3*h*w;
fwrite(&fileHeader, sizeof(BitmapFileHeader), 1, file);
//info header
BitmapInfoHeader infoHeader;
infoHeader.bitCount=24;
infoHeader.clrImportant=0;
infoHeader.clrUsed=0;
infoHeader.compression=0;
infoHeader.height= h;
infoHeader.planes=1;
infoHeader.size=sizeof(BitmapInfoHeader);
infoHeader.sizeImage=0;
infoHeader.width= w;
infoHeader.xPelsPerMeter= 0;
infoHeader.yPelsPerMeter= 0;
fwrite(&infoHeader, sizeof(BitmapInfoHeader), 1, file);
}
void PixmapIoBmp::write(uint8 *pixels){
for (int i=0; i<h*w*components; i+=components){
fwrite(&pixels[i+2], 1, 1, file);
fwrite(&pixels[i+1], 1, 1, file);
fwrite(&pixels[i], 1, 1, file);
}
}
// =====================================================
// class Pixmap1D
// =====================================================
// ===================== PUBLIC ========================
Pixmap1D::Pixmap1D(){
w= -1;
components= -1;
pixels= NULL;
}
Pixmap1D::Pixmap1D(int components){
init(components);
}
Pixmap1D::Pixmap1D(int w, int components){
init(w, components);
}
void Pixmap1D::init(int components){
this->w= -1;
this->components= components;
pixels= NULL;
}
void Pixmap1D::init(int w, int components){
this->w= w;
this->components= components;
pixels= new uint8[w*components];
}
Pixmap1D::~Pixmap1D(){
delete [] pixels;
}
void Pixmap1D::load(const string &path){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="bmp"){
loadBmp(path);
}
else if(extension=="tga"){
loadTga(path);
}
else{
throw runtime_error("Unknown pixmap extension: "+extension);
}
}
void Pixmap1D::loadBmp(const string &path){
PixmapIoBmp plb;
plb.openRead(path);
//init
if(plb.getH()==1){
w= plb.getW();
}
else if(plb.getW()==1){
w= plb.getH();
}
else{
throw runtime_error("One of the texture dimensions must be 1");
}
if(components==-1){
components= 3;
}
if(pixels==NULL){
pixels= new uint8[w*components];
}
//data
plb.read(pixels, components);
}
void Pixmap1D::loadTga(const string &path){
PixmapIoTga plt;
plt.openRead(path);
//init
if(plt.getH()==1){
w= plt.getW();
}
else if(plt.getW()==1){
w= plt.getH();
}
else{
throw runtime_error("One of the texture dimensions must be 1");
}
int fileComponents= plt.getComponents();
if(components==-1){
components= fileComponents;
}
if(pixels==NULL){
pixels= new uint8[w*components];
}
//read data
plt.read(pixels, components);
}
// =====================================================
// class Pixmap2D
// =====================================================
// ===================== PUBLIC ========================
Pixmap2D::Pixmap2D(){
h= -1;
w= -1;
components= -1;
pixels= NULL;
}
Pixmap2D::Pixmap2D(int components){
init(components);
}
Pixmap2D::Pixmap2D(int w, int h, int components){
init(w, h, components);
}
void Pixmap2D::init(int components){
this->w= -1;
this->h= -1;
this->components= components;
pixels= NULL;
}
void Pixmap2D::init(int w, int h, int components){
this->w= w;
this->h= h;
this->components= components;
pixels= new uint8[h*w*components];
}
Pixmap2D::~Pixmap2D(){
delete [] pixels;
}
void Pixmap2D::load(const string &path){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="bmp"){
loadBmp(path);
}
else if(extension=="tga"){
loadTga(path);
}
else{
throw runtime_error("Unknown pixmap extension: "+extension);
}
}
void Pixmap2D::loadBmp(const string &path){
PixmapIoBmp plb;
plb.openRead(path);
//init
w= plb.getW();
h= plb.getH();
if(components==-1){
components= 3;
}
if(pixels==NULL){
pixels= new uint8[w*h*components];
}
//data
plb.read(pixels, components);
}
void Pixmap2D::loadTga(const string &path){
PixmapIoTga plt;
plt.openRead(path);
w= plt.getW();
h= plt.getH();
//header
int fileComponents= plt.getComponents();
//init
if(components==-1){
components= fileComponents;
}
if(pixels==NULL){
pixels= new uint8[w*h*components];
}
//read data
plt.read(pixels, components);
}
void Pixmap2D::save(const string &path){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="bmp"){
saveBmp(path);
}
else if(extension=="tga"){
saveTga(path);
}
else{
throw runtime_error("Unknown pixmap extension: "+extension);
}
}
void Pixmap2D::saveBmp(const string &path){
PixmapIoBmp psb;
psb.openWrite(path, w, h, components);
psb.write(pixels);
}
void Pixmap2D::saveTga(const string &path){
PixmapIoTga pst;
pst.openWrite(path, w, h, components);
pst.write(pixels);
}
void Pixmap2D::getPixel(int x, int y, uint8 *value) const{
for(int i=0; i<components; ++i){
value[i]= pixels[(w*y+x)*components+i];
}
}
void Pixmap2D::getPixel(int x, int y, float32 *value) const{
for(int i=0; i<components; ++i){
value[i]= pixels[(w*y+x)*components+i]/255.f;
}
}
void Pixmap2D::getComponent(int x, int y, int component, uint8 &value) const{
value= pixels[(w*y+x)*components+component];
}
void Pixmap2D::getComponent(int x, int y, int component, float32 &value) const{
value= pixels[(w*y+x)*components+component]/255.f;
}
//vector get
Vec4f Pixmap2D::getPixel4f(int x, int y) const{
Vec4f v(0.f);
for(int i=0; i<components && i<4; ++i){
v.ptr()[i]= pixels[(w*y+x)*components+i]/255.f;
}
return v;
}
Vec3f Pixmap2D::getPixel3f(int x, int y) const{
Vec3f v(0.f);
for(int i=0; i<components && i<3; ++i){
v.ptr()[i]= pixels[(w*y+x)*components+i]/255.f;
}
return v;
}
float Pixmap2D::getPixelf(int x, int y) const{
return pixels[(w*y+x)*components]/255.f;
}
float Pixmap2D::getComponentf(int x, int y, int component) const{
float c;
getComponent(x, y, component, c);
return c;
}
void Pixmap2D::setPixel(int x, int y, const uint8 *value){
for(int i=0; i<components; ++i){
pixels[(w*y+x)*components+i]= value[i];
}
}
void Pixmap2D::setPixel(int x, int y, const float32 *value){
for(int i=0; i<components; ++i){
pixels[(w*y+x)*components+i]= static_cast<uint8>(value[i]*255.f);
}
}
void Pixmap2D::setComponent(int x, int y, int component, uint8 value){
pixels[(w*y+x)*components+component]= value;
}
void Pixmap2D::setComponent(int x, int y, int component, float32 value){
pixels[(w*y+x)*components+component]= static_cast<uint8>(value*255.f);
}
//vector set
void Pixmap2D::setPixel(int x, int y, const Vec3f &p){
for(int i=0; i<components && i<3; ++i){
pixels[(w*y+x)*components+i]= static_cast<uint8>(p.ptr()[i]*255.f);
}
}
void Pixmap2D::setPixel(int x, int y, const Vec4f &p){
for(int i=0; i<components && i<4; ++i){
pixels[(w*y+x)*components+i]= static_cast<uint8>(p.ptr()[i]*255.f);
}
}
void Pixmap2D::setPixel(int x, int y, float p){
pixels[(w*y+x)*components]= static_cast<uint8>(p*255.f);
}
void Pixmap2D::setPixels(const uint8 *value){
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
setPixel(i, j, value);
}
}
}
void Pixmap2D::setPixels(const float32 *value){
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
setPixel(i, j, value);
}
}
}
void Pixmap2D::setComponents(int component, uint8 value){
assert(component<components);
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
setComponent(i, j, component, value);
}
}
}
void Pixmap2D::setComponents(int component, float32 value){
assert(component<components);
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
setComponent(i, j, component, value);
}
}
}
float splatDist(Vec2i a, Vec2i b){
return (max(abs(a.x-b.x),abs(a.y- b.y)) + 3.f*a.dist(b))/4.f;
}
void Pixmap2D::splat(const Pixmap2D *leftUp, const Pixmap2D *rightUp, const Pixmap2D *leftDown, const Pixmap2D *rightDown){
Random random;
assert(components==3 || components==4);
if(
!doDimensionsAgree(leftUp) ||
!doDimensionsAgree(rightUp) ||
!doDimensionsAgree(leftDown) ||
!doDimensionsAgree(rightDown))
{
throw runtime_error("Pixmap2D::splat: pixmap dimensions don't agree");
}
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
float avg= (w+h)/2.f;
float distLu= splatDist(Vec2i(i, j), Vec2i(0, 0));
float distRu= splatDist(Vec2i(i, j), Vec2i(w, 0));
float distLd= splatDist(Vec2i(i, j), Vec2i(0, h));
float distRd= splatDist(Vec2i(i, j), Vec2i(w, h));
const float powFactor= 2.0f;
distLu= pow(distLu, powFactor);
distRu= pow(distRu, powFactor);
distLd= pow(distLd, powFactor);
distRd= pow(distRd, powFactor);
avg= pow(avg, powFactor);
float lu= distLu>avg? 0: ((avg-distLu))*random.randRange(0.5f, 1.0f);
float ru= distRu>avg? 0: ((avg-distRu))*random.randRange(0.5f, 1.0f);
float ld= distLd>avg? 0: ((avg-distLd))*random.randRange(0.5f, 1.0f);
float rd= distRd>avg? 0: ((avg-distRd))*random.randRange(0.5f, 1.0f);
float total= lu+ru+ld+rd;
Vec4f pix= (leftUp->getPixel4f(i, j)*lu+
rightUp->getPixel4f(i, j)*ru+
leftDown->getPixel4f(i, j)*ld+
rightDown->getPixel4f(i, j)*rd)*(1.0f/total);
setPixel(i, j, pix);
}
}
}
void Pixmap2D::lerp(float t, const Pixmap2D *pixmap1, const Pixmap2D *pixmap2){
if(
!doDimensionsAgree(pixmap1) ||
!doDimensionsAgree(pixmap2))
{
throw runtime_error("Pixmap2D::lerp: pixmap dimensions don't agree");
}
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
setPixel(i, j, pixmap1->getPixel4f(i, j).lerp(t, pixmap2->getPixel4f(i, j)));
}
}
}
void Pixmap2D::copy(const Pixmap2D *sourcePixmap){
assert(components==sourcePixmap->getComponents());
if(w!=sourcePixmap->getW() || h!=sourcePixmap->getH()){
throw runtime_error("Pixmap2D::copy() dimensions must agree");
}
memcpy(pixels, sourcePixmap->getPixels(), w*h*sourcePixmap->getComponents());
}
void Pixmap2D::subCopy(int x, int y, const Pixmap2D *sourcePixmap){
assert(components==sourcePixmap->getComponents());
if(w<sourcePixmap->getW() && h<sourcePixmap->getH()){
throw runtime_error("Pixmap2D::subCopy(), bad dimensions");
}
uint8 *pixel= new uint8[components];
for(int i=0; i<sourcePixmap->getW(); ++i){
for(int j=0; j<sourcePixmap->getH(); ++j){
sourcePixmap->getPixel(i, j, pixel);
setPixel(i+x, j+y, pixel);
}
}
delete pixel;
}
bool Pixmap2D::doDimensionsAgree(const Pixmap2D *pixmap){
return pixmap->getW() == w && pixmap->getH() == h;
}
// =====================================================
// class Pixmap3D
// =====================================================
Pixmap3D::Pixmap3D(){
w= -1;
h= -1;
d= -1;
components= -1;
}
Pixmap3D::Pixmap3D(int w, int h, int d, int components){
init(w, h, d, components);
}
Pixmap3D::Pixmap3D(int d, int components){
init(d, components);
}
void Pixmap3D::init(int w, int h, int d, int components){
this->w= w;
this->h= h;
this->d= d;
this->components= components;
pixels= new uint8[h*w*d*components];;
}
void Pixmap3D::init(int d, int components){
this->w= -1;
this->h= -1;
this->d= d;
this->components= components;
pixels= NULL;
}
Pixmap3D::~Pixmap3D(){
delete [] pixels;
}
void Pixmap3D::loadSlice(const string &path, int slice){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="bmp"){
loadSliceBmp(path, slice);
}
else if(extension=="tga"){
loadSliceTga(path, slice);
}
else{
throw runtime_error("Unknown pixmap extension: "+extension);
}
}
void Pixmap3D::loadSliceBmp(const string &path, int slice){
PixmapIoBmp plb;
plb.openRead(path);
//init
w= plb.getW();
h= plb.getH();
if(components==-1){
components= 3;
}
if(pixels==NULL){
pixels= new uint8[w*h*d*components];
}
//data
plb.read(&pixels[slice*w*h*components], components);
}
void Pixmap3D::loadSliceTga(const string &path, int slice){
PixmapIoTga plt;
plt.openRead(path);
//header
int fileComponents= plt.getComponents();
//init
w= plt.getW();
h= plt.getH();
if(components==-1){
components= fileComponents;
}
if(pixels==NULL){
pixels= new uint8[w*h*d*components];
}
//read data
plt.read(&pixels[slice*w*h*components], components);
}
// =====================================================
// class PixmapCube
// =====================================================
void PixmapCube::init(int w, int h, int components){
for(int i=0; i<6; ++i){
faces[i].init(w, h, components);
}
}
//load & save
void PixmapCube::loadFace(const string &path, int face){
faces[face].load(path);
}
void PixmapCube::loadFaceBmp(const string &path, int face){
faces[face].loadBmp(path);
}
void PixmapCube::loadFaceTga(const string &path, int face){
faces[face].loadTga(path);
}
}}//end namespace

View File

@@ -1,210 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "quaternion.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class AxisAngle
// =====================================================
AxisAngle::AxisAngle(const Vec3f &axis, float angle){
this->axis= axis;
this->angle= angle;
}
// =====================================================
// class EulerAngles
// =====================================================
EulerAngles::EulerAngles(float x, float y, float z){
this->x= x;
this->y= y;
this->z= z;
}
// =====================================================
// class Quaternion
// =====================================================
Quaternion::Quaternion(){
setMultIdentity();
}
Quaternion::Quaternion(float w, const Vec3f &v){
this->w= w;
this->v= v;
}
Quaternion::Quaternion(const EulerAngles &eulerAngles){
setEuler(eulerAngles);
}
Quaternion::Quaternion(const AxisAngle &axisAngle){
setAxisAngle(axisAngle);
}
void Quaternion::setMultIdentity(){
w= 1.0f;
v= Vec3f(0.0f);
}
void Quaternion::setAddIdentity(){
w= 0.0f;
v= Vec3f(0.0f);
}
void Quaternion::setAxisAngle(const AxisAngle &axisAngle){
w= cosf(axisAngle.angle/2.0f);
v.x= axisAngle.axis.x * sinf(axisAngle.angle/2.0f);
v.y= axisAngle.axis.y * sinf(axisAngle.angle/2.0f);
v.z= axisAngle.axis.z * sinf(axisAngle.angle/2.0f);
}
void Quaternion::setEuler(const EulerAngles &eulerAngles){
Quaternion qx, qy, qz, qr;
qx.w= cosf(eulerAngles.x/2.0f);
qx.v= Vec3f(sinf(eulerAngles.x/2.0f), 0.0f, 0.0f);
qy.w= cosf(eulerAngles.y/2.0f);
qy.v= Vec3f(0.0f, sinf(eulerAngles.y/2.0f), 0.0f);
qz.w= cosf(eulerAngles.z/2.0f);
qz.v= Vec3f(0.0f, 0.0f, sinf(eulerAngles.z/2.0f));
qr= qx*qy*qz;
w= qr.w;
v= qr.v;
}
float Quaternion::length(){
return sqrt(w*w+v.x*v.x+v.y*v.y+v.z*v.z);
}
Quaternion Quaternion::conjugate(){
return Quaternion(w, -v);
}
void Quaternion::normalize(){
float il= 1.f/length();
w*= il;
v= v*il;
}
Quaternion Quaternion::operator + (const Quaternion &q) const{
return Quaternion(w +q.w, v+q.v);
}
Quaternion Quaternion::operator * (const Quaternion &q) const{
return Quaternion(
w*q.w - v.x*q.v.x - v.y*q.v.y - v.z*q.v.z,
Vec3f(
w*q.v.x + v.x*q.w + v.y*q.v.z - v.z*q.v.y,
w*q.v.y + v.y*q.w + v.z*q.v.x - v.x*q.v.z,
w*q.v.z + v.z*q.w + v.x*q.v.y - v.y*q.v.x));
}
void Quaternion::operator += (const Quaternion &q){
*this= *this + q;
}
void Quaternion::operator *= (const Quaternion &q){
*this= *this * q;
}
Quaternion Quaternion::lerp(float t, const Quaternion &q) const{
return Quaternion(
w * (1.0f-t) + q.w * t,
v * (1.0f-t) + q.v * t);
}
Matrix3f Quaternion::toMatrix3() const{
Matrix3f rm;
//row1
rm[0]= 1.0f - 2*v.y*v.y - 2*v.z*v.z;
rm[3]= 2*v.x*v.y - 2*w*v.z;
rm[6]= 2*v.x*v.z + 2*w*v.y;
//row2
rm[1]= 2*v.x*v.y + 2*w*v.z;
rm[4]= 1.0f - 2*v.x*v.x - 2*v.z*v.z;
rm[7]= 2*v.y*v.z - 2*w*v.x;
//row3
rm[2]= 2*v.x*v.z - 2*w*v.y;
rm[5]= 2*v.y*v.z + 2*w*v.x;
rm[8]= 1.0f - 2*v.x*v.x - 2*v.y*v.y;
return rm;
}
Matrix4f Quaternion::toMatrix4() const{
Matrix4f rm;
//row1
rm[0]= 1.0f - 2*v.y*v.y - 2*v.z*v.z;
rm[4]= 2*v.x*v.y - 2*w*v.z;
rm[8]= 2*v.x*v.z + 2*w*v.y;
rm[12]= 0.0f;
//row2
rm[1]= 2*v.x*v.y + 2*w*v.z;
rm[5]= 1.0f - 2*v.x*v.x - 2*v.z*v.z;
rm[9]= 2*v.y*v.z - 2*w*v.x;
rm[13]= 0.0f;
//row3
rm[2]= 2*v.x*v.z - 2*w*v.y;
rm[6]= 2*v.y*v.z + 2*w*v.x;
rm[10]= 1.0f - 2*v.x*v.x - 2*v.y*v.y;
rm[14]= 0.0f;
//row4
rm[3]= 0.0f;
rm[7]= 0.0f;
rm[11]= 0.0f;
rm[15]= 1.0f;
return rm;
}
AxisAngle Quaternion::toAxisAngle() const{
float scale= 1.0f/(v.x*v.x + v.y*v.y + v.z*v.z);
return AxisAngle(v*scale, 2*acosf(w));
}
Vec3f Quaternion::getLocalXAxis() const{
return Vec3f(
1.0f - 2*v.y*v.y - 2*v.z*v.z,
2*v.x*v.y + 2*w*v.z,
2*v.x*v.z - 2*w*v.y);
}
Vec3f Quaternion::getLocalYAxis() const{
return Vec3f(
2*v.x*v.y - 2*w*v.z,
1.0f - 2*v.x*v.x - 2*v.z*v.z,
2*v.y*v.z + 2*w*v.x);
}
Vec3f Quaternion::getLocalZAxis() const{
return Vec3f(
2*v.x*v.z + 2*w*v.y,
2*v.y*v.z - 2*w*v.x,
1.0f - 2*v.x*v.x - 2*v.y*v.y);
}
}}//end namespace

View File

@@ -1,46 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "shader.h"
#include <stdexcept>
#include <fstream>
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Graphics{
// =====================================================
// class ShaderSource
// =====================================================
void ShaderSource::load(const string &path){
pathInfo+= path + " ";
//open file
ifstream ifs(path.c_str());
if(ifs.fail()){
throw runtime_error("Can't open shader file: " + path);
}
//read source
while(true){
fstream::int_type c= ifs.get();
if(ifs.eof() || ifs.fail() || ifs.bad()){
break;
}
code+= c;
}
}
}}//end namespace

View File

@@ -1,75 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "shader_manager.h"
#include <stdexcept>
#include "graphics_interface.h"
#include "graphics_factory.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class ShaderManager
// =====================================================
ShaderManager::~ShaderManager(){
}
void ShaderManager::init(){
for(int i=0; i<shaders.size(); ++i){
shaders[i]->init();
if(!shaders[i]->compile(logString)){
throw runtime_error("Can't compile shader\n");
}
}
for(int i=0; i<shaderPrograms.size(); ++i){
shaderPrograms[i]->init();
if(!shaderPrograms[i]->link(logString)){
throw runtime_error("Can't link shader\n");
}
}
}
void ShaderManager::end(){
for(int i=0; i<shaderPrograms.size(); ++i){
shaderPrograms[i]->end();
delete shaderPrograms[i];
}
shaderPrograms.clear();
for(int i=0; i<shaders.size(); ++i){
shaders[i]->end();
delete shaders[i];
}
shaders.clear();
}
ShaderProgram *ShaderManager::newShaderProgram(){
ShaderProgram *sp= GraphicsInterface::getInstance().getFactory()->newShaderProgram();
shaderPrograms.push_back(sp);
return sp;
}
VertexShader *ShaderManager::newVertexShader(){
VertexShader *vs= GraphicsInterface::getInstance().getFactory()->newVertexShader();
shaders.push_back(vs);
return vs;
}
FragmentShader *ShaderManager::newFragmentShader(){
FragmentShader *fs= GraphicsInterface::getInstance().getFactory()->newFragmentShader();
shaders.push_back(fs);
return fs;
}
}}//end namespace

View File

@@ -1,69 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "texture.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class Texture
// =====================================================
const int Texture::defaultSize= 256;
Texture::Texture(){
mipmap= true;
pixmapInit= true;
wrapMode= wmRepeat;
format= fAuto;
inited= false;
}
// =====================================================
// class Texture1D
// =====================================================
void Texture1D::load(const string &path){
this->path= path;
pixmap.load(path);
}
// =====================================================
// class Texture2D
// =====================================================
void Texture2D::load(const string &path){
this->path= path;
pixmap.load(path);
}
// =====================================================
// class Texture3D
// =====================================================
void Texture3D::loadSlice(const string &path, int slice){
this->path= path;
pixmap.loadSlice(path, slice);
}
// =====================================================
// class TextureCube
// =====================================================
void TextureCube::loadFace(const string &path, int face){
this->path= path;
pixmap.loadFace(path, face);
}
}}//end namespace

View File

@@ -1,96 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "texture_manager.h"
#include <cstdlib>
#include "graphics_interface.h"
#include "graphics_factory.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class TextureManager
// =====================================================
TextureManager::TextureManager(){
textureFilter= Texture::fBilinear;
maxAnisotropy= 1;
}
TextureManager::~TextureManager(){
end();
}
void TextureManager::init(){
for(int i=0; i<textures.size(); ++i){
textures[i]->init(textureFilter, maxAnisotropy);
}
}
void TextureManager::end(){
for(int i=0; i<textures.size(); ++i){
textures[i]->end();
delete textures[i];
}
textures.clear();
}
void TextureManager::setFilter(Texture::Filter textureFilter){
this->textureFilter= textureFilter;
}
void TextureManager::setMaxAnisotropy(int maxAnisotropy){
this->maxAnisotropy= maxAnisotropy;
}
Texture *TextureManager::getTexture(const string &path){
for(int i=0; i<textures.size(); ++i){
if(textures[i]->getPath()==path){
return textures[i];
}
}
return NULL;
}
Texture1D *TextureManager::newTexture1D(){
Texture1D *texture1D= GraphicsInterface::getInstance().getFactory()->newTexture1D();
textures.push_back(texture1D);
return texture1D;
}
Texture2D *TextureManager::newTexture2D(){
Texture2D *texture2D= GraphicsInterface::getInstance().getFactory()->newTexture2D();
textures.push_back(texture2D);
return texture2D;
}
Texture3D *TextureManager::newTexture3D(){
Texture3D *texture3D= GraphicsInterface::getInstance().getFactory()->newTexture3D();
textures.push_back(texture3D);
return texture3D;
}
TextureCube *TextureManager::newTextureCube(){
TextureCube *textureCube= GraphicsInterface::getInstance().getFactory()->newTextureCube();
textures.push_back(textureCube);
return textureCube;
}
}}//end namespace

View File

@@ -1,191 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "lua_script.h"
#include <stdexcept>
#include "conversion.h"
#include "leak_dumper.h"
using namespace std;
using namespace Shared::Util;
namespace Shared{ namespace Lua{
// =====================================================
// class LuaScript
// =====================================================
LuaScript::LuaScript(){
luaState= luaL_newstate();
luaL_openlibs(luaState);
if(luaState==NULL){
throw runtime_error("Can not allocate lua state");
}
argumentCount= -1;
}
LuaScript::~LuaScript(){
lua_close(luaState);
}
void LuaScript::loadCode(const string &code, const string &name){
int errorCode= luaL_loadbuffer(luaState, code.c_str(), code.size(), name.c_str());
if(errorCode!=0){
throw runtime_error("Error loading lua code: " + errorToString(errorCode));
}
//run code
errorCode= lua_pcall(luaState, 0, 0, 0)!=0;
if(errorCode!=0){
throw runtime_error("Error initializing lua: " + errorToString(errorCode));
}
}
void LuaScript::beginCall(const string& functionName){
lua_getglobal(luaState, functionName.c_str());
argumentCount= 0;
}
void LuaScript::endCall(){
lua_pcall(luaState, argumentCount, 0, 0);
}
void LuaScript::registerFunction(LuaFunction luaFunction, const string &functionName){
lua_pushcfunction(luaState, luaFunction);
lua_setglobal(luaState, functionName.c_str());
}
string LuaScript::errorToString(int errorCode){
string error;
switch(errorCode){
case LUA_ERRSYNTAX:
error+= "Syntax error";
break;
case LUA_ERRRUN:
error+= "Runtime error";
break;
case LUA_ERRMEM:
error+= "Memory allocation error";
break;
case LUA_ERRERR:
error+= "Error while running the error handler";
break;
default:
error+= "Unknown error";
}
error += string(": ")+luaL_checkstring(luaState, -1);
return error;
}
// =====================================================
// class LuaArguments
// =====================================================
LuaArguments::LuaArguments(lua_State *luaState){
this->luaState= luaState;
returnCount= 0;
}
int LuaArguments::getInt(int argumentIndex) const{
if(!lua_isnumber(luaState, argumentIndex)){
throwLuaError("Can not get int from Lua state");
}
return luaL_checkint(luaState, argumentIndex);
}
string LuaArguments::getString(int argumentIndex) const{
if(!lua_isstring(luaState, argumentIndex)){
throwLuaError("Can not get string from Lua state");
}
return luaL_checkstring(luaState, argumentIndex);
}
Vec2i LuaArguments::getVec2i(int argumentIndex) const{
Vec2i v;
if(!lua_istable(luaState, argumentIndex)){
throwLuaError("Can not get vec2i from Lua state, value on the stack is not a table");
}
if(luaL_getn(luaState, argumentIndex)!=2){
throwLuaError("Can not get vec2i from Lua state, array size not 2");
}
lua_rawgeti(luaState, argumentIndex, 1);
v.x= luaL_checkint(luaState, argumentIndex);
lua_pop(luaState, 1);
lua_rawgeti(luaState, argumentIndex, 2);
v.y= luaL_checkint(luaState, argumentIndex);
lua_pop(luaState, 1);
return v;
}
void LuaArguments::returnInt(int value){
++returnCount;
lua_pushinteger(luaState, value);
}
void LuaArguments::returnString(const string &value){
++returnCount;
lua_pushstring(luaState, value.c_str());
}
void LuaArguments::returnVec2i(const Vec2i &value){
++returnCount;
lua_newtable(luaState);
lua_pushnumber(luaState, value.x);
lua_rawseti(luaState, -2, 1);
lua_pushnumber(luaState, value.y);
lua_rawseti(luaState, -2, 2);
}
void LuaArguments::throwLuaError(const string &message) const{
string stackString;
int stackSize = lua_gettop(luaState);
//build stack string
for(int i= 1; i<=stackSize; ++i){
stackString+= "-" + intToStr(i) + ": ";
if(lua_isnumber(luaState, -i)){
stackString+= "Number: " + doubleToStr(luaL_checknumber(luaState, -i ));
}
else if(lua_isstring(luaState, -i)){
stackString+= "String: " + string(luaL_checkstring(luaState, -i));
}
else if(lua_istable(luaState, -i)){
stackString+= "Table (" + intToStr(luaL_getn(luaState, -i)) + ")";
}
else
{
stackString+= "Unknown";
}
stackString+= "\n";
}
throw runtime_error("Lua error: " + message + "\n\nLua Stack:\n" + stackString);
}
}}//end namespace

View File

@@ -1,703 +0,0 @@
//This file is part of Glest Shared Library (www.glest.org)
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//You can redistribute this code and/or modify it under
//the terms of the GNU General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
#include "socket.h"
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <stdexcept>
#include <sstream>
#if defined(HAVE_SYS_IOCTL_H)
#define BSD_COMP /* needed for FIONREAD on Solaris2 */
#include <sys/ioctl.h>
#endif
#if defined(HAVE_SYS_FILIO_H) /* needed for FIONREAD on Solaris 2.5 */
#include <sys/filio.h>
#endif
#include "conversion.h"
using namespace std;
using namespace Shared::Util;
namespace Shared{ namespace Platform{
bool Socket::enableDebugText = true;
// =====================================================
// class Ip
// =====================================================
Ip::Ip(){
bytes[0]= 0;
bytes[1]= 0;
bytes[2]= 0;
bytes[3]= 0;
}
Ip::Ip(unsigned char byte0, unsigned char byte1, unsigned char byte2, unsigned char byte3){
bytes[0]= byte0;
bytes[1]= byte1;
bytes[2]= byte2;
bytes[3]= byte3;
}
Ip::Ip(const string& ipString){
int offset= 0;
int byteIndex= 0;
for(byteIndex= 0; byteIndex<4; ++byteIndex){
int dotPos= ipString.find_first_of('.', offset);
bytes[byteIndex]= atoi(ipString.substr(offset, dotPos-offset).c_str());
offset= dotPos+1;
}
}
string Ip::getString() const{
return intToStr(bytes[0]) + "." + intToStr(bytes[1]) + "." + intToStr(bytes[2]) + "." + intToStr(bytes[3]);
}
// ===============================================
// class Socket
// ===============================================
Socket::Socket(int sock){
this->sock= sock;
}
Socket::Socket()
{
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock < 0)
{
throwException("Error creating socket");
}
}
Socket::~Socket()
{
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
disconnectSocket();
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
}
void Socket::disconnectSocket()
{
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
if(sock > 0)
{
if(Socket::enableDebugText) printf("In [%s::%s] calling shutdown and close for socket = %d...\n",__FILE__,__FUNCTION__,sock);
::shutdown(sock,2);
::close(sock);
sock = -1;
}
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
}
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
bool Socket::hasDataToRead(std::map<int,bool> &socketTriggeredList)
{
bool bResult = false;
if(socketTriggeredList.size() > 0)
{
/* Watch stdin (fd 0) to see when it has input. */
fd_set rfds;
FD_ZERO(&rfds);
int imaxsocket = 0;
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
itermap != socketTriggeredList.end(); itermap++)
{
int socket = itermap->first;
if(socket > 0)
{
FD_SET(socket, &rfds);
imaxsocket = max(socket,imaxsocket);
}
}
if(imaxsocket > 0)
{
/* Wait up to 0 seconds. */
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv);
if(retval < 0)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d errno = %d [%s]",__FILE__,__FUNCTION__,retval,errno,strerror(errno));
fprintf(stderr, "%s", szBuf);
}
else if(retval)
{
bResult = true;
if(Socket::enableDebugText) printf("In [%s::%s] select detected data imaxsocket = %d...\n",__FILE__,__FUNCTION__,imaxsocket);
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
itermap != socketTriggeredList.end(); itermap++)
{
int socket = itermap->first;
if (FD_ISSET(socket, &rfds))
{
if(Socket::enableDebugText) printf("In [%s] FD_ISSET true for socket %d...\n",__FUNCTION__,socket);
itermap->second = true;
}
else
{
itermap->second = false;
}
}
if(Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList->size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
}
}
}
return bResult;
}
bool Socket::hasDataToRead()
{
return Socket::hasDataToRead(sock) ;
}
bool Socket::hasDataToRead(int socket)
{
bool bResult = false;
if(socket > 0)
{
fd_set rfds;
struct timeval tv;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(socket, &rfds);
/* Wait up to 0 seconds. */
tv.tv_sec = 0;
tv.tv_usec = 0;
int retval = select(socket + 1, &rfds, NULL, NULL, &tv);
if(retval)
{
if (FD_ISSET(socket, &rfds))
{
bResult = true;
}
}
}
return bResult;
}
int Socket::getDataToRead(){
unsigned long size = 0;
//fd_set rfds;
//struct timeval tv;
//int retval;
/* Watch stdin (fd 0) to see when it has input. */
//FD_ZERO(&rfds);
//FD_SET(sock, &rfds);
/* Wait up to 0 seconds. */
//tv.tv_sec = 0;
//tv.tv_usec = 0;
//retval = select(sock + 1, &rfds, NULL, NULL, &tv);
//if(retval)
if(sock > 0)
{
/* ioctl isn't posix, but the following seems to work on all modern
* unixes */
int err= ioctl(sock, FIONREAD, &size);
if(err < 0 && errno != EAGAIN)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d errno = %d [%s]\n",__FILE__,__FUNCTION__,err,errno,strerror(errno));
//throwException(szBuf);
printf("%s",szBuf);
}
else if(err == 0)
{
//if(Socket::enableDebugText) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size);
}
}
return static_cast<int>(size);
}
int Socket::send(const void *data, int dataSize) {
ssize_t bytesSent= 0;
if(sock > 0)
{
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
}
if(bytesSent < 0 && errno != EAGAIN)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR WRITING SOCKET DATA, err = %d errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesSent,errno,strerror(errno));
//throwException(szBuf);
printf("%s",szBuf);
}
else if(bytesSent < 0 && errno == EAGAIN)
{
printf("In [%s::%s] #1 EAGAIN during send, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((bytesSent < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isWritable(true) == true)
{
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
printf("In [%s::%s] #2 EAGAIN during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent);
}
}
}
if(bytesSent <= 0)
{
int iErr = errno;
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesSent,iErr,strerror(iErr));
printf("%s",szBuf);
//throwException(szBuf);
}
if(Socket::enableDebugText) printf("In [%s::%s] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,sock,bytesSent);
return static_cast<int>(bytesSent);
}
int Socket::receive(void *data, int dataSize)
{
ssize_t bytesReceived = 0;
if(sock > 0)
{
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
}
if(bytesReceived < 0 && errno != EAGAIN)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesReceived,errno,strerror(errno));
//throwException(szBuf);
printf("%s",szBuf);
}
else if(bytesReceived < 0 && errno == EAGAIN)
{
printf("In [%s::%s] #1 EAGAIN during receive, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((bytesReceived < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isReadable() == true)
{
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
printf("In [%s::%s] #2 EAGAIN during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived);
}
}
}
if(bytesReceived <= 0)
{
int iErr = errno;
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesReceived,iErr,strerror(iErr));
printf("%s",szBuf);
//throwException(szBuf);
}
return static_cast<int>(bytesReceived);
}
int Socket::peek(void *data, int dataSize){
ssize_t err = 0;
if(sock > 0)
{
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
}
if(err < 0 && errno != EAGAIN)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] ERROR PEEKING SOCKET DATA error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,errno,strerror(errno));
//throwException(szBuf);
disconnectSocket();
}
else if(err < 0 && errno == EAGAIN)
{
printf("In [%s::%s] #1 EAGAIN during peek, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((err < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isReadable() == true)
{
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
printf("In [%s::%s] #2 EAGAIN during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err);
}
}
}
if(err <= 0)
{
int iErr = errno;
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
printf("%s",szBuf);
//throwException(szBuf);
}
return static_cast<int>(err);
}
void Socket::setBlock(bool block){
int err= fcntl(sock, F_SETFL, block ? 0 : O_NONBLOCK);
if(err<0){
throwException("Error setting I/O mode for socket");
}
}
bool Socket::isReadable()
{
if(sock <= 0) return false;
struct timeval tv;
tv.tv_sec= 0;
tv.tv_usec= 1;
fd_set set;
FD_ZERO(&set);
FD_SET(sock, &set);
int i= select(sock+1, &set, NULL, NULL, &tv);
if(i < 0)
{
if(difftime(time(NULL),lastDebugEvent) >= 1)
{
lastDebugEvent = time(NULL);
//throwException("Error selecting socket");
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
printf("%s",szBuf);
}
}
//return (i == 1 && FD_ISSET(sock, &set));
return (i == 1);
}
bool Socket::isWritable(bool waitOnDelayedResponse)
{
if(sock <= 0) return false;
struct timeval tv;
tv.tv_sec= 0;
tv.tv_usec= 1;
fd_set set;
FD_ZERO(&set);
FD_SET(sock, &set);
bool result = false;
do
{
int i = select(sock+1, NULL, &set, NULL, &tv);
if(i < 0 )
{
if(difftime(time(NULL),lastDebugEvent) >= 1)
{
lastDebugEvent = time(NULL);
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
printf("%s",szBuf);
}
waitOnDelayedResponse = false;
//throwException("Error selecting socket");
}
else if(i == 0)
{
if(difftime(time(NULL),lastDebugEvent) >= 1)
{
lastDebugEvent = time(NULL);
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] TIMEOUT while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
printf("%s",szBuf);
}
if(waitOnDelayedResponse == false)
{
result = true;
}
}
else
{
result = true;
}
} while(waitOnDelayedResponse == true && result == false);
//return (i == 1 && FD_ISSET(sock, &set));
return result;
}
bool Socket::isConnected()
{
//if the socket is not writable then it is not conencted
if(isWritable(false) == false)
{
return false;
}
//if the socket is readable it is connected if we can read a byte from it
if(isReadable())
{
char tmp;
int err = peek(&tmp, sizeof(tmp));
return (err > 0);
/*
int err = recv(sock, &tmp, sizeof(tmp), MSG_PEEK);
if(err <= 0 && errno != EAGAIN)
{
int iErr = errno;
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
printf("%s",szBuf);
return false;
}
else if(err <= 0)
{
int iErr = errno;
//disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] #2 DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
printf("%s",szBuf);
}
*/
}
//otherwise the socket is connected
return true;
}
string Socket::getHostName() const {
const int strSize= 256;
char hostname[strSize];
gethostname(hostname, strSize);
return hostname;
}
string Socket::getIp() const{
hostent* info= gethostbyname(getHostName().c_str());
unsigned char* address;
if(info==NULL){
throw runtime_error("Error getting host by name");
}
address= reinterpret_cast<unsigned char*>(info->h_addr_list[0]);
if(address==NULL){
throw runtime_error("Error getting host ip");
}
return
intToStr(address[0]) + "." +
intToStr(address[1]) + "." +
intToStr(address[2]) + "." +
intToStr(address[3]);
}
void Socket::throwException(const string &str){
std::stringstream msg;
msg << str << " (Error: " << strerror(errno) << ")";
throw runtime_error(msg.str());
}
// ===============================================
// class ClientSocket
// ===============================================
void ClientSocket::connect(const Ip &ip, int port)
{
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family= AF_INET;
addr.sin_addr.s_addr= inet_addr(ip.getString().c_str());
addr.sin_port= htons(port);
int err= ::connect(sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr));
if(err < 0)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] #2 Error connecting socket for IP: %s for Port: %d err = %d errno = %d [%s]\n",__FILE__,__FUNCTION__,ip.getString().c_str(),port,err,errno,strerror(errno));
fprintf(stderr, "%s", szBuf);
if (errno == EINPROGRESS)
{
fd_set myset;
struct timeval tv;
int valopt;
socklen_t lon;
fprintf(stderr, "In [%s::%s] EINPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__);
do
{
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&myset);
FD_SET(sock, &myset);
err = select(sock+1, NULL, &myset, NULL, &tv);
if (err < 0 && errno != EINTR)
{
sprintf(szBuf, "In [%s::%s] Error connecting %d - [%s]\n",__FILE__,__FUNCTION__,errno, strerror(errno));
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
else if (err > 0)
{
// Socket selected for write
lon = sizeof(int);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0)
{
sprintf(szBuf, "In [%s::%s] Error in getsockopt() %d - [%s]\n",__FILE__,__FUNCTION__,errno, strerror(errno));
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
// Check the value returned...
if (valopt)
{
sprintf(szBuf, "In [%s::%s] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,valopt, strerror(valopt));
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
errno = 0;
fprintf(stderr, "In [%s::%s] Apparent recovery for connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
break;
}
else
{
sprintf(szBuf, "In [%s::%s] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__);
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
disconnectSocket();
break;
}
} while (1);
}
if(err < 0)
{
fprintf(stderr, "In [%s::%s] Before END sock = %d, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,sock,err,errno,strerror(errno));
//throwException(szBuf);
disconnectSocket();
}
else
{
fprintf(stderr, "In [%s::%s] Valid recovery for connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
}
}
}
// ===============================================
// class ServerSocket
// ===============================================
void ServerSocket::bind(int port)
{
//sockaddr structure
sockaddr_in addr;
addr.sin_family= AF_INET;
addr.sin_addr.s_addr= INADDR_ANY;
addr.sin_port= htons(port);
int val = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
int err= ::bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
if(err < 0)
{
char szBuf[1024]="";
sprintf(szBuf, "In [%s::%s] Error binding socket sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
throwException(szBuf);
}
}
void ServerSocket::listen(int connectionQueueSize)
{
int err= ::listen(sock, connectionQueueSize);
if(err < 0)
{
char szBuf[1024]="";
sprintf(szBuf, "In [%s::%s] Error listening socket sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
throwException(szBuf);
}
}
Socket *ServerSocket::accept()
{
int newSock= ::accept(sock, NULL, NULL);
if(newSock < 0)
{
char szBuf[1024]="";
if(Socket::enableDebugText) printf(szBuf, "In [%s::%s] Error accepting socket connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,newSock,errno);
if(errno == EAGAIN)
{
return NULL;
}
throwException(szBuf);
}
return new Socket(newSock);
}
}}//end namespace

View File

@@ -1,41 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "factory_repository.h"
namespace Shared{ namespace Platform{
// =====================================================
// class FactoryRepository
// =====================================================
FactoryRepository &FactoryRepository::getInstance() {
static FactoryRepository factoryRepository;
return factoryRepository;
}
GraphicsFactory *FactoryRepository::getGraphicsFactory(const string &name) {
if(name == "OpenGL") {
return &graphicsFactoryGl;
}
throw runtime_error("Unknown graphics factory: " + name);
}
SoundFactory *FactoryRepository::getSoundFactory(const string &name) {
if(name == "OpenAL") {
return &soundFactoryOpenAL;
}
throw runtime_error("Unknown sound factory: " + name);
}
}}//end namespace

View File

@@ -1,122 +0,0 @@
//This file is part of Glest Shared Library (www.glest.org)
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//You can redistribute this code and/or modify it under
//the terms of the GNU General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
#include "gl_wrap.h"
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <cassert>
#include <SDL.h>
#ifdef X11_AVAILABLE
#include <GL/glx.h>
#endif
#include "opengl.h"
#include "sdl_private.h"
#include "leak_dumper.h"
#include "noimpl.h"
using namespace Shared::Graphics::Gl;
namespace Shared{ namespace Platform{
// ======================================
// class PlatformContextGl
// ======================================
void PlatformContextGl::init(int colorBits, int depthBits, int stencilBits) {
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 1);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 1);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 1);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilBits);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthBits);
int flags = SDL_OPENGL;
if(Private::shouldBeFullscreen)
flags |= SDL_FULLSCREEN;
int resW = Private::ScreenWidth;
int resH = Private::ScreenHeight;
SDL_Surface* screen = SDL_SetVideoMode(resW, resH, colorBits, flags);
if(screen == 0) {
std::ostringstream msg;
msg << "Couldn't set video mode "
<< resW << "x" << resH << " (" << colorBits
<< "bpp " << stencilBits << " stencil "
<< depthBits << " depth-buffer). SDL Error is: " << SDL_GetError();
throw std::runtime_error(msg.str());
}
}
void PlatformContextGl::end() {
}
void PlatformContextGl::makeCurrent() {
}
void PlatformContextGl::swapBuffers() {
SDL_GL_SwapBuffers();
}
// ======================================
// Global Fcs
// ======================================
void createGlFontBitmaps(uint32 &base, const string &type, int size, int width,
int charCount, FontMetrics &metrics) {
#ifdef X11_AVAILABLE
Display* display = glXGetCurrentDisplay();
if(display == 0) {
throw std::runtime_error("Couldn't create font: display is 0");
}
XFontStruct* fontInfo = XLoadQueryFont(display, type.c_str());
if(!fontInfo) {
throw std::runtime_error("Font not found.");
}
// we need the height of 'a' which sould ~ be half ascent+descent
metrics.setHeight(static_cast<float>
(fontInfo->ascent + fontInfo->descent) / 2);
for(unsigned int i = 0; i < static_cast<unsigned int> (charCount); ++i) {
if(i < fontInfo->min_char_or_byte2 ||
i > fontInfo->max_char_or_byte2) {
metrics.setWidth(i, static_cast<float>(6));
} else {
int p = i - fontInfo->min_char_or_byte2;
metrics.setWidth(i, static_cast<float> (
fontInfo->per_char[p].rbearing
- fontInfo->per_char[p].lbearing));
}
}
glXUseXFont(fontInfo->fid, 0, charCount, base);
XFreeFont(display, fontInfo);
#else
// we badly need a solution portable to more than just glx
NOIMPL;
#endif
}
void createGlFontOutlines(uint32 &base, const string &type, int width,
float depth, int charCount, FontMetrics &metrics) {
NOIMPL;
}
const char *getPlatformExtensions(const PlatformContextGl *pcgl) {
return "";
}
void *getGlProcAddress(const char *procName) {
void* proc = SDL_GL_GetProcAddress(procName);
assert(proc!=NULL);
return proc;
}
}}//end namespace

View File

@@ -1,461 +0,0 @@
//This file is part of Glest Shared Library (www.glest.org)
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//You can redistribute this code and/or modify it under
//the terms of the GNU General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
#include "platform_util.h"
#include <iostream>
#include <sstream>
#include <cassert>
#include <glob.h>
#include <errno.h>
#include <string.h>
#include <SDL.h>
#include "util.h"
#include "conversion.h"
#include "leak_dumper.h"
#include "sdl_private.h"
#include "window.h"
#include "noimpl.h"
#include "checksum.h"
#include "socket.h"
#include <algorithm>
using namespace Shared::Util;
using namespace std;
namespace Shared{ namespace Platform{
namespace Private{
bool shouldBeFullscreen = false;
int ScreenWidth;
int ScreenHeight;
}
// =====================================
// PerformanceTimer
// =====================================
void PerformanceTimer::init(float fps, int maxTimes){
times= 0;
this->maxTimes= maxTimes;
lastTicks= SDL_GetTicks();
updateTicks= static_cast<int>(1000./fps);
}
bool PerformanceTimer::isTime(){
Uint32 thisTicks = SDL_GetTicks();
if((thisTicks-lastTicks)>=updateTicks && times<maxTimes){
lastTicks+= updateTicks;
times++;
return true;
}
times= 0;
return false;
}
void PerformanceTimer::reset(){
lastTicks= SDL_GetTicks();
}
// =====================================
// Chrono
// =====================================
Chrono::Chrono() {
freq = 1000;
stopped= true;
accumCount= 0;
}
void Chrono::start() {
stopped= false;
startCount = SDL_GetTicks();
}
void Chrono::stop() {
Uint32 endCount;
endCount = SDL_GetTicks();
accumCount += endCount-startCount;
stopped= true;
}
int64 Chrono::getMicros() const {
return queryCounter(1000000);
}
int64 Chrono::getMillis() const {
return queryCounter(1000);
}
int64 Chrono::getSeconds() const {
return queryCounter(1);
}
int64 Chrono::queryCounter(int multiplier) const {
if(stopped) {
return multiplier*accumCount/freq;
} else {
Uint32 endCount;
endCount = SDL_GetTicks();
return multiplier*(accumCount+endCount-startCount)/freq;
}
}
// =====================================
// Misc
// =====================================
//finds all filenames like path and stores them in resultys
void findAll(const string &path, vector<string> &results, bool cutExtension, bool errorOnNotFound) {
results.clear();
std::string mypath = path;
/** Stupid win32 is searching for all files without extension when *. is
* specified as wildcard
*/
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
mypath = mypath.substr(0, mypath.size() - 2);
mypath += "*";
}
if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,mypath.c_str());
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
const char* begin = p;
for( ; *p != 0; ++p) {
// strip the path component
if(*p == '/')
begin = p+1;
}
results.push_back(begin);
}
globfree(&globbuf);
if(results.size() == 0 && errorOnNotFound == true) {
throw runtime_error("No files found in: " + mypath);
}
if(cutExtension) {
for (size_t i=0; i<results.size(); ++i){
results.at(i)=cutLastExt(results.at(i));
}
}
}
int isdir(const char *path)
{
struct stat stats;
return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
}
bool EndsWith(const string &str, const string& key)
{
size_t keylen = key.length();
size_t strlen = str.length();
if(keylen <= strlen)
return string::npos != str.rfind(key.c_str(),strlen - keylen, keylen);
else
return false;
}
//finds all filenames like path and gets their checksum of all files combined
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum) {
Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
std::string mypath = path;
/** Stupid win32 is searching for all files without extension when *. is
* specified as wildcard
*/
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
mypath = mypath.substr(0, mypath.size() - 2);
mypath += "*";
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
/*
const char* begin = p;
for( ; *p != 0; ++p) {
// strip the path component
if(*p == '/')
begin = p+1;
}
*/
if(isdir(p) == 0)
{
bool addFile = true;
if(filterFileExt != "")
{
addFile = EndsWith(p, filterFileExt);
}
if(addFile)
{
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
checksum.addFile(p);
}
}
}
globfree(&globbuf);
// Look recursively for sub-folders
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
/*
const char* begin = p;
for( ; *p != 0; ++p) {
// strip the path component
if(*p == '/')
begin = p+1;
}
*/
getFolderTreeContentsCheckSumRecursively(string(p) + "/*", filterFileExt, &checksum);
}
globfree(&globbuf);
return checksum.getSum();
}
//finds all filenames like path and gets the checksum of each file
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap) {
vector<std::pair<string,int32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,int32> >() : *recursiveMap);
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
std::string mypath = path;
/** Stupid win32 is searching for all files without extension when *. is
* specified as wildcard
*/
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
mypath = mypath.substr(0, mypath.size() - 2);
mypath += "*";
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
/*
const char* begin = p;
for( ; *p != 0; ++p) {
// strip the path component
if(*p == '/')
begin = p+1;
}
*/
if(isdir(p) == 0)
{
bool addFile = true;
if(filterFileExt != "")
{
addFile = EndsWith(p, filterFileExt);
}
if(addFile)
{
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
Checksum checksum;
checksum.addFile(p);
checksumFiles.push_back(std::pair<string,int32>(p,checksum.getSum()));
}
}
}
globfree(&globbuf);
// Look recursively for sub-folders
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
/*
const char* begin = p;
for( ; *p != 0; ++p) {
// strip the path component
if(*p == '/')
begin = p+1;
}
*/
checksumFiles = getFolderTreeContentsCheckSumListRecursively(string(p) + "/*", filterFileExt, &checksumFiles);
}
globfree(&globbuf);
return checksumFiles;
}
string extractDirectoryPathFromFile(string filename)
{
return filename.substr( 0, filename.rfind("/")+1 );
}
void createDirectoryPaths(string Path)
{
char DirName[256]="";
const char *path = Path.c_str();
char *dirName = DirName;
while(*path)
{
//if (('\\' == *path) || ('/' == *path))
if ('/' == *path)
{
//if (':' != *(path-1))
{
mkdir(DirName, S_IRWXO);
}
}
*dirName++ = *path++;
*dirName = '\0';
}
mkdir(DirName, S_IRWXO);
}
bool changeVideoMode(int resW, int resH, int colorBits, int ) {
Private::shouldBeFullscreen = true;
return true;
}
void restoreVideoMode() {
}
void message(string message) {
std::cerr << "******************************************************\n";
std::cerr << " " << message << "\n";
std::cerr << "******************************************************\n";
}
bool ask(string message) {
std::cerr << "Confirmation: " << message << "\n";
int res;
std::cin >> res;
return res != 0;
}
void exceptionMessage(const exception &excp) {
std::cerr << "Exception: " << excp.what() << std::endl;
}
int getScreenW() {
return SDL_GetVideoSurface()->w;
}
int getScreenH() {
return SDL_GetVideoSurface()->h;
}
void sleep(int millis) {
SDL_Delay(millis);
}
void showCursor(bool b) {
SDL_ShowCursor(b ? SDL_ENABLE : SDL_DISABLE);
}
bool isKeyDown(int virtualKey) {
char key = static_cast<char> (virtualKey);
const Uint8* keystate = SDL_GetKeyState(0);
// kinda hack and wrong...
if(key >= 0) {
return keystate[key];
}
switch(key) {
case vkAdd:
return keystate[SDLK_PLUS] | keystate[SDLK_KP_PLUS];
case vkSubtract:
return keystate[SDLK_MINUS] | keystate[SDLK_KP_MINUS];
case vkAlt:
return keystate[SDLK_LALT] | keystate[SDLK_RALT];
case vkControl:
return keystate[SDLK_LCTRL] | keystate[SDLK_RCTRL];
case vkShift:
return keystate[SDLK_LSHIFT] | keystate[SDLK_RSHIFT];
case vkEscape:
return keystate[SDLK_ESCAPE];
case vkUp:
return keystate[SDLK_UP];
case vkLeft:
return keystate[SDLK_LEFT];
case vkRight:
return keystate[SDLK_RIGHT];
case vkDown:
return keystate[SDLK_DOWN];
case vkReturn:
return keystate[SDLK_RETURN] | keystate[SDLK_KP_ENTER];
case vkBack:
return keystate[SDLK_BACKSPACE];
default:
std::cerr << "isKeyDown called with unknown key.\n";
break;
}
return false;
}
}}//end namespace

View File

@@ -1,67 +0,0 @@
//This file is part of Glest Shared Library (www.glest.org)
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//You can redistribute this code and/or modify it under
//the terms of the GNU General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
#include "thread.h"
#include <iostream>
#include <sstream>
#include <stdexcept>
#include "noimpl.h"
namespace Shared{ namespace Platform{
// =====================================
// Threads
// =====================================
void Thread::start() {
thread = SDL_CreateThread(beginExecution, this);
}
void Thread::setPriority(Thread::Priority threadPriority) {
NOIMPL;
}
int Thread::beginExecution(void* data) {
Thread* thread = static_cast<Thread*> (data);
thread->execute();
return 0;
}
void Thread::suspend() {
NOIMPL;
}
void Thread::resume() {
NOIMPL;
}
// =====================================
// Mutex
// =====================================
Mutex::Mutex() {
mutex = SDL_CreateMutex();
if(mutex == 0)
throw std::runtime_error("Couldn't initialize mutex");
}
Mutex::~Mutex() {
SDL_DestroyMutex(mutex);
}
void Mutex::p() {
SDL_mutexP(mutex);
}
void Mutex::v() {
SDL_mutexV(mutex);
}
}}//end namespace

View File

@@ -1,303 +0,0 @@
//This file is part of Glest Shared Library (www.glest.org)
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//You can redistribute this code and/or modify it under
//the terms of the GNU General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
#include "window.h"
#include <iostream>
#include <stdexcept>
#include <cassert>
#include <cctype>
#include "conversion.h"
#include "platform_util.h"
#include "leak_dumper.h"
#include "sdl_private.h"
#include "noimpl.h"
using namespace Shared::Util;
using namespace std;
namespace Shared{ namespace Platform{
// =======================================
// WINDOW
// =======================================
// ========== STATIC INICIALIZATIONS ==========
// Matze: hack for now...
static Window* global_window = 0;
// ========== PUBLIC ==========
Window::Window() {
memset(lastMouseDown, 0, sizeof(lastMouseDown));
assert(global_window == 0);
global_window = this;
}
Window::~Window() {
assert(global_window == this);
global_window = 0;
}
bool Window::handleEvent() {
SDL_Event event;
while(SDL_PollEvent(&event)) {
try {
switch(event.type) {
case SDL_QUIT:
return false;
case SDL_MOUSEBUTTONDOWN:
global_window->handleMouseDown(event);
break;
case SDL_MOUSEBUTTONUP: {
global_window->eventMouseUp(event.button.x,
event.button.y,getMouseButton(event.button.button));
break;
}
case SDL_MOUSEMOTION: {
MouseState ms;
ms.leftMouse = (event.motion.state & SDL_BUTTON_LMASK) != 0;
ms.rightMouse = (event.motion.state & SDL_BUTTON_RMASK) != 0;
ms.centerMouse = (event.motion.state & SDL_BUTTON_MMASK) != 0;
global_window->eventMouseMove(event.motion.x, event.motion.y, &ms);
break;
}
case SDL_KEYDOWN:
/* handle ALT+Return */
if(event.key.keysym.sym == SDLK_RETURN
&& (event.key.keysym.mod & (KMOD_LALT | KMOD_RALT))) {
toggleFullscreen();
}
global_window->eventKeyDown(getKey(event.key.keysym));
global_window->eventKeyPress(static_cast<char>(event.key.keysym.unicode));
break;
case SDL_KEYUP:
global_window->eventKeyUp(getKey(event.key.keysym));
break;
}
} catch(std::exception& e) {
std::cerr << "Couldn't process event: " << e.what() << "\n";
}
}
return true;
}
string Window::getText() {
char* c = 0;
SDL_WM_GetCaption(&c, 0);
return string(c);
}
float Window::getAspect() {
return static_cast<float>(getClientH())/getClientW();
}
void Window::setText(string text) {
SDL_WM_SetCaption(text.c_str(), 0);
}
void Window::setSize(int w, int h) {
this->w = w;
this->h = h;
Private::ScreenWidth = w;
Private::ScreenHeight = h;
}
void Window::setPos(int x, int y) {
if(x != 0 || y != 0) {
NOIMPL;
return;
}
}
void Window::minimize() {
NOIMPL;
}
void Window::setEnabled(bool enabled) {
NOIMPL;
}
void Window::setVisible(bool visible) {
NOIMPL;
}
void Window::setStyle(WindowStyle windowStyle) {
if(windowStyle == wsFullscreen)
return;
// NOIMPL;
}
void Window::create() {
// nothing here
}
void Window::destroy() {
SDL_Event event;
event.type = SDL_QUIT;
SDL_PushEvent(&event);
}
void Window::toggleFullscreen() {
SDL_WM_ToggleFullScreen(SDL_GetVideoSurface());
}
void Window::handleMouseDown(SDL_Event event) {
static const Uint32 DOUBLECLICKTIME = 500;
static const int DOUBLECLICKDELTA = 5;
MouseButton button = getMouseButton(event.button.button);
Uint32 ticks = SDL_GetTicks();
int n = (int) button;
if(ticks - lastMouseDown[n] < DOUBLECLICKTIME
&& abs(lastMouseX[n] - event.button.x) < DOUBLECLICKDELTA
&& abs(lastMouseY[n] - event.button.y) < DOUBLECLICKDELTA) {
eventMouseDown(event.button.x, event.button.y, button);
eventMouseDoubleClick(event.button.x, event.button.y, button);
} else {
eventMouseDown(event.button.x, event.button.y, button);
}
lastMouseDown[n] = ticks;
lastMouseX[n] = event.button.x;
lastMouseY[n] = event.button.y;
}
MouseButton Window::getMouseButton(int sdlButton) {
switch(sdlButton) {
case SDL_BUTTON_LEFT:
return mbLeft;
case SDL_BUTTON_RIGHT:
return mbRight;
case SDL_BUTTON_MIDDLE:
return mbCenter;
default:
throw std::runtime_error("Mouse Button > 3 not handled.");
}
}
char Window::getKey(SDL_keysym keysym) {
switch(keysym.sym) {
case SDLK_PLUS:
case SDLK_KP_PLUS:
return vkAdd;
case SDLK_MINUS:
case SDLK_KP_MINUS:
return vkSubtract;
case SDLK_LALT:
case SDLK_RALT:
return vkAlt;
case SDLK_LCTRL:
case SDLK_RCTRL:
return vkControl;
case SDLK_LSHIFT:
case SDLK_RSHIFT:
return vkShift;
case SDLK_ESCAPE:
return vkEscape;
case SDLK_UP:
return vkUp;
case SDLK_LEFT:
return vkLeft;
case SDLK_RIGHT:
return vkRight;
case SDLK_DOWN:
return vkDown;
case SDLK_RETURN:
case SDLK_KP_ENTER:
return vkReturn;
case SDLK_BACKSPACE:
return vkBack;
case SDLK_0:
return '0';
case SDLK_1:
return '1';
case SDLK_2:
return '2';
case SDLK_3:
return '3';
case SDLK_4:
return '4';
case SDLK_5:
return '5';
case SDLK_6:
return '6';
case SDLK_7:
return '7';
case SDLK_8:
return '8';
case SDLK_9:
return '9';
case SDLK_a:
return 'A';
case SDLK_b:
return 'B';
case SDLK_c:
return 'C';
case SDLK_d:
return 'D';
case SDLK_e:
return 'E';
case SDLK_f:
return 'F';
case SDLK_g:
return 'G';
case SDLK_h:
return 'H';
case SDLK_i:
return 'I';
case SDLK_j:
return 'J';
case SDLK_k:
return 'K';
case SDLK_l:
return 'L';
case SDLK_m:
return 'M';
case SDLK_n:
return 'N';
case SDLK_o:
return 'O';
case SDLK_p:
return 'P';
case SDLK_q:
return 'Q';
case SDLK_r:
return 'R';
case SDLK_s:
return 'S';
case SDLK_t:
return 'T';
case SDLK_u:
return 'U';
case SDLK_v:
return 'V';
case SDLK_w:
return 'W';
case SDLK_x:
return 'X';
case SDLK_y:
return 'Y';
case SDLK_z:
return 'Z';
default:
Uint16 c = keysym.unicode;
if((c & 0xFF80) == 0) {
return toupper(c);
}
break;
}
return 0;
}
}}//end namespace

View File

@@ -1,42 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "window_gl.h"
#include "gl_wrap.h"
#include "graphics_interface.h"
#include "leak_dumper.h"
using namespace Shared::Graphics;
namespace Shared{ namespace Platform{
// =====================================================
// class WindowGl
// =====================================================
void WindowGl::initGl(int colorBits, int depthBits, int stencilBits){
context.setColorBits(colorBits);
context.setDepthBits(depthBits);
context.setStencilBits(stencilBits);
context.init();
}
void WindowGl::makeCurrentGl() {
GraphicsInterface::getInstance().setCurrentContext(&context);
context.makeCurrent();
}
void WindowGl::swapBuffersGl(){
context.swapBuffers();
}
}}//end namespace

View File

@@ -1,46 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "factory_repository.h"
#include "leak_dumper.h"
namespace Shared{ namespace Platform{
// =====================================================
// class FactoryRepository
// =====================================================
FactoryRepository &FactoryRepository::getInstance(){
static FactoryRepository factoryRepository;
return factoryRepository;
}
GraphicsFactory *FactoryRepository::getGraphicsFactory(const string &name){
if(name == "OpenGL"){
return &graphicsFactoryGl;
}
else if(name == "OpenGL2"){
return &graphicsFactoryGl2;
}
throw runtime_error("Unknown graphics factory: " + name);
}
SoundFactory *FactoryRepository::getSoundFactory(const string &name){
if(name == "DirectSound8"){
return &soundFactoryDs8;
}
throw runtime_error("Unknown sound factory: " + name);
}
}}//end namespace

View File

@@ -1,164 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "gl_wrap.h"
#include <cassert>
#include <windows.h>
#include "opengl.h"
#include "leak_dumper.h"
using namespace Shared::Graphics::Gl;
namespace Shared{ namespace Platform{
// =====================================================
// class PlatformContextGl
// =====================================================
void PlatformContextGl::init(int colorBits, int depthBits, int stencilBits){
int iFormat;
PIXELFORMATDESCRIPTOR pfd;
BOOL err;
//Set8087CW($133F);
dch = GetDC(GetActiveWindow());
assert(dch!=NULL);
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize= sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion= 1;
pfd.dwFlags= PFD_GENERIC_ACCELERATED | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType= PFD_TYPE_RGBA;
pfd.cColorBits= colorBits;
pfd.cDepthBits= depthBits;
pfd.iLayerType= PFD_MAIN_PLANE;
pfd.cStencilBits= stencilBits;
iFormat= ChoosePixelFormat(dch, &pfd);
assert(iFormat!=0);
err= SetPixelFormat(dch, iFormat, &pfd);
assert(err);
glch= wglCreateContext(dch);
if(glch==NULL){
throw runtime_error("Error initing OpenGL device context");
}
makeCurrent();
}
void PlatformContextGl::end(){
int makeCurrentError= wglDeleteContext(glch);
assert(makeCurrentError);
}
void PlatformContextGl::makeCurrent(){
int makeCurrentError= wglMakeCurrent(dch, glch);
assert(makeCurrentError);
}
void PlatformContextGl::swapBuffers(){
int swapErr= SwapBuffers(dch);
assert(swapErr);
}
// ======================================
// Global Fcs
// ======================================
void createGlFontBitmaps(uint32 &base, const string &type, int size, int width, int charCount, FontMetrics &metrics){
HFONT font= CreateFont(
size, 0, 0, 0, width, 0, FALSE, FALSE, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
DEFAULT_PITCH, type.c_str());
assert(font!=NULL);
HDC dc= wglGetCurrentDC();
SelectObject(dc, font);
BOOL err= wglUseFontBitmaps(dc, 0, charCount, base);
FIXED one;
one.value= 1;
one.fract= 0;
FIXED zero;
zero.value= 0;
zero.fract= 0;
MAT2 mat2;
mat2.eM11= one;
mat2.eM12= zero;
mat2.eM21= zero;
mat2.eM22= one;
//metrics
GLYPHMETRICS glyphMetrics;
int errorCode= GetGlyphOutline(dc, 'a', GGO_METRICS, &glyphMetrics, 0, NULL, &mat2);
if(errorCode!=GDI_ERROR){
metrics.setHeight(static_cast<float>(glyphMetrics.gmBlackBoxY));
}
for(int i=0; i<charCount; ++i){
int errorCode= GetGlyphOutline(dc, i, GGO_METRICS, &glyphMetrics, 0, NULL, &mat2);
if(errorCode!=GDI_ERROR){
metrics.setWidth(i, static_cast<float>(glyphMetrics.gmCellIncX));
}
}
DeleteObject(font);
assert(err);
}
void createGlFontOutlines(uint32 &base, const string &type, int width, float depth, int charCount, FontMetrics &metrics){
HFONT font= CreateFont(
10, 0, 0, 0, width, 0, FALSE, FALSE, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
DEFAULT_PITCH, type.c_str());
assert(font!=NULL);
GLYPHMETRICSFLOAT *glyphMetrics= new GLYPHMETRICSFLOAT[charCount];
HDC dc= wglGetCurrentDC();
SelectObject(dc, font);
BOOL err= wglUseFontOutlines(dc, 0, charCount, base, 1000, depth, WGL_FONT_POLYGONS, glyphMetrics);
//load metrics
metrics.setHeight(glyphMetrics['a'].gmfBlackBoxY);
for(int i=0; i<charCount; ++i){
metrics.setWidth(i, glyphMetrics[i].gmfCellIncX);
}
DeleteObject(font);
delete [] glyphMetrics;
assert(err);
}
const char *getPlatformExtensions(const PlatformContextGl *pcgl){
typedef const char* (WINAPI * PROCTYPE) (HDC hdc);
PROCTYPE proc= reinterpret_cast<PROCTYPE>(getGlProcAddress("wglGetExtensionsStringARB"));
return proc==NULL? "": proc(pcgl->getHandle());
}
PROC getGlProcAddress(const char *procName){
PROC proc= wglGetProcAddress(procName);
assert(proc!=NULL);
return proc;
}
}}//end namespace

View File

@@ -1,75 +0,0 @@
#include "platform_menu.h"
#include <cassert>
#include "leak_dumper.h"
namespace Shared{ namespace Platform{
int MenuBase::nextId= 1000;
// =====================================================
// class MenuBase
// =====================================================
void MenuBase::init(const string &text){
this->text= text;
id= nextId++;
}
// =====================================================
// class Menu
// =====================================================
void Menu::create(Menu *parent){
handle= CreatePopupMenu();
for(int i= 0; i<children.size(); ++i){
children[i]->create(this);
}
if(parent!=NULL){
BOOL result = AppendMenu(parent->getHandle(), MF_POPUP | MF_STRING, reinterpret_cast<UINT_PTR>(handle), text.c_str());
assert(result);
}
}
void Menu::destroy(){
for(int i= 0; i<children.size(); ++i){
children[i]->destroy();
}
children.clear();
BOOL result = DestroyMenu(handle);
assert(result);
}
// =====================================================
// class MenuItem
// =====================================================
void MenuItem::create(Menu *parent){
isChecked= false;
this->parent = parent;
assert(parent!=NULL);
BOOL result = AppendMenu(parent->getHandle(), MF_STRING, static_cast<UINT>(id), text.c_str());
assert(result);
}
void MenuItem::setChecked(bool checked){
isChecked= checked;
CheckMenuItem(parent->getHandle(), id, checked? MF_CHECKED: MF_UNCHECKED);
}
// =====================================================
// class MenuSeparator
// =====================================================
void MenuSeparator::create(Menu *parent){
assert(parent!=NULL);
BOOL result = AppendMenu(parent->getHandle(), MF_SEPARATOR, static_cast<UINT>(id), NULL);
assert(result);
}
}}//end namespace

View File

@@ -1,482 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "platform_util.h"
#include <io.h>
#include <DbgHelp.h>
#include <cassert>
#include "util.h"
#include "conversion.h"
#include "leak_dumper.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <direct.h>
#define S_ISDIR(mode) ((mode) & _S_IFDIR)
using namespace Shared::Util;
using namespace std;
namespace Shared{ namespace Platform{
// =====================================================
// class PerformanceTimer
// =====================================================
void PerformanceTimer::init(int fps, int maxTimes){
int64 freq;
if(QueryPerformanceFrequency((LARGE_INTEGER*) &freq)==0){
throw runtime_error("Performance counters not supported");
}
times= 0;
this->maxTimes= maxTimes;
QueryPerformanceCounter((LARGE_INTEGER*) &lastTicks);
updateTicks= freq/fps;
}
bool PerformanceTimer::isTime(){
QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks);
if((thisTicks-lastTicks)>=updateTicks && times<maxTimes){
lastTicks+= updateTicks;
times++;
return true;
}
times= 0;
return false;
}
void PerformanceTimer::reset(){
QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks);
lastTicks= thisTicks;
}
// =====================================================
// class Chrono
// =====================================================
Chrono::Chrono(){
if(!QueryPerformanceFrequency((LARGE_INTEGER*) &freq)){
throw runtime_error("Performance counters not supported");
}
stopped= true;
accumCount= 0;
}
void Chrono::start(){
stopped= false;
QueryPerformanceCounter((LARGE_INTEGER*) &startCount);
}
void Chrono::stop(){
int64 endCount;
QueryPerformanceCounter((LARGE_INTEGER*) &endCount);
accumCount+= endCount-startCount;
stopped= true;
}
int64 Chrono::getMicros() const{
return queryCounter(1000000);
}
int64 Chrono::getMillis() const{
return queryCounter(1000);
}
int64 Chrono::getSeconds() const{
return queryCounter(1);
}
int64 Chrono::queryCounter(int multiplier) const{
if(stopped){
return multiplier*accumCount/freq;
}
else{
int64 endCount;
QueryPerformanceCounter((LARGE_INTEGER*) &endCount);
return multiplier*(accumCount+endCount-startCount)/freq;
}
}
// =====================================================
// class PlatformExceptionHandler
// =====================================================
PlatformExceptionHandler *PlatformExceptionHandler::thisPointer= NULL;
LONG WINAPI PlatformExceptionHandler::handler(LPEXCEPTION_POINTERS pointers){
HANDLE hFile = CreateFile(
thisPointer->dumpFileName.c_str(),
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0);
MINIDUMP_EXCEPTION_INFORMATION lExceptionInformation;
lExceptionInformation.ThreadId= GetCurrentThreadId();
lExceptionInformation.ExceptionPointers= pointers;
lExceptionInformation.ClientPointers= false;
MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MiniDumpNormal,
&lExceptionInformation,
NULL,
NULL );
thisPointer->handle();
return EXCEPTION_EXECUTE_HANDLER;
}
void PlatformExceptionHandler::install(string dumpFileName){
thisPointer= this;
this->dumpFileName= dumpFileName;
SetUnhandledExceptionFilter(handler);
}
// =====================================================
// class Misc
// =====================================================
//finds all filenames like path and stores them in resultys
void findAll(const string &path, vector<string> &results, bool cutExtension, bool errorOnNotFound){
int i= 0;
struct _finddata_t fi;
intptr_t handle;
char *cstr;
results.clear();
cstr= new char[path.length()+1];
strcpy(cstr, path.c_str());
if((handle=_findfirst(cstr,&fi))!=-1){
do{
if(!(strcmp(".", fi.name)==0 || strcmp("..", fi.name)==0)){
i++;
results.push_back(fi.name);
}
}
while(_findnext(handle, &fi)==0);
}
else if(errorOnNotFound == true){
throw runtime_error("Error opening files: "+ path);
}
if(i==0 && errorOnNotFound == true){
throw runtime_error("No files found: "+ path);
}
if(cutExtension){
for (int i=0; i<results.size(); ++i){
results.at(i)=cutLastExt(results.at(i));
}
}
delete [] cstr;
}
int isdir(const char *path)
{
struct stat stats;
return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
}
bool EndsWith(const string &str, const string& key)
{
size_t keylen = key.length();
size_t strlen = str.length();
if(keylen <= strlen)
return string::npos != str.rfind(key.c_str(),strlen - keylen, keylen);
else
return false;
}
//finds all filenames like path and gets their checksum of all files combined
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum) {
Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
/* MV - PORT THIS to win32
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
std::string mypath = path;
// Stupid win32 is searching for all files without extension when *. is specified as wildcard
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
mypath = mypath.substr(0, mypath.size() - 2);
mypath += "*";
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
//
//const char* begin = p;
//for( ; *p != 0; ++p) {
// // strip the path component
// if(*p == '/')
// begin = p+1;
//}
if(isdir(p) == 0)
{
bool addFile = true;
if(filterFileExt != "")
{
addFile = EndsWith(p, filterFileExt);
}
if(addFile)
{
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
checksum.addFile(p);
}
}
}
globfree(&globbuf);
// Look recursively for sub-folders
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
//
//const char* begin = p;
//for( ; *p != 0; ++p) {
// strip the path component
// if(*p == '/')
// begin = p+1;
//}
getFolderTreeContentsCheckSumRecursively(string(p) + "/*", filterFileExt, &checksum);
}
globfree(&globbuf);
*/
return checksum.getSum();
}
//finds all filenames like path and gets the checksum of each file
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap) {
vector<std::pair<string,int32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,int32> >() : *recursiveMap);
/* MV - PORT THIS to win32
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
std::string mypath = path;
// Stupid win32 is searching for all files without extension when *. is specified as wildcard
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
mypath = mypath.substr(0, mypath.size() - 2);
mypath += "*";
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
//
//const char* begin = p;
//for( ; *p != 0; ++p) {
// strip the path component
// if(*p == '/')
// begin = p+1;
//}
if(isdir(p) == 0)
{
bool addFile = true;
if(filterFileExt != "")
{
addFile = EndsWith(p, filterFileExt);
}
if(addFile)
{
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
Checksum checksum;
checksum.addFile(p);
checksumFiles.push_back(std::pair<string,int32>(p,checksum.getSum()));
}
}
}
globfree(&globbuf);
// Look recursively for sub-folders
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
if(res < 0) {
std::stringstream msg;
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw runtime_error(msg.str());
}
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
//
//const char* begin = p;
//for( ; *p != 0; ++p) {
// strip the path component
// if(*p == '/')
// begin = p+1;
//}
checksumFiles = getFolderTreeContentsCheckSumListRecursively(string(p) + "/*", filterFileExt, &checksumFiles);
}
globfree(&globbuf);
*/
return checksumFiles;
}
string extractDirectoryPathFromFile(string filename)
{
return filename.substr( 0, filename.rfind("/")+1 );
}
void createDirectoryPaths(string Path)
{
char DirName[256]="";
const char *path = Path.c_str();
char *dirName = DirName;
while(*path)
{
//if (('\\' == *path) || ('/' == *path))
if ('/' == *path)
{
//if (':' != *(path-1))
{
_mkdir(DirName);
}
}
*dirName++ = *path++;
*dirName = '\0';
}
_mkdir(DirName);
}
bool changeVideoMode(int resW, int resH, int colorBits, int refreshFrequency){
DEVMODE devMode;
for (int i=0; EnumDisplaySettings(NULL, i, &devMode) ;i++){
if (devMode.dmPelsWidth== resW &&
devMode.dmPelsHeight== resH &&
devMode.dmBitsPerPel== colorBits){
devMode.dmDisplayFrequency=refreshFrequency;
LONG result= ChangeDisplaySettings(&devMode, 0);
if(result == DISP_CHANGE_SUCCESSFUL){
return true;
}
else{
return false;
}
}
}
return false;
}
void restoreVideoMode(){
int dispChangeErr= ChangeDisplaySettings(NULL, 0);
assert(dispChangeErr==DISP_CHANGE_SUCCESSFUL);
}
void message(string message){
MessageBox(NULL, message.c_str(), "Message", MB_OK);
}
bool ask(string message){
return MessageBox(NULL, message.c_str(), "Confirmation", MB_YESNO)==IDYES;
}
void exceptionMessage(const exception &excp){
string message, title;
showCursor(true);
message+= "ERROR(S):\n\n";
message+= excp.what();
title= "Error: Unhandled Exception";
printf("Error detected with text: %s\n",message.c_str());
MessageBox(NULL, message.c_str(), title.c_str(), MB_ICONSTOP | MB_OK | MB_TASKMODAL);
}
int getScreenW(){
return GetSystemMetrics(SM_CXSCREEN);
}
int getScreenH(){
return GetSystemMetrics(SM_CYSCREEN);
}
void sleep(int millis){
Sleep(millis);
}
void showCursor(bool b){
ShowCursor(b);
}
bool isKeyDown(int virtualKey){
return (GetKeyState(virtualKey) & 0x8000) != 0;
}
}}//end namespace

View File

@@ -1,796 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2007 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "socket.h"
#include <stdexcept>
#include "conversion.h"
#include "leak_dumper.h"
#include <time.h>
#include <strstream>
#include <algorithm>
#define socklen_t int
using namespace std;
using namespace Shared::Util;
#define MAXHOSTNAME 254
//// Constants /////////////////////////////////////////////////////////
const int kBufferSize = 1024;
//// Statics ///////////////////////////////////////////////////////////
// List of Winsock error constants mapped to an interpretation string.
// Note that this list must remain sorted by the error constants'
// values, because we do a binary search on the list when looking up
// items.
static class ErrorEntry
{
public:
int nID;
const char* pcMessage;
ErrorEntry(int id, const char* pc = 0) : nID(id), pcMessage(pc)
{
}
bool operator<(const ErrorEntry& rhs)
{
return nID < rhs.nID;
}
} gaErrorList[] =
{
ErrorEntry(0, "No error"),
ErrorEntry(WSAEINTR, "Interrupted system call"),
ErrorEntry(WSAEBADF, "Bad file number"),
ErrorEntry(WSAEACCES, "Permission denied"),
ErrorEntry(WSAEFAULT, "Bad address"),
ErrorEntry(WSAEINVAL, "Invalid argument"),
ErrorEntry(WSAEMFILE, "Too many open sockets"),
ErrorEntry(WSAEWOULDBLOCK, "Operation would block"),
ErrorEntry(WSAEINPROGRESS, "Operation now in progress"),
ErrorEntry(WSAEALREADY, "Operation already in progress"),
ErrorEntry(WSAENOTSOCK, "Socket operation on non-socket"),
ErrorEntry(WSAEDESTADDRREQ, "Destination address required"),
ErrorEntry(WSAEMSGSIZE, "Message too long"),
ErrorEntry(WSAEPROTOTYPE, "Protocol wrong type for socket"),
ErrorEntry(WSAENOPROTOOPT, "Bad protocol option"),
ErrorEntry(WSAEPROTONOSUPPORT, "Protocol not supported"),
ErrorEntry(WSAESOCKTNOSUPPORT, "Socket type not supported"),
ErrorEntry(WSAEOPNOTSUPP, "Operation not supported on socket"),
ErrorEntry(WSAEPFNOSUPPORT, "Protocol family not supported"),
ErrorEntry(WSAEAFNOSUPPORT, "Address family not supported"),
ErrorEntry(WSAEADDRINUSE, "Address already in use"),
ErrorEntry(WSAEADDRNOTAVAIL, "Can't assign requested address"),
ErrorEntry(WSAENETDOWN, "Network is down"),
ErrorEntry(WSAENETUNREACH, "Network is unreachable"),
ErrorEntry(WSAENETRESET, "Net connection reset"),
ErrorEntry(WSAECONNABORTED, "Software caused connection abort"),
ErrorEntry(WSAECONNRESET, "Connection reset by peer"),
ErrorEntry(WSAENOBUFS, "No buffer space available"),
ErrorEntry(WSAEISCONN, "Socket is already connected"),
ErrorEntry(WSAENOTCONN, "Socket is not connected"),
ErrorEntry(WSAESHUTDOWN, "Can't send after socket shutdown"),
ErrorEntry(WSAETOOMANYREFS, "Too many references, can't splice"),
ErrorEntry(WSAETIMEDOUT, "Connection timed out"),
ErrorEntry(WSAECONNREFUSED, "Connection refused"),
ErrorEntry(WSAELOOP, "Too many levels of symbolic links"),
ErrorEntry(WSAENAMETOOLONG, "File name too long"),
ErrorEntry(WSAEHOSTDOWN, "Host is down"),
ErrorEntry(WSAEHOSTUNREACH, "No route to host"),
ErrorEntry(WSAENOTEMPTY, "Directory not empty"),
ErrorEntry(WSAEPROCLIM, "Too many processes"),
ErrorEntry(WSAEUSERS, "Too many users"),
ErrorEntry(WSAEDQUOT, "Disc quota exceeded"),
ErrorEntry(WSAESTALE, "Stale NFS file handle"),
ErrorEntry(WSAEREMOTE, "Too many levels of remote in path"),
ErrorEntry(WSASYSNOTREADY, "Network system is unavailable"),
ErrorEntry(WSAVERNOTSUPPORTED, "Winsock version out of range"),
ErrorEntry(WSANOTINITIALISED, "WSAStartup not yet called"),
ErrorEntry(WSAEDISCON, "Graceful shutdown in progress"),
ErrorEntry(WSAHOST_NOT_FOUND, "Host not found"),
ErrorEntry(WSANO_DATA, "No host data of that type was found")
};
bool operator<(const ErrorEntry& rhs1,const ErrorEntry& rhs2)
{
return rhs1.nID < rhs2.nID;
}
const int kNumMessages = sizeof(gaErrorList) / sizeof(ErrorEntry);
//// WSAGetLastErrorMessage ////////////////////////////////////////////
// A function similar in spirit to Unix's perror() that tacks a canned
// interpretation of the value of WSAGetLastError() onto the end of a
// passed string, separated by a ": ". Generally, you should implement
// smarter error handling than this, but for default cases and simple
// programs, this function is sufficient.
//
// This function returns a pointer to an internal static buffer, so you
// must copy the data from this function before you call it again. It
// follows that this function is also not thread-safe.
const char* WSAGetLastErrorMessage(const char* pcMessagePrefix,
int nErrorID /* = 0 */)
{
// Build basic error string
static char acErrorBuffer[256];
std::ostrstream outs(acErrorBuffer, sizeof(acErrorBuffer));
outs << pcMessagePrefix << ": ";
// Tack appropriate canned message onto end of supplied message
// prefix. Note that we do a binary search here: gaErrorList must be
// sorted by the error constant's value.
ErrorEntry* pEnd = gaErrorList + kNumMessages;
ErrorEntry Target(nErrorID ? nErrorID : WSAGetLastError());
ErrorEntry* it = std::lower_bound(gaErrorList, pEnd, Target);
if ((it != pEnd) && (it->nID == Target.nID))
{
outs << it->pcMessage;
}
else
{
// Didn't find error in list, so make up a generic one
outs << "unknown error";
}
outs << " (" << Target.nID << ")";
// Finish error message off and return it.
outs << std::ends;
acErrorBuffer[sizeof(acErrorBuffer) - 1] = '\0';
return acErrorBuffer;
}
namespace Shared{ namespace Platform{
bool Socket::enableDebugText = true;
// =====================================================
// class Ip
// =====================================================
Ip::Ip(){
bytes[0]= 0;
bytes[1]= 0;
bytes[2]= 0;
bytes[3]= 0;
}
Ip::Ip(unsigned char byte0, unsigned char byte1, unsigned char byte2, unsigned char byte3){
bytes[0]= byte0;
bytes[1]= byte1;
bytes[2]= byte2;
bytes[3]= byte3;
}
Ip::Ip(const string& ipString){
int offset= 0;
int byteIndex= 0;
for(byteIndex= 0; byteIndex<4; ++byteIndex){
int dotPos= ipString.find_first_of('.', offset);
bytes[byteIndex]= atoi(ipString.substr(offset, dotPos-offset).c_str());
offset= dotPos+1;
}
}
string Ip::getString() const{
return intToStr(bytes[0]) + "." + intToStr(bytes[1]) + "." + intToStr(bytes[2]) + "." + intToStr(bytes[3]);
}
// =====================================================
// class Socket
// =====================================================
Socket::SocketManager Socket::socketManager;
Socket::SocketManager::SocketManager(){
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 0);
WSAStartup(wVersionRequested, &wsaData);
//dont throw exceptions here, this is a static initializacion
printf("Winsock initialized.\n");
}
Socket::SocketManager::~SocketManager(){
WSACleanup();
printf("Winsock cleanup complete.\n");
}
Socket::Socket(SOCKET sock){
this->sock= sock;
}
Socket::Socket(){
sock= socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if(sock==INVALID_SOCKET){
throwException("Error creating socket");
}
}
Socket::~Socket()
{
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
disconnectSocket();
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
}
void Socket::disconnectSocket()
{
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
if(sock > 0)
{
::shutdown(sock,2);
::closesocket(sock);
sock = -1;
}
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
}
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
bool Socket::hasDataToRead(std::map<int,bool> &socketTriggeredList)
{
bool bResult = false;
if(socketTriggeredList.size() > 0)
{
/* Watch stdin (fd 0) to see when it has input. */
fd_set rfds;
FD_ZERO(&rfds);
int imaxsocket = 0;
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
itermap != socketTriggeredList.end(); itermap++)
{
int socket = itermap->first;
if(socket > 0)
{
FD_SET(socket, &rfds);
imaxsocket = max(socket,imaxsocket);
}
}
if(imaxsocket > 0)
{
/* Wait up to 0 seconds. */
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv);
if(retval < 0)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,retval,WSAGetLastError());
fprintf(stderr, "%s", szBuf);
}
else if(retval)
{
bResult = true;
if(Socket::enableDebugText) printf("In [%s::%s] select detected data imaxsocket = %d...\n",__FILE__,__FUNCTION__,imaxsocket);
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
itermap != socketTriggeredList.end(); itermap++)
{
int socket = itermap->first;
if (FD_ISSET(socket, &rfds))
{
if(Socket::enableDebugText) printf("In [%s] FD_ISSET true for socket %d...\n",__FUNCTION__,socket);
itermap->second = true;
}
else
{
itermap->second = false;
}
}
if(Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList->size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
}
}
}
return bResult;
}
bool Socket::hasDataToRead()
{
return Socket::hasDataToRead(sock) ;
}
bool Socket::hasDataToRead(int socket)
{
bool bResult = false;
if(socket > 0)
{
fd_set rfds;
struct timeval tv;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(socket, &rfds);
/* Wait up to 0 seconds. */
tv.tv_sec = 0;
tv.tv_usec = 0;
int retval = select(socket + 1, &rfds, NULL, NULL, &tv);
if(retval)
{
if (FD_ISSET(socket, &rfds))
{
bResult = true;
}
}
}
return bResult;
}
int Socket::getDataToRead(){
unsigned long size = 0;
//fd_set rfds;
//struct timeval tv;
//int retval;
/* Watch stdin (fd 0) to see when it has input. */
//FD_ZERO(&rfds);
//FD_SET(sock, &rfds);
/* Wait up to 0 seconds. */
//tv.tv_sec = 0;
//tv.tv_usec = 0;
//retval = select(sock + 1, &rfds, NULL, NULL, &tv);
//if(retval)
if(sock > 0)
{
/* ioctl isn't posix, but the following seems to work on all modern
* unixes */
int err= ioctlsocket(sock, FIONREAD, &size);
if(err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,WSAGetLastError());
printf("%s",szBuf);
//throwException(szBuf);
}
else if(err == 0)
{
//if(Socket::enableDebugText) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size);
}
}
return static_cast<int>(size);
}
int Socket::send(const void *data, int dataSize) {
int bytesSent= 0;
if(sock > 0)
{
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
}
if(bytesSent < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
char szBuf[1024]="";
sprintf(szBuf,"In [%s::%s] ERROR WRITING SOCKET DATA, err = %d WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesSent,WSAGetLastError());
//throwException(szBuf);
printf("%s",szBuf);
}
else if(bytesSent < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
{
printf("In [%s::%s] #1 WSAEWOULDBLOCK during send, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((bytesSent < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isWritable(true) == true)
{
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
printf("In [%s::%s] #2 WSAEWOULDBLOCK during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent);
}
}
}
if(bytesSent <= 0)
{
int iErr = WSAGetLastError();
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesSent,iErr);
printf("%s",szBuf);
//throwException(szBuf);
}
if(Socket::enableDebugText) printf("In [%s::%s] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,sock,bytesSent);
return static_cast<int>(bytesSent);
}
int Socket::receive(void *data, int dataSize)
{
int bytesReceived = 0;
if(sock > 0)
{
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
}
if(bytesReceived < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesReceived,WSAGetLastError());
//throwException(szBuf);
printf("%s",szBuf);
}
else if(bytesReceived < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
{
printf("In [%s::%s] #1 WSAEWOULDBLOCK during receive, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((bytesReceived < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isReadable() == true)
{
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
printf("In [%s::%s] #2 WSAEWOULDBLOCK during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived);
}
}
}
if(bytesReceived <= 0)
{
int iErr = WSAGetLastError();
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesReceived,iErr);
printf("%s",szBuf);
//throwException(szBuf);
}
return static_cast<int>(bytesReceived);
}
int Socket::peek(void *data, int dataSize){
int err = 0;
if(sock > 0)
{
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
}
if(err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] ERROR PEEKING SOCKET DATA error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,WSAGetLastError());
//throwException(szBuf);
printf("%s",szBuf);
}
else if(err < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
{
printf("In [%s::%s] #1 WSAEWOULDBLOCK during peek, trying again...\n",__FILE__,__FUNCTION__);
time_t tStartTimer = time(NULL);
while((err < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
{
if(Socket::isReadable() == true)
{
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
printf("In [%s::%s] #2 WSAEWOULDBLOCK during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err);
}
}
}
if(err <= 0)
{
int iErr = WSAGetLastError();
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking socket data, err = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,iErr);
printf("%s",szBuf);
//throwException(szBuf);
}
return static_cast<int>(err);
}
void Socket::setBlock(bool block){
u_long iMode= !
block;
int err= ioctlsocket(sock, FIONBIO, &iMode);
if(err==SOCKET_ERROR)
{
throwException("Error setting I/O mode for socket");
}
}
bool Socket::isReadable()
{
if(sock <= 0) return false;
TIMEVAL tv;
tv.tv_sec= 0;
tv.tv_usec= 1;
fd_set set;
FD_ZERO(&set);
FD_SET(sock, &set);
int i= select(sock+1, &set, NULL, NULL, &tv);
if(i==SOCKET_ERROR)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
printf("%s",szBuf);
}
//return (i == 1 && FD_ISSET(sock, &set));
return (i == 1);
}
bool Socket::isWritable(bool waitOnDelayedResponse)
{
if(sock <= 0) return false;
TIMEVAL tv;
tv.tv_sec= 0;
tv.tv_usec= 1;
fd_set set;
FD_ZERO(&set);
FD_SET(sock, &set);
bool result = false;
do
{
int i= select(sock+1, NULL, &set, NULL, &tv);
if(i==SOCKET_ERROR)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
printf("%s",szBuf);
waitOnDelayedResponse = false;
}
else if(i == 0)
{
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] TIMEOUT while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
printf("%s",szBuf);
if(waitOnDelayedResponse == false)
{
result = true;
}
}
else
{
result = true;
}
} while(waitOnDelayedResponse == true && result == false);
return result;
}
bool Socket::isConnected(){
//if the socket is not writable then it is not conencted
if(isWritable(false) == false)
{
return false;
}
//if the socket is readable it is connected if we can read a byte from it
if(isReadable())
{
char tmp;
int err = peek(&tmp, sizeof(tmp));
return (err > 0);
/*
int err = recv(sock, &tmp, sizeof(tmp), MSG_PEEK);
if(err <= 0 && WSAGetLastError() != WSAEWOULDBLOCK)
{
int iErr = WSAGetLastError();
disconnectSocket();
char szBuf[1024]="";
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,iErr);
printf("%s",szBuf);
return false;
}
*/
}
//otherwise the socket is connected
return true;
}
string Socket::getHostName() const{
const int strSize= 256;
char hostname[strSize];
gethostname(hostname, strSize);
return hostname;
}
string Socket::getIp() const{
hostent* info= gethostbyname(getHostName().c_str());
unsigned char* address;
if(info==NULL)
{
throwException("Error getting host by name");
}
address= reinterpret_cast<unsigned char*>(info->h_addr_list[0]);
if(address==NULL)
{
throwException("Error getting host ip");
}
return
intToStr(address[0]) + "." +
intToStr(address[1]) + "." +
intToStr(address[2]) + "." +
intToStr(address[3]);
}
void Socket::throwException(const string &str){
throw runtime_error("Network error: " + str+" (Code: " + intToStr(WSAGetLastError())+")");
}
// =====================================================
// class ClientSocket
// =====================================================
void ClientSocket::connect(const Ip &ip, int port)
{
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family= AF_INET;
addr.sin_addr.s_addr= inet_addr(ip.getString().c_str());
addr.sin_port= htons(port);
fprintf(stderr, "Connecting to host [%s] on port = %d\n", ip.getString().c_str(),port);
int err= ::connect(sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr));
if(err < 0)
{
char szBuf[1024]="";
sprintf(szBuf,"#2 Error connecting socket for IP: %s for Port: %d err = %d WSAGetLastError() = %d",ip.getString().c_str(),port,err,WSAGetLastError());
fprintf(stderr, "%s\n", WSAGetLastErrorMessage(szBuf));
//fprintf(stderr, "%s", szBuf);
if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK)
{
fd_set myset;
struct timeval tv;
int valopt;
socklen_t lon;
fprintf(stderr, "WSAEINPROGRESS or WSAEWOULDBLOCK in connect() - selecting\n");
do {
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&myset);
FD_SET(sock, &myset);
err = select(0, NULL, &myset, NULL, &tv);
if (err < 0 && WSAGetLastError() != WSAEWOULDBLOCK && WSAGetLastError() != WSAEWOULDBLOCK)
{
sprintf(szBuf, "Error connecting %d\n", WSAGetLastError());
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
else if (err > 0) {
// Socket selected for write
lon = sizeof(int);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)(&valopt), &lon) < 0)
{
sprintf(szBuf, "Error in getsockopt() %d\n", WSAGetLastError());
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
// Check the value returned...
if (valopt)
{
sprintf(szBuf, "Error in delayed connection() %d\n", valopt);
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
break;
}
fprintf(stderr, "Apparent recovery for connection sock = %d, err = %d, WSAGetLastError() = %d\n",sock,err,WSAGetLastError());
break;
}
else
{
sprintf(szBuf, "Timeout in select() - Cancelling!\n");
//throwException(szBuf);
fprintf(stderr, "%s", szBuf);
disconnectSocket();
break;
}
} while (1);
}
if(err < 0)
{
fprintf(stderr, "In [%s::%s] Before END sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,WSAGetLastError());
//throwException(szBuf);
disconnectSocket();
}
fprintf(stderr, "Valid recovery for connection sock = %d, err = %d, WSAGetLastError() = %d\n",sock,err,WSAGetLastError());
}
else
{
fprintf(stderr, "Connected to host [%s] on port = %d sock = %d err = %d", ip.getString().c_str(),port,err);
}
}
// =====================================================
// class ServerSocket
// =====================================================
void ServerSocket::bind(int port){
//sockaddr structure
sockaddr_in addr;
addr.sin_family= AF_INET;
addr.sin_addr.s_addr= INADDR_ANY;
addr.sin_port= htons(port);
int err= ::bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
if(err==SOCKET_ERROR){
throwException("Error binding socket");
}
}
void ServerSocket::listen(int connectionQueueSize){
int err= ::listen(sock, connectionQueueSize);
if(err==SOCKET_ERROR){
throwException("Error listening socket");
}
}
Socket *ServerSocket::accept(){
SOCKET newSock= ::accept(sock, NULL, NULL);
if(newSock==INVALID_SOCKET){
if(WSAGetLastError()==WSAEWOULDBLOCK){
return NULL;
}
throwException("Error accepting socket connection");
}
return new Socket(newSock);
}
}}//end namespace

View File

@@ -1,66 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "thread.h"
#include "leak_dumper.h"
namespace Shared{ namespace Platform{
// =====================================================
// class Threads
// =====================================================
ThreadId Thread::nextThreadId= threadIdBase;
void Thread::start(){
threadHandle= CreateThread(NULL, 0, beginExecution, this, 0, &nextThreadId);
nextThreadId++;
}
void Thread::setPriority(Thread::Priority threadPriority){
SetThreadPriority(threadHandle, threadPriority);
}
DWORD WINAPI Thread::beginExecution(void *param){
static_cast<Thread*>(param)->execute();
return 0;
}
void Thread::suspend(){
SuspendThread(threadHandle);
}
void Thread::resume(){
ResumeThread(threadHandle);
}
// =====================================================
// class Mutex
// =====================================================
Mutex::Mutex(){
InitializeCriticalSection(&mutex);
}
Mutex::~Mutex(){
DeleteCriticalSection(&mutex);
}
void Mutex::p(){
EnterCriticalSection(&mutex);
}
void Mutex::v(){
LeaveCriticalSection(&mutex);
}
}}//end namespace

View File

@@ -1,396 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "window.h"
#include <cassert>
#include "control.h"
#include "conversion.h"
#include "platform_util.h"
#include "leak_dumper.h"
using namespace Shared::Util;
using namespace std;
namespace Shared{ namespace Platform{
// =====================================================
// class Window
// =====================================================
const DWORD Window::fullscreenStyle= WS_POPUP | WS_OVERLAPPED;
const DWORD Window::windowedFixedStyle= WS_CAPTION | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_SYSMENU;
const DWORD Window::windowedResizeableStyle= WS_SIZEBOX | WS_CAPTION | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_SYSMENU;
int Window::nextClassName= 0;
Window::WindowMap Window::createdWindows;
// ===================== PUBLIC ========================
Window::Window(){
handle= 0;
style= windowedFixedStyle;
exStyle= 0;
ownDc= false;
x= 0;
y= 0;
w= 100;
h= 100;
}
Window::~Window(){
if(handle!=0){
DestroyWindow(handle);
handle= 0;
BOOL b= UnregisterClass(className.c_str(), GetModuleHandle(NULL));
assert(b);
}
}
//static
bool Window::handleEvent(){
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
if(msg.message==WM_QUIT){
return false;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return true;
}
string Window::getText(){
if(handle==0){
return text;
}
char c[255];
SendMessage(handle, WM_GETTEXT, 255, (LPARAM) c);
return string(c);
}
int Window::getClientW(){
RECT r;
GetClientRect(handle, &r);
return r.right;
}
int Window::getClientH(){
RECT r;
GetClientRect(handle, &r);
return r.bottom;
}
float Window::getAspect(){
return static_cast<float>(getClientH())/getClientW();
}
void Window::setText(string text){
this->text= text;
if(handle!=0){
SendMessage(handle, WM_SETTEXT, 0, (LPARAM) text.c_str());
}
}
void Window::setSize(int w, int h){
if(windowStyle != wsFullscreen){
RECT rect;
rect.left= 0;
rect.top= 0;
rect.bottom= h;
rect.right= w;
AdjustWindowRect(&rect, style, FALSE);
w= rect.right-rect.left;
h= rect.bottom-rect.top;
}
this->w= w;
this->h= h;
if(handle!=0){
MoveWindow(handle, x, y, w, h, FALSE);
UpdateWindow(handle);
}
}
void Window::setPos(int x, int y){
this->x= x;
this->y= y;
if(handle!=0){
MoveWindow(handle, x, y, w, h, FALSE);
}
}
void Window::setEnabled(bool enabled){
EnableWindow(handle, static_cast<BOOL>(enabled));
}
void Window::setVisible(bool visible){
if (visible){
ShowWindow(handle, SW_SHOW);
UpdateWindow(handle);
}
else{
ShowWindow(handle, SW_HIDE);
UpdateWindow(handle);
}
}
void Window::setStyle(WindowStyle windowStyle){
this->windowStyle= windowStyle;
switch(windowStyle){
case wsFullscreen:
style= fullscreenStyle;
exStyle= WS_EX_APPWINDOW;
ownDc= true;
break;
case wsWindowedFixed:
style= windowedFixedStyle;
exStyle= 0;
ownDc= false;
break;
case wsWindowedResizeable:
style= windowedResizeableStyle;
exStyle= 0;
ownDc= false;
break;
}
if(handle!=0){
setVisible(false);
int err= SetWindowLong(handle, GWL_STYLE, style);
assert(err);
setVisible(true);
UpdateWindow(handle);
}
}
void Window::create(){
registerWindow();
createWindow();
}
void Window::minimize(){
ShowWindow(getHandle(), SW_MINIMIZE);
}
void Window::maximize(){
ShowWindow(getHandle(), SW_MAXIMIZE);
}
void Window::restore(){
ShowWindow(getHandle(), SW_RESTORE);
}
void Window::showPopupMenu(Menu *menu, int x, int y){
RECT rect;
GetWindowRect(handle, &rect);
TrackPopupMenu(menu->getHandle(), TPM_LEFTALIGN | TPM_TOPALIGN, rect.left+x, rect.top+y, 0, handle, NULL);
}
void Window::destroy(){
DestroyWindow(handle);
BOOL b= UnregisterClass(className.c_str(), GetModuleHandle(NULL));
assert(b);
handle= 0;
}
// ===================== PRIVATE =======================
LRESULT CALLBACK Window::eventRouter(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
Window *eventWindow;
WindowMap::iterator it;
it= createdWindows.find(hwnd);
if(it==createdWindows.end()){
return DefWindowProc(hwnd, msg, wParam, lParam);
}
eventWindow= it->second;
POINT mousePos;
RECT windowRect;
GetWindowRect(eventWindow->getHandle(), &windowRect);
mousePos.x = LOWORD(lParam) - windowRect.left;
mousePos.y = HIWORD(lParam) -windowRect.top;
ClientToScreen(eventWindow->getHandle(), &mousePos);
switch(msg){
case WM_CREATE:
eventWindow->eventCreate();
break;
case WM_LBUTTONDOWN:
eventWindow->eventMouseDown(mousePos.x, mousePos.y, mbLeft);
break;
case WM_RBUTTONDOWN:
eventWindow->eventMouseDown(mousePos.x, mousePos.y, mbRight);
break;
case WM_LBUTTONUP:
eventWindow->eventMouseUp(mousePos.x, mousePos.y, mbLeft);
break;
case WM_RBUTTONUP:
eventWindow->eventMouseUp(mousePos.x, mousePos.y, mbRight);
break;
case WM_LBUTTONDBLCLK:
eventWindow->eventMouseDoubleClick(mousePos.x, mousePos.y, mbLeft);
break;
case WM_RBUTTONDBLCLK:
eventWindow->eventMouseDoubleClick(mousePos.x, mousePos.y, mbRight);
break;
case WM_MOUSEMOVE:
{
MouseState ms;
ms.leftMouse= (wParam & MK_LBUTTON) ? true : false;
ms.rightMouse= (wParam & MK_RBUTTON) ? true : false;
ms.centerMouse= (wParam & MK_MBUTTON) ? true : false;
eventWindow->eventMouseMove(mousePos.x, mousePos.y, &ms);
}
break;
case WM_KEYDOWN:
eventWindow->eventKeyDown(static_cast<char>(wParam));
break;
case WM_KEYUP:
eventWindow->eventKeyUp(static_cast<char>(wParam));
break;
case WM_CHAR:
eventWindow->eventKeyPress(static_cast<char>(wParam));
break;
case WM_COMMAND:
if(HIWORD(wParam)==0){
eventWindow->eventMenu(LOWORD(wParam));
}
break;
case WM_ACTIVATE:
eventWindow->eventActivate(wParam!=WA_INACTIVE);
break;
case WM_MOVE:
{
RECT rect;
GetWindowRect(eventWindow->getHandle(), &rect);
eventWindow->x= rect.left;
eventWindow->y= rect.top;
eventWindow->w= rect.right-rect.left;
eventWindow->h= rect.bottom-rect.top;
}
break;
case WM_SIZE:
{
RECT rect;
GetWindowRect(eventWindow->getHandle(), &rect);
eventWindow->x= rect.left;
eventWindow->y= rect.top;
eventWindow->w= rect.right-rect.left;
eventWindow->h= rect.bottom-rect.top;
eventWindow->eventResize(static_cast<SizeState>(wParam));
}
break;
case WM_SIZING:
eventWindow->eventResize();
break;
case WM_PAINT:
eventWindow->eventPaint();
break;
case WM_CLOSE:
eventWindow->eventClose();
break;
case WM_DESTROY:
eventWindow->eventDestroy();
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int Window::getNextClassName(){
return ++nextClassName;
}
void Window::registerWindow(WNDPROC wndProc){
WNDCLASSEX wc;
this->className= "Window" + intToStr(Window::getNextClassName());
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_DBLCLKS | (ownDc? CS_OWNDC : 0);
wc.lpfnWndProc = wndProc==NULL? eventRouter: wndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = this->className.c_str();
wc.hIconSm = NULL;
int registerClassErr=RegisterClassEx(&wc);
assert(registerClassErr);
}
void Window::createWindow(LPVOID creationData){
handle = CreateWindowEx(
exStyle,
className.c_str(),
text.c_str(),
style,
x, y, w, h,
NULL, NULL, GetModuleHandle(NULL), creationData);
createdWindows.insert(pair<WindowHandle, Window*>(handle, this));
eventRouter(handle, WM_CREATE, 0, 0);
assert(handle != NULL);
ShowWindow(handle, SW_SHOW);
UpdateWindow(handle);
}
}}//end namespace

View File

@@ -1,44 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "window_gl.h"
#include "gl_wrap.h"
#include "graphics_interface.h"
#include "leak_dumper.h"
using namespace Shared::Graphics;
namespace Shared{ namespace Platform{
// =====================================================
// class WindowGl
// =====================================================
void WindowGl::initGl(int colorBits, int depthBits, int stencilBits){
context.setColorBits(colorBits);
context.setDepthBits(depthBits);
context.setStencilBits(stencilBits);
context.init();
}
void WindowGl::makeCurrentGl(){
GraphicsInterface::getInstance().setCurrentContext(&context);
context.makeCurrent();
}
void WindowGl::swapBuffersGl(){
context.swapBuffers();
}
}}//end namespace

View File

@@ -1,489 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "sound_player_ds8.h"
#include <cassert>
#include <cmath>
#include "util.h"
#include "leak_dumper.h"
namespace Shared{ namespace Sound{ namespace Ds8{
using namespace Util;
// =====================================================
// class SoundBuffer
// =====================================================
// ===================== PUBLIC ========================
SoundBuffer::SoundBuffer(){
dsBuffer= NULL;
sound= NULL;
}
bool SoundBuffer::isFree(){
if(dsBuffer==NULL){
return true;
}
DWORD status;
dsBuffer->GetStatus(&status);
if(status & DSBSTATUS_BUFFERLOST){
end();
return true;
}
return false;
}
bool SoundBuffer::isReady(){
DWORD status;
dsBuffer->GetStatus(&status);
if ((status & DSBSTATUS_PLAYING) || (status & DSBSTATUS_BUFFERLOST)){
return false;
}
return true;
}
// ==================== PROTECTED ======================
void SoundBuffer::createDsBuffer(IDirectSound8 *dsObject){
IDirectSoundBuffer *buffer;
const SoundInfo *soundInfo= sound->getInfo();
//format
WAVEFORMATEX format;
format.wFormatTag= WAVE_FORMAT_PCM;
format.nChannels= soundInfo->getChannels();
format.nSamplesPerSec= soundInfo->getSamplesPerSecond();
format.nAvgBytesPerSec= (soundInfo->getBitsPerSample() * soundInfo->getSamplesPerSecond() * soundInfo->getChannels())/8;
format.nBlockAlign= (soundInfo->getChannels() * soundInfo->getBitsPerSample())/8;
format.wBitsPerSample= soundInfo->getBitsPerSample();
format.cbSize= 0;
//buffer desc
DSBUFFERDESC dsBufferDesc;
memset(&dsBufferDesc, 0, sizeof(DSBUFFERDESC));
dsBufferDesc.dwSize= sizeof(DSBUFFERDESC);
dsBufferDesc.dwFlags= DSBCAPS_CTRLVOLUME;
dsBufferDesc.dwBufferBytes= size;
dsBufferDesc.lpwfxFormat= &format;
//create buffer
HRESULT hr= dsObject->CreateSoundBuffer(&dsBufferDesc, &buffer, NULL);
if (hr!=DS_OK){
throw runtime_error("Failed to create direct sound buffer");
}
//query dx8 interface
hr = buffer->QueryInterface(IID_IDirectSoundBuffer8, (void**) &dsBuffer);
buffer->Release();
if (hr!=S_OK){
throw runtime_error("Failed to create direct sound 8 static buffer");
}
}
// =====================================================
// class StaticBuffer
// =====================================================
// ===================== PUBLIC ========================
void StaticSoundBuffer::init(IDirectSound8 *dsObject, Sound *sound){
if(this->sound==NULL){
this->sound= sound;
this->size= sound->getInfo()->getSize();
createDsBuffer(dsObject);
dsBuffer->SetCurrentPosition(0);
fillDsBuffer();
}
}
void StaticSoundBuffer::end(){
dsBuffer->Stop();
dsBuffer->Release();
dsBuffer= NULL;
sound= NULL;
}
void StaticSoundBuffer::play(){
dsBuffer->SetVolume(dsVolume(sound->getVolume()));
dsBuffer->Play(0, 0, 0);
}
// ===================== PRIVATE =======================
void StaticSoundBuffer::fillDsBuffer(){
void * writePointer;
unsigned long size;
//lock
HRESULT hr= dsBuffer->Lock(0, 0, &writePointer, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER);
if (hr!=DS_OK){
throw runtime_error("Failed to Lock direct sound buffer");
}
//copy memory
memcpy(writePointer, getStaticSound()->getSamples(), size);
//unlock
hr= dsBuffer->Unlock(writePointer, size, NULL, 0);
if (hr!=DS_OK){
throw runtime_error("Failed to Unlock direct sound buffer");
}
}
// =====================================================
// class StrBuffer
// =====================================================
// ===================== PUBLIC ========================
StrSoundBuffer::StrSoundBuffer(){
state= sFree;
}
void StrSoundBuffer::init(IDirectSound8 *dsObject, Sound *sound, uint32 strBufferSize){
state= sStopped;
if(this->sound==NULL){
this->sound= sound;
this->size= strBufferSize;
createDsBuffer(dsObject);
dsBuffer->SetCurrentPosition(0);
fillDsBuffer();
}
else if(this->sound!=sound){
this->sound= sound;
this->size= strBufferSize;
dsBuffer->SetCurrentPosition(0);
fillDsBuffer();
}
}
void StrSoundBuffer::end(){
state= sFree;
dsBuffer->Stop();
dsBuffer->Release();
dsBuffer= NULL;
sound= NULL;
}
void StrSoundBuffer::play(int64 fadeOn){
assert(state==sStopped);
lastPlayCursor= 0;
if(fadeOn==0){
state= sPlaying;
dsBuffer->SetVolume(dsVolume(sound->getVolume()));
}
else{
this->fade= fadeOn;
state= sFadingOn;
chrono.start();
dsBuffer->SetVolume(dsVolume(0.f));
}
dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
}
void StrSoundBuffer::update(){
switch(state){
case sFadingOn:
if(chrono.getMillis()>fade){
dsBuffer->SetVolume(dsVolume(sound->getVolume()));
state= sPlaying;
}
else{
dsBuffer->SetVolume(dsVolume(sound->getVolume()*(static_cast<float>(chrono.getMillis())/fade)));
}
refreshDsBuffer();
break;
case sFadingOff:
if(chrono.getMillis()>fade){
state= sStopped;
dsBuffer->Stop();
}
else{
dsBuffer->SetVolume(dsVolume(sound->getVolume()*(1.0f-static_cast<float>(chrono.getMillis())/fade)));
refreshDsBuffer();
}
break;
case sPlaying:
dsBuffer->SetVolume(dsVolume(sound->getVolume()));
refreshDsBuffer();
break;
default:
break;
}
}
void StrSoundBuffer::stop(int64 fadeOff){
if(fadeOff==0){
dsBuffer->Stop();
state= sStopped;
}
else{
this->fade= fadeOff;
state= sFadingOff;
chrono.start();
}
}
// ===================== PRIVATE =======================
void StrSoundBuffer::fillDsBuffer(){
void * writePointer;
unsigned long size;
//lock
HRESULT hr= dsBuffer->Lock(0, 0, &writePointer, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER);
if (hr!=DS_OK){
throw runtime_error("Failed to Lock direct sound buffer");
}
//copy memory
readChunk(writePointer, size);
//unlock
hr= dsBuffer->Unlock(writePointer, size, NULL, 0 );
if (hr!=DS_OK){
throw runtime_error("Failed to Unlock direct sound buffer");
}
}
void StrSoundBuffer::refreshDsBuffer(){
void *writePointer1, *writePointer2;
DWORD size1, size2;
DWORD playCursor;
DWORD bytesToLock;
DWORD status;
dsBuffer->GetStatus(&status);
assert(!(status & DSBSTATUS_BUFFERLOST));
HRESULT hr= dsBuffer->GetCurrentPosition(&playCursor, NULL);
if(hr!=DS_OK){
throw runtime_error("Failed to Lock query play position");
}
//compute bytes to lock
if(playCursor>=lastPlayCursor){
bytesToLock= playCursor - lastPlayCursor;
}
else{
bytesToLock= size - (lastPlayCursor - playCursor);
}
//copy data
if(bytesToLock>0){
//lock
HRESULT hr=dsBuffer->Lock(lastPlayCursor, bytesToLock, &writePointer1, &size1, &writePointer2, &size2, 0);
if (hr!=DS_OK){
throw runtime_error("Failed to Lock direct sound buffer");
}
//copy memory
assert(size1+size2==bytesToLock);
readChunk(writePointer1, size1);
readChunk(writePointer2, size2);
//unlock
hr= dsBuffer->Unlock(writePointer1, size1, writePointer2, size2);
if (hr!=DS_OK){
throw runtime_error("Failed to Unlock direct sound buffer");
}
}
lastPlayCursor= playCursor;
}
void StrSoundBuffer::readChunk(void *writePointer, uint32 size){
StrSound *s= getStrSound();
uint32 readSize= s->read(static_cast<int8*>(writePointer), size);
if(readSize<size){
StrSound *next= s->getNext()==NULL? s: s->getNext();
next->restart();
next->read(&static_cast<int8*>(writePointer)[readSize], size-readSize);
next->setVolume(s->getVolume());
sound= next;
}
}
// =====================================================
// class SoundPlayerDs8
// =====================================================
SoundPlayerDs8::SoundPlayerDs8(){
dsObject= NULL;
}
void SoundPlayerDs8::init(const SoundPlayerParams *params){
HRESULT hr;
this->params= *params;
//reserve memory for buffers
staticSoundBuffers.resize(params->staticBufferCount);
strSoundBuffers.resize(params->strBufferCount);
//create object
hr=DirectSoundCreate8(NULL, &dsObject, NULL);
if (hr!=DS_OK){
throw runtime_error("Can't create direct sound object");
}
//Set cooperative level
hr= dsObject->SetCooperativeLevel(GetActiveWindow(), DSSCL_PRIORITY);
if (hr!=DS_OK){
throw runtime_error("Can't set cooperative level of dsound");
}
}
void SoundPlayerDs8::end(){
}
void SoundPlayerDs8::play(StaticSound *staticSound){
int bufferIndex= -1;
assert(staticSound!=NULL);
//if buffer found, play the sound
if (findStaticBuffer(staticSound, &bufferIndex)){
staticSoundBuffers[bufferIndex].init(dsObject, staticSound);
staticSoundBuffers[bufferIndex].play();
}
}
void SoundPlayerDs8::play(StrSound *strSound, int64 fadeOn){
int bufferIndex= -1;
//play sound if buffer found
if(findStrBuffer(strSound, &bufferIndex)){
strSoundBuffers[bufferIndex].init(dsObject, strSound, params.strBufferSize);
strSoundBuffers[bufferIndex].play(fadeOn);
}
}
void SoundPlayerDs8::stop(StrSound *strSound, int64 fadeOff){
//find the buffer with this sound and stop it
for(int i= 0; i<params.strBufferCount; ++i){
if(strSoundBuffers[i].getSound()==strSound){
strSoundBuffers[i].stop(fadeOff);
}
}
}
void SoundPlayerDs8::stopAllSounds(){
for(int i=0; i<params.strBufferCount; ++i){
if(!strSoundBuffers[i].isFree()){
strSoundBuffers[i].stop(0);
strSoundBuffers[i].end();
}
}
for(int i=0; i<params.staticBufferCount; ++i){
if(!staticSoundBuffers[i].isFree()){
staticSoundBuffers[i].end();
}
}
}
void SoundPlayerDs8::updateStreams(){
for(int i=0; i<params.strBufferCount; ++i){
strSoundBuffers[i].update();
}
}
// ===================== PRIVATE =======================
bool SoundPlayerDs8::findStaticBuffer(Sound *sound, int *bufferIndex){
bool bufferFound= false;
assert(sound!=NULL);
//1st: we try fo find a stopped buffer with the same sound
for(int i=0; i<staticSoundBuffers.size(); ++i){
if(sound==staticSoundBuffers[i].getSound() && staticSoundBuffers[i].isReady()){
*bufferIndex= i;
bufferFound= true;
break;
}
}
//2nd: we try to find a free buffer
if(!bufferFound){
for(uint32 i=0; i<staticSoundBuffers.size(); ++i){
if(staticSoundBuffers[i].isFree()){
*bufferIndex= i;
bufferFound= true;
break;
}
}
}
//3rd: we try to find a stopped buffer
if(!bufferFound){
for(int i=0; i<staticSoundBuffers.size(); ++i){
if(staticSoundBuffers[i].isReady()){
staticSoundBuffers[i].end();
*bufferIndex= i;
bufferFound= true;
break;
}
}
}
return bufferFound;
}
bool SoundPlayerDs8::findStrBuffer(Sound *sound, int *bufferIndex){
bool bufferFound= false;
assert(sound!=NULL);
assert(sound->getVolume()<=1.0f && sound->getVolume()>=0.0f);
//We try to find a free or ready buffer
if(!bufferFound){
for(uint32 i=0; i<strSoundBuffers.size(); ++i){
if(strSoundBuffers[i].isFree() || strSoundBuffers[i].isReady()){
*bufferIndex= i;
bufferFound= true;
break;
}
}
}
return bufferFound;
}
// =====================================================
// Misc
// =====================================================
long dsVolume(float floatVolume){
float correctedVol= log10f(floatVolume*9.f+1.f);
long vol= static_cast<long>(DSBVOLUME_MIN+correctedVol*(DSBVOLUME_MAX-DSBVOLUME_MIN));
return clamp(vol, DSBVOLUME_MIN, DSBVOLUME_MAX);
}
}}}//end namespace

View File

@@ -1,429 +0,0 @@
//This file is part of Glest Shared Library (www.glest.org)
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//You can redistribute this code and/or modify it under
//the terms of the GNU General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
#include "sound_player_openal.h"
#include <cassert>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include "platform_util.h"
#include "util.h"
#include "leak_dumper.h"
namespace Shared{ namespace Sound{ namespace OpenAL{
using namespace Util;
SoundSource::SoundSource()
{
alGenSources(1, &source);
SoundPlayerOpenAL::checkAlError("Couldn't create audio source: ");
}
SoundSource::~SoundSource()
{
stop();
alDeleteSources(1, &source);
}
bool SoundSource::playing()
{
ALint state = AL_PLAYING;
alGetSourcei(source, AL_SOURCE_STATE, &state);
return state != AL_STOPPED;
}
void SoundSource::stop()
{
alSourceStop(source);
alSourcei(source, AL_BUFFER, AL_NONE);
SoundPlayerOpenAL::checkAlError("Problem stopping audio source: ");
}
ALenum SoundSource::getFormat(Sound* sound)
{
if(sound->getInfo()->getChannels() == 2) {
if(sound->getInfo()->getBitsPerSample() == 16)
return AL_FORMAT_STEREO16;
else if(sound->getInfo()->getBitsPerSample() == 8)
return AL_FORMAT_STEREO8;
else
throw std::runtime_error("Sample format not supported");
} else if(sound->getInfo()->getChannels() == 1) {
if(sound->getInfo()->getBitsPerSample() == 16)
return AL_FORMAT_MONO16;
else if(sound->getInfo()->getBitsPerSample() == 8)
return AL_FORMAT_MONO8;
else
throw std::runtime_error("Sample format not supported");
}
throw std::runtime_error("Sample format not supported");
}
//---------------------------------------------------------------------------
StaticSoundSource::StaticSoundSource() {
bufferAllocated = false;
}
StaticSoundSource::~StaticSoundSource() {
if(bufferAllocated) {
stop();
alDeleteBuffers(1, &buffer);
}
}
void StaticSoundSource::play(StaticSound* sound)
{
if(bufferAllocated) {
stop();
alDeleteBuffers(1, &buffer);
}
ALenum format = getFormat(sound);
alGenBuffers(1, &buffer);
SoundPlayerOpenAL::checkAlError("Couldn't create audio buffer: ");
bufferAllocated = true;
alBufferData(buffer, format, sound->getSamples(),
static_cast<ALsizei> (sound->getInfo()->getSize()),
static_cast<ALsizei> (sound->getInfo()->getSamplesPerSecond()));
SoundPlayerOpenAL::checkAlError("Couldn't fill audio buffer: ");
alSourcei(source, AL_BUFFER, buffer);
alSourcef(source, AL_GAIN, sound->getVolume());
alSourcePlay(source);
SoundPlayerOpenAL::checkAlError("Couldn't start audio source: ");
}
StreamSoundSource::StreamSoundSource()
{
sound = 0;
alGenBuffers(STREAMFRAGMENTS, buffers);
SoundPlayerOpenAL::checkAlError("Couldn't allocate audio buffers: ");
}
StreamSoundSource::~StreamSoundSource()
{
stop();
alDeleteBuffers(STREAMFRAGMENTS, buffers);
SoundPlayerOpenAL::checkAlError("Couldn't delete audio buffers: ");
}
void StreamSoundSource::stop()
{
sound = 0;
SoundSource::stop();
}
void StreamSoundSource::stop(int64 fadeoff)
{
if(fadeoff > 0) {
fadeState = FadingOff;
fade = fadeoff;
chrono.start();
} else {
stop();
}
}
void StreamSoundSource::play(StrSound* sound, int64 fadeon)
{
stop();
this->sound = sound;
format = getFormat(sound);
for(size_t i = 0; i < STREAMFRAGMENTS; ++i) {
fillBufferAndQueue(buffers[i]);
}
if(fadeon > 0) {
alSourcef(source, AL_GAIN, 0);
fadeState = FadingOn;
fade = fadeon;
chrono.start();
} else {
fadeState = NoFading;
alSourcef(source, AL_GAIN, sound->getVolume());
}
alSourcePlay(source);
}
void StreamSoundSource::update()
{
if(sound == 0)
return;
ALint processed = 0;
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
while(processed > 0) {
processed--;
ALuint buffer;
alSourceUnqueueBuffers(source, 1, &buffer);
SoundPlayerOpenAL::checkAlError("Couldn't unqueu audio buffer: ");
if(!fillBufferAndQueue(buffer))
break;
}
// we might have to restart the source if we had a buffer underrun
if(!playing()) {
std::cerr
<< "Restarting audio source because of buffer underrun.\n";
alSourcePlay(source);
SoundPlayerOpenAL::checkAlError("Couldn't restart audio source: ");
}
// handle fading
switch(fadeState) {
case FadingOn:
if(chrono.getMillis() > fade) {
alSourcef(source, AL_GAIN, sound->getVolume());
fadeState = NoFading;
} else {
alSourcef(source, AL_GAIN, sound->getVolume() *
static_cast<float> (chrono.getMillis())/fade);
}
break;
case FadingOff:
if(chrono.getMillis() > fade) {
stop();
} else {
alSourcef(source, AL_GAIN, sound->getVolume() *
(1.0f - static_cast<float>(chrono.getMillis())/fade));
}
break;
default:
break;
}
}
bool StreamSoundSource::fillBufferAndQueue(ALuint buffer)
{
// fill buffer
int8* bufferdata = new int8[STREAMFRAGMENTSIZE];
uint32 bytesread = 0;
do {
bytesread += sound->read(bufferdata + bytesread,
STREAMFRAGMENTSIZE - bytesread);
if(bytesread < STREAMFRAGMENTSIZE) {
StrSound* next = sound->getNext();
if(next == 0)
next = sound;
next->restart();
next->setVolume(sound->getVolume());
sound = next;
}
} while(bytesread < STREAMFRAGMENTSIZE);
alBufferData(buffer, format, bufferdata, STREAMFRAGMENTSIZE,
sound->getInfo()->getSamplesPerSecond());
delete[] bufferdata;
SoundPlayerOpenAL::checkAlError("Couldn't refill audio buffer: ");
alSourceQueueBuffers(source, 1, &buffer);
SoundPlayerOpenAL::checkAlError("Couldn't queue audio buffer: ");
return true;
}
// ================================
// Sound Player OpenAL
// ================================
SoundPlayerOpenAL::SoundPlayerOpenAL() {
device = 0;
}
SoundPlayerOpenAL::~SoundPlayerOpenAL() {
end();
}
void SoundPlayerOpenAL::printOpenALInfo()
{
std::cout << "OpenAL Vendor: " << alGetString(AL_VENDOR) << "\n"
<< "OpenAL Version: " << alGetString(AL_VERSION) << "\n"
<< "OpenAL Renderer: " << alGetString(AL_RENDERER) << "\n"
<< "OpenAl Extensions: " << alGetString(AL_RENDERER) << "\n";
}
void SoundPlayerOpenAL::init(const SoundPlayerParams* params) {
this->params = *params;
device = alcOpenDevice(0);
if(device == 0) {
printOpenALInfo();
throw std::runtime_error("Couldn't open audio device.");
}
try {
int attributes[] = { 0 };
context = alcCreateContext(device, attributes);
checkAlcError("Couldn't create audio context: ");
alcMakeContextCurrent(context);
checkAlcError("Couldn't select audio context: ");
checkAlError("Audio error after init: ");
} catch(...) {
printOpenALInfo();
throw;
}
}
void SoundPlayerOpenAL::end() {
for(StaticSoundSources::iterator i = staticSources.begin();
i != staticSources.end(); ++i)
delete *i;
for(StreamSoundSources::iterator i = streamSources.begin();
i != streamSources.end(); ++i)
delete *i;
if(context != 0) {
alcDestroyContext(context);
context = 0;
}
if(device != 0) {
alcCloseDevice(device);
device = 0;
}
}
void SoundPlayerOpenAL::play(StaticSound* staticSound) {
assert(staticSound != 0);
try {
StaticSoundSource* source = findStaticSoundSource();
if(source == 0)
return;
source->play(staticSound);
} catch(std::exception& e) {
std::cerr << "Couldn't play static sound: " << e.what() << "\n";
}
}
void SoundPlayerOpenAL::play(StrSound* strSound, int64 fadeOn) {
assert(strSound != 0);
try {
StreamSoundSource* source = findStreamSoundSource();
source->play(strSound, fadeOn);
} catch(std::exception& e) {
std::cerr << "Couldn't play streaming sound: " << e.what() << "\n";
}
}
void SoundPlayerOpenAL::stop(StrSound* strSound, int64 fadeOff) {
assert(strSound != 0);
for(StreamSoundSources::iterator i = streamSources.begin();
i != streamSources.end(); ++i) {
StreamSoundSource* source = *i;
if(source->sound == strSound) {
source->stop(fadeOff);
}
}
}
void SoundPlayerOpenAL::stopAllSounds() {
for(StaticSoundSources::iterator i = staticSources.begin();
i != staticSources.end(); ++i) {
StaticSoundSource* source = *i;
source->stop();
}
for(StreamSoundSources::iterator i = streamSources.begin();
i != streamSources.end(); ++i) {
StreamSoundSource* source = *i;
source->stop();
}
}
void SoundPlayerOpenAL::updateStreams() {
assert(context != 0);
try {
for(StreamSoundSources::iterator i = streamSources.begin();
i != streamSources.end(); ++i) {
StreamSoundSource* source = *i;
try {
source->update();
} catch(std::exception& e) {
std::cerr << "Error while updating sound stream: "
<< e.what() << "\n";
}
}
alcProcessContext(context);
checkAlcError("Error while processing audio context: ");
} catch(...) {
printOpenALInfo();
throw;
}
}
StaticSoundSource* SoundPlayerOpenAL::findStaticSoundSource() {
// try to find a stopped source
for(StaticSoundSources::iterator i = staticSources.begin();
i != staticSources.end(); ++i) {
StaticSoundSource* source = *i;
if(! source->playing()) {
return source;
}
}
// create a new source
if(staticSources.size() >= params.staticBufferCount) {
return 0;
}
StaticSoundSource* source = new StaticSoundSource();
staticSources.push_back(source);
return source;
}
StreamSoundSource* SoundPlayerOpenAL::findStreamSoundSource() {
// try to find a stopped source
for(StreamSoundSources::iterator i = streamSources.begin();
i != streamSources.end(); ++i) {
StreamSoundSource* source = *i;
if(! source->playing()) {
return source;
}
}
// create a new source
if(streamSources.size() >= params.strBufferCount) {
throw std::runtime_error("Too many stream sounds played at once");
}
StreamSoundSource* source = new StreamSoundSource();
streamSources.push_back(source);
return source;
}
void SoundPlayerOpenAL::checkAlcError(const char* message)
{
int err = alcGetError(device);
if(err != ALC_NO_ERROR) {
std::stringstream msg;
msg << message << alcGetString(device, err);
throw std::runtime_error(msg.str());
}
}
void SoundPlayerOpenAL::checkAlError(const char* message)
{
int err = alGetError();
if(err != AL_NO_ERROR) {
std::stringstream msg;
msg << message << alGetString(err);
throw std::runtime_error(msg.str());
}
}
}}} // end of namespace

View File

@@ -1,100 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "sound.h"
#include <fstream>
#include <stdexcept>
#include "leak_dumper.h"
namespace Shared{ namespace Sound{
// =====================================================
// class SoundInfo
// =====================================================
SoundInfo::SoundInfo(){
channels= 0;
samplesPerSecond= 0;
bitsPerSample= 0;
size= 0;
}
// =====================================================
// class Sound
// =====================================================
Sound::Sound(){
volume= 0.0f;
}
// =====================================================
// class StaticSound
// =====================================================
StaticSound::StaticSound(){
samples= NULL;
}
StaticSound::~StaticSound(){
delete [] samples;
}
void StaticSound::load(const string &path){
string ext= path.substr(path.find_last_of('.')+1);
soundFileLoader= SoundFileLoaderFactory::getInstance()->newInstance(ext);
soundFileLoader->open(path, &info);
samples= new int8[info.getSize()];
soundFileLoader->read(samples, info.getSize());
soundFileLoader->close();
delete soundFileLoader;
}
// =====================================================
// class StrSound
// =====================================================
StrSound::StrSound(){
soundFileLoader= NULL;
next= NULL;
}
StrSound::~StrSound(){
close();
}
void StrSound::open(const string &path){
string ext= path.substr(path.find_last_of('.')+1);
soundFileLoader= SoundFileLoaderFactory::getInstance()->newInstance(ext);
soundFileLoader->open(path, &info);
}
uint32 StrSound::read(int8 *samples, uint32 size){
return soundFileLoader->read(samples, size);
}
void StrSound::close(){
if(soundFileLoader!=NULL){
soundFileLoader->close();
delete soundFileLoader;
soundFileLoader= NULL;
}
}
void StrSound::restart(){
soundFileLoader->restart();
}
}}//end namespace

View File

@@ -1,199 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "sound_file_loader.h"
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
#include "sound.h"
#include "leak_dumper.h"
using namespace Shared::Platform;
using namespace std;
namespace Shared{ namespace Sound{
// =====================================================
// class WavSoundFileLoader
// =====================================================
void WavSoundFileLoader::open(const string &path, SoundInfo *soundInfo){
char chunkId[]={'-', '-', '-', '-', '\0'};
uint32 size32= 0;
uint16 size16= 0;
int count;
f.open(path.c_str(), ios_base::in | ios_base::binary);
if(!f.is_open()){
throw runtime_error("Error opening wav file: "+ string(path));
}
//RIFF chunk - Id
f.read(chunkId, 4);
if(strcmp(chunkId, "RIFF")!=0){
throw runtime_error("Not a valid wav file (first four bytes are not RIFF):" + path);
}
//RIFF chunk - Size
f.read((char*) &size32, 4);
//RIFF chunk - Data (WAVE string)
f.read(chunkId, 4);
if(strcmp(chunkId, "WAVE")!=0){
throw runtime_error("Not a valid wav file (wave data don't start by WAVE): " + path);
}
// === HEADER ===
//first sub-chunk (header) - Id
f.read(chunkId, 4);
if(strcmp(chunkId, "fmt ")!=0){
throw runtime_error("Not a valid wav file (first sub-chunk Id is not fmt): "+ path);
}
//first sub-chunk (header) - Size
f.read((char*) &size32, 4);
//first sub-chunk (header) - Data (encoding type) - Ignore
f.read((char*) &size16, 2);
//first sub-chunk (header) - Data (nChannels)
f.read((char*) &size16, 2);
soundInfo->setChannels(size16);
//first sub-chunk (header) - Data (nsamplesPerSecond)
f.read((char*) &size32, 4);
soundInfo->setsamplesPerSecond(size32);
//first sub-chunk (header) - Data (nAvgBytesPerSec) - Ignore
f.read((char*) &size32, 4);
//first sub-chunk (header) - Data (blockAlign) - Ignore
f.read((char*) &size16, 2);
//first sub-chunk (header) - Data (nsamplesPerSecond)
f.read((char*) &size16, 2);
soundInfo->setBitsPerSample(size16);
if (soundInfo->getBitsPerSample() != 8 && soundInfo->getBitsPerSample()!=16){
throw runtime_error("Bits per sample must be 8 or 16: " + path);
}
bytesPerSecond= soundInfo->getBitsPerSample()*8*soundInfo->getSamplesPerSecond()*soundInfo->getChannels();
count=0;
do{
count++;
// === DATA ===
//second sub-chunk (samples) - Id
f.read(chunkId, 4);
if(strncmp(chunkId, "data", 4)!=0){
continue;
}
//second sub-chunk (samples) - Size
f.read((char*) &size32, 4);
dataSize= size32;
soundInfo->setSize(dataSize);
}
while(strncmp(chunkId, "data", 4)!=0 && count<maxDataRetryCount);
if(f.bad() || count==maxDataRetryCount){
throw runtime_error("Error reading samples: "+ path);
}
dataOffset= f.tellg();
}
uint32 WavSoundFileLoader::read(int8 *samples, uint32 size){
f.read(reinterpret_cast<char*> (samples), size);
return f.gcount();
}
void WavSoundFileLoader::close(){
f.close();
}
void WavSoundFileLoader::restart(){
f.seekg(dataOffset, ios_base::beg);
}
// =======================================
// Ogg Sound File Loader
// =======================================
void OggSoundFileLoader::open(const string &path, SoundInfo *soundInfo){
f= fopen(path.c_str(), "rb");
if(f==NULL){
throw runtime_error("Can't open ogg file: "+path);
}
vf= new OggVorbis_File();
ov_open(f, vf, NULL, 0);
vorbis_info *vi= ov_info(vf, -1);
soundInfo->setChannels(vi->channels);
soundInfo->setsamplesPerSecond(vi->rate);
soundInfo->setBitsPerSample(16);
soundInfo->setSize(static_cast<uint32>(ov_pcm_total(vf, -1))*2);
}
uint32 OggSoundFileLoader::read(int8 *samples, uint32 size){
int section;
int totalBytesRead= 0;
while(size>0){
int bytesRead= ov_read(vf, reinterpret_cast<char*> (samples), size,
0, 2, 1, &section);
if(bytesRead==0){
break;
}
size-= bytesRead;
samples+= bytesRead;
totalBytesRead+= bytesRead;
}
return totalBytesRead;
}
void OggSoundFileLoader::close(){
if(vf!=NULL){
ov_clear(vf);
delete vf;
vf= 0;
}
}
void OggSoundFileLoader::restart(){
ov_raw_seek(vf, 0);
}
// =====================================================
// class SoundFileLoaderFactory
// =====================================================
SoundFileLoaderFactory::SoundFileLoaderFactory(){
registerClass<WavSoundFileLoader>("wav");
registerClass<OggSoundFileLoader>("ogg");
}
SoundFileLoaderFactory *SoundFileLoaderFactory::getInstance(){
static SoundFileLoaderFactory soundFileLoaderFactory;
return &soundFileLoaderFactory;
}
}}//end namespace

View File

@@ -1,35 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "sound_interface.h"
#include "leak_dumper.h"
namespace Shared{ namespace Sound{
// =====================================================
// class SoundInterface
// =====================================================
SoundInterface &SoundInterface::getInstance(){
static SoundInterface soundInterface;
return soundInterface;
}
void SoundInterface::setFactory(SoundFactory *soundFactory){
this->soundFactory= soundFactory;
}
SoundPlayer *SoundInterface::newSoundPlayer(){
return soundFactory->newSoundPlayer();
}
}}//end namespace

View File

@@ -1,28 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "sound_player.h"
#include "leak_dumper.h"
namespace Shared{ namespace Sound{
// =====================================================
// class SoundPlayerParams
// =====================================================
SoundPlayerParams::SoundPlayerParams(){
staticBufferCount= 8;
strBufferCount= 4;
strBufferSize= 44050*2*2*2; //2 second buffer
}
}}//end namespace

View File

@@ -1,70 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "checksum.h"
#include <cassert>
#include <stdexcept>
#include "util.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Util{
// =====================================================
// class Checksum
// =====================================================
Checksum::Checksum(){
sum= 0;
r= 55665;
c1= 52845;
c2= 22719;
}
void Checksum::addByte(int8 value){
int32 cipher= (value ^ (r >> 8));
r= (cipher + r) * c1 + c2;
sum+= cipher;
}
void Checksum::addString(const string &value){
for(int i= 0; i<value.size(); ++i){
addByte(value[i]);
}
}
void Checksum::addFile(const string &path){
FILE* file= fopen(path.c_str(), "rb");
if(file!=NULL){
addString(lastFile(path));
while(!feof(file)){
int8 byte= 0;
fread(&byte, 1, 1, file);
addByte(byte);
}
}
else
{
throw runtime_error("Can not open file: " + path);
}
fclose(file);
}
}}//end namespace

View File

@@ -1,126 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "conversion.h"
#include <stdexcept>
#include <cstdio>
#include <cstdlib>
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Util{
const int strSize = 256;
bool strToBool(const string &s){
if (s=="0" || s=="false"){
return false;
}
if (s=="1" || s=="true"){
return true;
}
throw runtime_error("Error converting string to bool, expected 0 or 1, found: " + s);
}
int strToInt(const string &s){
char *endChar;
int intValue= strtol(s.c_str(), &endChar, 10);
if(*endChar!='\0'){
throw runtime_error("Error converting from string to int, found: "+s);
}
return intValue;
}
float strToFloat(const string &s){
char *endChar;
float floatValue= static_cast<float>(strtod(s.c_str(), &endChar));
if(*endChar!='\0'){
throw runtime_error("Error converting from string to float, found: "+s);
}
return floatValue;
}
bool strToBool(const string &s, bool *b){
if (s=="0" || s=="false"){
*b= false;
return true;
}
if (s=="1" || s=="true"){
*b= true;
return true;
}
return false;
}
bool strToInt(const string &s, int *i){
char *endChar;
*i= strtol(s.c_str(), &endChar, 10);
if(*endChar!='\0'){
return false;
}
return true;
}
bool strToFloat(const string &s, float *f){
char *endChar;
*f= static_cast<float>(strtod(s.c_str(), &endChar));
if(*endChar!='\0'){
return false;
}
return true;
}
string boolToStr(bool b){
if(b){
return "1";
}
else{
return "0";
}
}
string intToStr(int i){
char str[strSize];
sprintf(str, "%d", i);
return str;
}
string intToHex(int i){
char str[strSize];
sprintf(str, "%x", i);
return str;
}
string floatToStr(float f){
char str[strSize];
sprintf(str, "%.2f", f);
return str;
}
string doubleToStr(double d){
char str[strSize];
sprintf(str, "%.2f", d);
return str;
}
}}//end namespace

View File

@@ -1,123 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "leak_dumper.h"
#ifdef SL_LEAK_DUMP
AllocInfo::AllocInfo(){
ptr= NULL;
file= "";
line= -1;
bytes= -1;
array= false;
free= true;
}
AllocInfo::AllocInfo(void* ptr, const char* file, int line, size_t bytes, bool array){
this->ptr= ptr;
this->file= file;
this->line= line;
this->bytes= bytes;
this->array= array;
free= false;
}
// =====================================================
// class AllocRegistry
// =====================================================
// ===================== PRIVATE =======================
AllocRegistry::AllocRegistry(){
allocCount= 0;
allocBytes= 0;
nonMonitoredCount= 0;
nonMonitoredBytes= 0;
}
// ===================== PUBLIC ========================
AllocRegistry &AllocRegistry::getInstance(){
static AllocRegistry allocRegistry;
return allocRegistry;
}
AllocRegistry::~AllocRegistry(){
dump("leak_dump.log");
}
void AllocRegistry::allocate(AllocInfo info){
++allocCount;
allocBytes+= info.bytes;
unsigned hashCode= reinterpret_cast<unsigned>(info.ptr) % maxAllocs;
for(int i=hashCode; i<maxAllocs; ++i){
if(allocs[i].free){
allocs[i]= info;
return;
}
}
for(int i=0; i<hashCode; ++i){
if(allocs[i].free){
allocs[i]= info;
return;
}
}
++nonMonitoredCount;
nonMonitoredBytes+= info.bytes;
}
void AllocRegistry::deallocate(void* ptr, bool array){
unsigned hashCode= reinterpret_cast<unsigned>(ptr) % maxAllocs;
for(int i=hashCode; i<maxAllocs; ++i){
if(!allocs[i].free && allocs[i].ptr==ptr && allocs[i].array==array){
allocs[i].free= true;
return;
}
}
for(int i=0; i<hashCode; ++i){
if(!allocs[i].free && allocs[i].ptr==ptr && allocs[i].array==array){
allocs[i].free= true;
return;
}
}
}
void AllocRegistry::reset(){
for(int i=0; i<maxAllocs; ++i){
allocs[i]= AllocInfo();
}
}
void AllocRegistry::dump(const char *path){
FILE *f= fopen(path, "wt");
int leakCount=0;
size_t leakBytes=0;
fprintf(f, "Memory leak dump\n\n");
for(int i=0; i<maxAllocs; ++i){
if(!allocs[i].free){
leakBytes+= allocs[i].bytes;
fprintf(f, "%d.\tfile: %s, line: %d, bytes: %d, array: %d\n", ++leakCount, allocs[i].file, allocs[i].line, allocs[i].bytes, allocs[i].array);
}
}
fprintf(f, "\nTotal leaks: %d, %d bytes\n", leakCount, leakBytes);
fprintf(f, "Total allocations: %d, %d bytes\n", allocCount, allocBytes);
fprintf(f, "Not monitored allocations: %d, %d bytes\n", nonMonitoredCount, nonMonitoredBytes);
fclose(f);
}
#endif

View File

@@ -1,113 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "profiler.h"
#ifdef SL_PROFILE
#include <stdexcept>
using namespace std;
namespace Shared{ namespace Util{
// =====================================================
// class Section
// =====================================================
Section::Section(const string &name){
this->name= name;
milisElapsed= 0;
parent= NULL;
}
Section *Section::getChild(const string &name){
SectionContainer::iterator it;
for(it= children.begin(); it!=children.end(); ++it){
if((*it)->getName()==name){
return *it;
}
}
return NULL;
}
void Section::print(FILE *outStream, int tabLevel){
float percent= (parent==NULL || parent->milisElapsed==0)? 100.0f: 100.0f*milisElapsed/parent->milisElapsed;
string pname= parent==NULL? "": parent->getName();
for(int i=0; i<tabLevel; ++i)
fprintf(outStream, "\t");
fprintf(outStream, "%s: ", name.c_str());
fprintf(outStream, "%d ms, ", milisElapsed);
fprintf(outStream, "%.1f%s\n", percent, "%");
SectionContainer::iterator it;
for(it= children.begin(); it!=children.end(); ++it){
(*it)->print(outStream, tabLevel+1);
}
}
// =====================================================
// class Profiler
// =====================================================
Profiler::Profiler(){
rootSection= new Section("Root");
currSection= rootSection;
rootSection->start();
}
Profiler::~Profiler(){
rootSection->stop();
FILE *f= fopen("profiler.log", "w");
if(f==NULL)
throw runtime_error("Can not open file: profiler.log");
fprintf(f, "Profiler Results\n\n");
rootSection->print(f);
fclose(f);
}
Profiler &Profiler::getInstance(){
static Profiler profiler;
return profiler;
}
void Profiler::sectionBegin(const string &name){
Section *childSection= currSection->getChild(name);
if(childSection==NULL){
childSection= new Section(name);
currSection->addChild(childSection);
childSection->setParent(currSection);
}
currSection= childSection;
childSection->start();
}
void Profiler::sectionEnd(const string &name){
if(name==currSection->getName()){
currSection->stop();
currSection= currSection->getParent();
}
else{
throw runtime_error("Profile: Leaving section is not current section: "+name);
}
}
}};//end namespace
#endif

View File

@@ -1,171 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2007 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "properties.h"
#include <fstream>
#include <stdexcept>
#include <cstring>
#include "conversion.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Util{
// =====================================================
// class Properties
// =====================================================
void Properties::load(const string &path){
ifstream fileStream;
char lineBuffer[maxLine];
string line, key, value;
int pos;
this->path= path;
fileStream.open(path.c_str(), ios_base::in);
if(fileStream.fail()){
throw runtime_error("Can't open propertyMap file: " + path);
}
propertyMap.clear();
while(!fileStream.eof()){
fileStream.getline(lineBuffer, maxLine);
lineBuffer[maxLine-1]='\0';
//process line if it it not a comment
if(lineBuffer[0]!=';'){
// gracefully handle win32 \r\n line endings
size_t len= strlen(lineBuffer);
if(len > 0 && lineBuffer[len-1] == '\r'){
lineBuffer[len-1]= 0;
}
line= lineBuffer;
pos= line.find('=');
if(pos != string::npos){
key= line.substr(0, pos);
value= line.substr(pos+1);
propertyMap.insert(PropertyPair(key, value));
propertyVector.push_back(PropertyPair(key, value));
}
}
}
fileStream.close();
}
void Properties::save(const string &path){
ofstream fileStream;
fileStream.open(path.c_str(), ios_base::out | ios_base::trunc);
fileStream << "; === propertyMap File === \n";
fileStream << '\n';
for(PropertyMap::iterator pi= propertyMap.begin(); pi!=propertyMap.end(); ++pi){
fileStream << pi->first << '=' << pi->second << '\n';
}
fileStream.close();
}
void Properties::clear(){
propertyMap.clear();
propertyVector.clear();
}
bool Properties::getBool(const string &key) const{
try{
return strToBool(getString(key));
}
catch(exception &e){
throw runtime_error("Error accessing value: " + key + " in: " + path+"\n" + e.what());
}
}
int Properties::getInt(const string &key) const{
try{
return strToInt(getString(key));
}
catch(exception &e){
throw runtime_error("Error accessing value: " + key + " in: " + path + "\n" + e.what());
}
}
int Properties::getInt(const string &key, int min, int max) const{
int i= getInt(key);
if(i<min || i>max){
throw runtime_error("Value out of range: " + key + ", min: " + intToStr(min) + ", max: " + intToStr(max));
}
return i;
}
float Properties::getFloat(const string &key) const{
try{
return strToFloat(getString(key));
}
catch(exception &e){
throw runtime_error("Error accessing value: " + key + " in: " + path + "\n" + e.what());
}
}
float Properties::getFloat(const string &key, float min, float max) const{
float f= getFloat(key);
if(f<min || f>max){
throw runtime_error("Value out of range: " + key + ", min: " + floatToStr(min) + ", max: " + floatToStr(max));
}
return f;
}
const string &Properties::getString(const string &key) const{
PropertyMap::const_iterator it;
it= propertyMap.find(key);
if(it==propertyMap.end()){
throw runtime_error("Value not found in propertyMap: " + key + ", loaded from: " + path);
}
else{
return it->second;
}
}
void Properties::setInt(const string &key, int value){
setString(key, intToStr(value));
}
void Properties::setBool(const string &key, bool value){
setString(key, boolToStr(value));
}
void Properties::setFloat(const string &key, float value){
setString(key, floatToStr(value));
}
void Properties::setString(const string &key, const string &value){
propertyMap.erase(key);
propertyMap.insert(PropertyPair(key, value));
}
string Properties::toString(){
string rStr;
for(PropertyMap::iterator pi= propertyMap.begin(); pi!=propertyMap.end(); pi++)
rStr+= pi->first + "=" + pi->second + "\n";
return rStr;
}
}}//end namepsace

View File

@@ -1,46 +0,0 @@
#include "random.h"
#include <cassert>
#include "leak_dumper.h"
namespace Shared{ namespace Util{
// =====================================================
// class Random
// =====================================================
const int Random::m= 714025;
const int Random::a= 1366;
const int Random::b= 150889;
Random::Random(){
lastNumber= 0;
}
void Random::init(int seed){
lastNumber= seed % m;
}
int Random::rand(){
lastNumber= (a*lastNumber + b) % m;
return lastNumber;
}
int Random::randRange(int min, int max){
assert(min<=max);
int diff= max-min;
int res= min + static_cast<int>(static_cast<float>(diff+1)*Random::rand() / m);
assert(res>=min && res<=max);
return res;
}
float Random::randRange(float min, float max){
assert(min<=max);
float rand01= static_cast<float>(Random::rand())/(m-1);
float res= min+(max-min)*rand01;
assert(res>=min && res<=max);
return res;
}
}}//end namespace

View File

@@ -1,170 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "util.h"
#include <ctime>
#include <cassert>
#include <stdexcept>
#include <cstring>
#include <cstdio>
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Util{
string lastDir(const string &s){
size_t i= s.find_last_of('/');
size_t j= s.find_last_of('\\');
size_t pos;
if(i==string::npos){
pos= j;
}
else if(j==string::npos){
pos= i;
}
else{
pos= i<j? j: i;
}
if (pos==string::npos){
throw runtime_error(string(__FILE__)+" lastDir - i==string::npos");
}
return (s.substr(pos+1, s.length()));
}
string lastFile(const string &s){
return lastDir(s);
}
string cutLastFile(const string &s){
size_t i= s.find_last_of('/');
size_t j= s.find_last_of('\\');
size_t pos;
if(i==string::npos){
pos= j;
}
else if(j==string::npos){
pos= i;
}
else{
pos= i<j? j: i;
}
if (pos==string::npos){
throw runtime_error(string(__FILE__)+"cutLastFile - i==string::npos");
}
return (s.substr(0, pos));
}
string cutLastExt(const string &s){
size_t i= s.find_last_of('.');
if (i==string::npos){
throw runtime_error(string(__FILE__)+"cutLastExt - i==string::npos");
}
return (s.substr(0, i));
}
string ext(const string &s){
size_t i;
i=s.find_last_of('.')+1;
if (i==string::npos){
throw runtime_error(string(__FILE__)+"cutLastExt - i==string::npos");
}
return (s.substr(i, s.size()-i));
}
string replaceBy(const string &s, char c1, char c2){
string rs= s;
for(size_t i=0; i<s.size(); ++i){
if (rs[i]==c1){
rs[i]=c2;
}
}
return rs;
}
string toLower(const string &s){
string rs= s;
for(size_t i=0; i<s.size(); ++i){
rs[i]= tolower(s[i]);
}
return rs;
}
void copyStringToBuffer(char *buffer, int bufferSize, const string& s){
strncpy(buffer, s.c_str(), bufferSize-1);
buffer[bufferSize-1]= '\0';
}
// ==================== numeric fcs ====================
float saturate(float value){
if (value<0.f){
return 0.f;
}
if (value>1.f){
return 1.f;
}
return value;
}
int clamp(int value, int min, int max){
if (value<min){
return min;
}
if (value>max){
return max;
}
return value;
}
float clamp(float value, float min, float max){
if (value<min){
return min;
}
if (value>max){
return max;
}
return value;
}
int round(float f){
return (int) f;
}
// ==================== misc ====================
bool fileExists(const string &path){
FILE* file= fopen(path.c_str(), "rb");
if(file!=NULL){
fclose(file);
return true;
}
return false;
}
}}//end namespace

View File

@@ -1,426 +0,0 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "xml_parser.h"
#include <fstream>
#include <stdexcept>
#include "conversion.h"
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include "leak_dumper.h"
XERCES_CPP_NAMESPACE_USE
using namespace std;
namespace Shared{ namespace Xml{
using namespace Util;
// =====================================================
// class ErrorHandler
// =====================================================
class ErrorHandler: public DOMErrorHandler{
public:
virtual bool handleError (const DOMError &domError){
if(domError.getSeverity()== DOMError::DOM_SEVERITY_FATAL_ERROR){
char msgStr[strSize], fileStr[strSize];
XMLString::transcode(domError.getMessage(), msgStr, strSize-1);
XMLString::transcode(domError.getLocation()->getURI(), fileStr, strSize-1);
int lineNumber= domError.getLocation()->getLineNumber();
throw runtime_error("Error parsing XML, file: " + string(fileStr) + ", line: " + intToStr(lineNumber) + ": " + string(msgStr));
}
return true;
}
};
// =====================================================
// class XmlIo
// =====================================================
bool XmlIo::initialized= false;
XmlIo::XmlIo(){
try{
XMLPlatformUtils::Initialize();
}
catch(const XMLException&){
throw runtime_error("Error initializing XML system");
}
try{
XMLCh str[strSize];
XMLString::transcode("LS", str, strSize-1);
implementation = DOMImplementationRegistry::getDOMImplementation(str);
}
catch(const DOMException){
throw runtime_error("Exception while creating XML parser");
}
}
XmlIo &XmlIo::getInstance(){
static XmlIo XmlIo;
return XmlIo;
}
XmlIo::~XmlIo(){
XMLPlatformUtils::Terminate();
}
XmlNode *XmlIo::load(const string &path){
try{
ErrorHandler errorHandler;
#if XERCES_VERSION_MAJOR < 3
DOMBuilder *parser= (static_cast<DOMImplementationLS*>(implementation))->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
parser->setErrorHandler(&errorHandler);
parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
parser->setFeature(XMLUni::fgDOMValidation, true);
#else
DOMLSParser *parser = (static_cast<DOMImplementationLS*>(implementation))->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
DOMConfiguration *config = parser->getDomConfig();
config->setParameter(XMLUni::fgXercesSchemaFullChecking, true);
config->setParameter(XMLUni::fgDOMValidate, true);
#endif
DOMDocument *document= parser->parseURI(path.c_str());
if(document==NULL){
throw runtime_error("Can not parse URL: " + path);
}
XmlNode *rootNode= new XmlNode(document->getDocumentElement());
parser->release();
return rootNode;
}
catch(const DOMException &e){
throw runtime_error("Exception while loading: " + path + ": " + XMLString::transcode(e.msg));
}
}
void XmlIo::save(const string &path, const XmlNode *node){
try{
XMLCh str[strSize];
XMLString::transcode(node->getName().c_str(), str, strSize-1);
DOMDocument *document= implementation->createDocument(0, str, 0);
DOMElement *documentElement= document->getDocumentElement();
for(int i=0; i<node->getChildCount(); ++i){
documentElement->appendChild(node->getChild(i)->buildElement(document));
}
LocalFileFormatTarget file(path.c_str());
#if XERCES_VERSION_MAJOR < 3
DOMWriter* writer = implementation->createDOMWriter();
writer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
writer->writeNode(&file, *document);
#else
DOMLSSerializer *serializer = implementation->createLSSerializer();
DOMLSOutput* output=implementation->createLSOutput();
DOMConfiguration* config=serializer->getDomConfig();
config->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint,true);
output->setByteStream(&file);
serializer->write(document,output);
output->release();
serializer->release();
#endif
document->release();
}
catch(const DOMException &e){
throw runtime_error("Exception while saving: " + path + ": " + XMLString::transcode(e.msg));
}
}
// =====================================================
// class XmlTree
// =====================================================
XmlTree::XmlTree(){
rootNode= NULL;
}
void XmlTree::init(const string &name){
this->rootNode= new XmlNode(name);
}
void XmlTree::load(const string &path){
this->rootNode= XmlIo::getInstance().load(path);
}
void XmlTree::save(const string &path){
XmlIo::getInstance().save(path, rootNode);
}
XmlTree::~XmlTree(){
delete rootNode;
}
// =====================================================
// class XmlNode
// =====================================================
XmlNode::XmlNode(DOMNode *node){
//get name
char str[strSize];
XMLString::transcode(node->getNodeName(), str, strSize-1);
name= str;
//check document
if(node->getNodeType()==DOMNode::DOCUMENT_NODE){
name="document";
}
//check children
for(int i=0; i<node->getChildNodes()->getLength(); ++i){
DOMNode *currentNode= node->getChildNodes()->item(i);
if(currentNode->getNodeType()==DOMNode::ELEMENT_NODE){
XmlNode *xmlNode= new XmlNode(currentNode);
children.push_back(xmlNode);
}
}
//check attributes
DOMNamedNodeMap *domAttributes= node->getAttributes();
if(domAttributes!=NULL){
for(int i=0; i<domAttributes->getLength(); ++i){
DOMNode *currentNode= domAttributes->item(i);
if(currentNode->getNodeType()==DOMNode::ATTRIBUTE_NODE){
XmlAttribute *xmlAttribute= new XmlAttribute(domAttributes->item(i));
attributes.push_back(xmlAttribute);
}
}
}
//get value
if(node->getNodeType()==DOMNode::ELEMENT_NODE && children.size()==0){
char *textStr= XMLString::transcode(node->getTextContent());
text= textStr;
XMLString::release(&textStr);
}
}
XmlNode::XmlNode(const string &name){
this->name= name;
}
XmlNode::~XmlNode(){
for(int i=0; i<children.size(); ++i){
delete children[i];
}
for(int i=0; i<attributes.size(); ++i){
delete attributes[i];
}
}
XmlAttribute *XmlNode::getAttribute(int i) const{
if(i>=attributes.size()){
throw runtime_error(getName()+" node doesn't have "+intToStr(i)+" attributes");
}
return attributes[i];
}
XmlAttribute *XmlNode::getAttribute(const string &name) const{
for(int i=0; i<attributes.size(); ++i){
if(attributes[i]->getName()==name){
return attributes[i];
}
}
throw runtime_error("\"" + getName() + "\" node doesn't have a attribute named \"" + name + "\"");
}
XmlNode *XmlNode::getChild(int i) const {
if(i>=children.size())
throw runtime_error("\"" + getName()+"\" node doesn't have "+intToStr(i+1)+" children");
return children[i];
}
XmlNode *XmlNode::getChild(const string &childName, int i) const{
if(i>=children.size()){
throw runtime_error("\"" + name + "\" node doesn't have "+intToStr(i+1)+" children named \"" + childName + "\"\n\nTree: "+getTreeString());
}
int count= 0;
for(int j=0; j<children.size(); ++j){
if(children[j]->getName()==childName){
if(count==i){
return children[j];
}
count++;
}
}
throw runtime_error("Node \""+getName()+"\" doesn't have "+intToStr(i+1)+" children named \""+childName+"\"\n\nTree: "+getTreeString());
}
bool XmlNode::hasChildAtIndex(const string &childName, int i) const
{
int count= 0;
for(int j = 0; j < children.size(); ++j)
{
if(children[j]->getName()==childName)
{
if(count==i){
return true;
}
count++;
}
}
return false;
}
bool XmlNode::hasChild(const string &childName) const
{
int count= 0;
for(int j = 0; j < children.size(); ++j)
{
if(children[j]->getName()==childName)
{
return true;
}
}
return false;
}
XmlNode *XmlNode::addChild(const string &name){
XmlNode *node= new XmlNode(name);
children.push_back(node);
return node;
}
XmlAttribute *XmlNode::addAttribute(const string &name, const string &value){
XmlAttribute *attr= new XmlAttribute(name, value);
attributes.push_back(attr);
return attr;
}
DOMElement *XmlNode::buildElement(DOMDocument *document) const{
XMLCh str[strSize];
XMLString::transcode(name.c_str(), str, strSize-1);
DOMElement *node= document->createElement(str);
for(int i=0; i<attributes.size(); ++i){
XMLString::transcode(attributes[i]->getName().c_str(), str, strSize-1);
DOMAttr *attr= document->createAttribute(str);
XMLString::transcode(attributes[i]->getValue().c_str(), str, strSize-1);
attr->setValue(str);
node->setAttributeNode(attr);
}
for(int i=0; i<children.size(); ++i){
node->appendChild(children[i]->buildElement(document));
}
return node;
}
string XmlNode::getTreeString() const{
string str;
str+= getName();
if(!children.empty()){
str+= " (";
for(int i=0; i<children.size(); ++i){
str+= children[i]->getTreeString();
str+= " ";
}
str+=") ";
}
return str;
}
// =====================================================
// class XmlAttribute
// =====================================================
XmlAttribute::XmlAttribute(DOMNode *attribute){
char str[strSize];
XMLString::transcode(attribute->getNodeValue(), str, strSize-1);
value= str;
XMLString::transcode(attribute->getNodeName(), str, strSize-1);
name= str;
}
XmlAttribute::XmlAttribute(const string &name, const string &value){
this->name= name;
this->value= value;
}
bool XmlAttribute::getBoolValue() const{
if(value=="true"){
return true;
}
else if(value=="false"){
return false;
}
else{
throw runtime_error("Not a valid bool value (true or false): " +getName()+": "+ value);
}
}
int XmlAttribute::getIntValue() const{
return strToInt(value);
}
int XmlAttribute::getIntValue(int min, int max) const{
int i= strToInt(value);
if(i<min || i>max){
throw runtime_error("Xml Attribute int out of range: " + getName() + ": " + value);
}
return i;
}
float XmlAttribute::getFloatValue() const{
return strToFloat(value);
}
float XmlAttribute::getFloatValue(float min, float max) const{
float f= strToFloat(value);
if(f<min || f>max){
throw runtime_error("Xml attribute float out of range: " + getName() + ": " + value);
}
return f;
}
const string &XmlAttribute::getRestrictedValue() const
{
const string allowedCharacters = "abcdefghijklmnopqrstuvwxyz1234567890._-/";
for(int i= 0; i<value.size(); ++i){
if(allowedCharacters.find(value[i])==string::npos){
throw runtime_error(
string("The string \"" + value + "\" contains a character that is not allowed: \"") + value[i] +
"\"\nFor portability reasons the only allowed characters in this field are: " + allowedCharacters);
}
}
return value;
}
}}//end namespace