Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: OGRE
GAMEINATOR forums > Общие разделы > Создание и модификация игр. Геймдев. > Игровые проекты форумчан
centrino
предлагаю в этой теме делиться опытом всем, кто имел дело с этим движком, возможно ссылками на литературу, ресурсы и примеры.

хочу поделиться исходным кодом OGRE 1.6.2. Shoggoth для Visual Studio C++ 2005 SP1 готовым для сборки. также, из исходников собираются все необходимые движку библиотеки: zlib, FreeImage, FreeType, etc. собираются только основная библиотека ogre и dx9 рендер.

ссылка: Ogre Source Code.rar

файл решения расположен в .\Ogre Source Code\src\ogre\ogre.sln ,доступны конфигурации для сборки статической и динамической библиотек

неплохой учебник на английском языке: http://rapidshare.com/files/126816945/book...7_2008.rar.html

документация на сайте проекта: http://www.ogre3d.org/docs/api/html/
centrino
перезалил: Ogre Source Code (copy 2).rar

пример использования статической библиотеки OGRE

Код
//

#define VC_EXTRALEAN
#define OGRE_STATIC_LIB

#include <windows.h>
#include <ogre.h>
#include <OgreD3D9Plugin.h>


#define KEY_DOWN( code ) \
  ( ( GetAsyncKeyState( code ) & 0x8000 ) ? 1 : 0 )

#define KB_ESC 27


int Run()
{
  MSG Msg;
  Ogre::Root* root = new Ogre::Root( "","","" );
  Ogre::D3D9Plugin* dx9dll = new Ogre::D3D9Plugin;
  Ogre::RenderSystem* dx9render;
  Ogre::RenderWindow* window;
  Ogre::SceneManager* scene;

  root->getSingleton().installPlugin( dx9dll );
  dx9render = *( root->getAvailableRenderers()->begin() );
  root->setRenderSystem( dx9render );
  window = root->initialise( true, "Statically linked OGRE" );
  scene = root->createSceneManager( Ogre::ST_GENERIC );

  while( 1 )
  {
    if( KEY_DOWN( KB_ESC ) )
      break;

    while ( PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE ) )
    {
      TranslateMessage( &Msg );
      DispatchMessage( &Msg );
    }

    if ( !root->_fireFrameStarted() )
      break;

    root->_updateAllRenderTargets();

    if ( !root->_fireFrameEnded() )
      break;
  }

  delete root;
  return 0;
}


int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
  int nRet = -1;

  try
  {
    nRet = Run();
  }
  catch( Ogre::Exception &e )
  {
    MessageBox( NULL, e.getDescription().c_str(), "Error", MB_ICONSTOP );
  }

  return nRet;
}



полученный .exe (никакие длл-ки для запуска больше не требуютя)
test (copy 2).rar
HappyMenses
Чё, Source тебя больше не интересует? )))
centrino
ты хочешь спросить собираюсь ли я переписывать рендер из source engine? нет, и никогда не задавался подобной целью ибо в ближайшие несколько лет у меня точно ничего не получится smile.gif

но кое-что полезное в исходниках source подчерпнуть удается, вот предыдущий пример с некоторыми изменениями:

Код
//

#define VC_EXTRALEAN
#define OGRE_STATIC_LIB

#include <windows.h>
#include <ogre.h>
#include <OgreD3D9Plugin.h>
#include <dbg/dbg.h>




#define KEY_DOWN( code ) \
  ( ( GetAsyncKeyState( code ) & 0x8000 ) ? 1 : 0 )

#define KB_ESC 27


Ogre::LogManager g_LogManager;
Ogre::Log* g_pLog = g_LogManager.getSingleton().createLog( "test.log", true );



SpewRetval_t SpewFunc( SpewType_t spewType, char const *pMsg )
{
  switch( spewType )
  {
  case SPEW_SEH:
    g_pLog->logMessage( pMsg );
    return SPEW_ABORT;
  default:
    return SPEW_CONTINUE;
  }
}




int Run()
{
  MSG Msg;
  Ogre::Root* root = new Ogre::Root( "","","" );
  Ogre::D3D9Plugin* dx9dll = new Ogre::D3D9Plugin;
  Ogre::RenderSystem* dx9render;
  Ogre::RenderWindow* window;
  Ogre::SceneManager* scene;

  root->getSingleton().installPlugin( dx9dll );
  dx9render = *( root->getAvailableRenderers()->begin() );
  root->setRenderSystem( dx9render );
  window = root->initialise( true, "Statically linked OGRE" );
  scene = root->createSceneManager( Ogre::ST_GENERIC );

  while( 1 )
  {
    if( KEY_DOWN( KB_ESC ) )
      break;

    while ( PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE ) )
    {
      TranslateMessage( &Msg );
      DispatchMessage( &Msg );
    }

    if ( !root->_fireFrameStarted() )
      break;

    root->_updateAllRenderTargets();

    if ( !root->_fireFrameEnded() )
      break;
  }

  //------------------------------------------------------
  int* i = 0;
  *i = 0;
  //------------------------------------------------------

  delete root;
  return 0;
}





int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
  int nRet = -1;

  SpewOutputFunc( SpewFunc );
  SpewInstallFilter();

  try
  {
    nRet = Run();
  }
  catch( Ogre::Exception &e )
  {
    MessageBox( NULL, e.getDescription().c_str(), "Error", MB_ICONSTOP );
  }

  return nRet;
}



лог
15:49:37: Creating resource group General
15:49:37: Creating resource group Internal
15:49:37: Creating resource group Autodetect
15:49:37: SceneManagerFactory for type 'DefaultSceneManager' registered.
15:49:38: Registering ResourceManager for type Material
15:49:38: Registering ResourceManager for type Mesh
15:49:38: Registering ResourceManager for type Skeleton
15:49:38: MovableObjectFactory for type 'ParticleSystem' registered.
15:49:38: OverlayElementFactory for type Panel registered.
15:49:38: OverlayElementFactory for type BorderPanel registered.
15:49:38: OverlayElementFactory for type TextArea registered.
15:49:38: Registering ResourceManager for type Font
15:49:38: ArchiveFactory for archive type FileSystem registered.
15:49:38: ArchiveFactory for archive type Zip registered.
15:49:38: FreeImage version: 3.12.0
15:49:38: This program uses FreeImage, a free, open source image library supporting all common bitmap formats. See http://freeimage.sourceforge.net for details
15:49:38: Supported formats: bmp,ico,jpg,jif,jpeg,jpe,jng,koa,iff,lbm,mng,pbm,pbm,pcd,pcx,pgm,pgm,png,ppm,ppm
,ras,tga,targa,tif,tiff,wap,wbmp,wbm,psd,cut,xbm,xpm,gif,hdr,g3,sgi,exr,j2k,j2c,
j
p2,pfm
15:49:38: DDS codec registering
15:49:38: Registering ResourceManager for type HighLevelGpuProgram
15:49:38: Registering ResourceManager for type Compositor
15:49:38: MovableObjectFactory for type 'Entity' registered.
15:49:38: MovableObjectFactory for type 'Light' registered.
15:49:38: MovableObjectFactory for type 'BillboardSet' registered.
15:49:38: MovableObjectFactory for type 'ManualObject' registered.
15:49:38: MovableObjectFactory for type 'BillboardChain' registered.
15:49:38: MovableObjectFactory for type 'RibbonTrail' registered.
15:49:38: *-*-* OGRE Initialising
15:49:38: *-*-* Version 1.6.2 (Shoggoth)
15:49:38: Installing plugin: D3D9 RenderSystem
15:49:38: D3D9 : Direct3D9 Rendering Subsystem created.
15:49:38: D3D9: Driver Detection Starts
15:49:38: D3D9: Driver Detection Ends
15:49:38: Plugin successfully installed
15:49:38: CPU Identifier & Features
15:49:38: -------------------------
15:49:38: * CPU ID: GenuineIntel: Intel® Pentium® D CPU 3.00GHz
15:49:38: * SSE: yes
15:49:38: * SSE2: yes
15:49:38: * SSE3: yes
15:49:38: * MMX: yes
15:49:38: * MMXEXT: yes
15:49:38: * 3DNOW: no
15:49:38: * 3DNOWEXT: no
15:49:38: * CMOV: yes
15:49:38: * TSC: yes
15:49:38: * FPU: yes
15:49:38: * PRO: yes
15:49:38: * HT: yes
15:49:38: -------------------------
15:49:38: D3D9 : Subsystem Initialising
15:49:38: D3D9RenderSystem::_createRenderWindow "Statically linked OGRE", 800x600 fullscreen miscParams: FSAA=0 FSAAQuality=0 colourDepth=32 gamma=false useNVPerfHUD=false vsync=true
15:49:38: D3D9 : Created D3D9 Rendering Window 'Statically linked OGRE' : 800x600, 32bpp
15:49:38: Registering ResourceManager for type Texture
15:49:38: Registering ResourceManager for type GpuProgram
15:49:38: D3D9: Vertex texture format supported - PF_L8
15:49:38: D3D9: Vertex texture format supported - PF_L16
15:49:38: D3D9: Vertex texture format supported - PF_A8
15:49:38: D3D9: Vertex texture format supported - PF_A4L4
15:49:38: D3D9: Vertex texture format supported - PF_BYTE_LA
15:49:38: D3D9: Vertex texture format supported - PF_R5G6B5
15:49:38: D3D9: Vertex texture format supported - PF_B5G6R5
15:49:38: D3D9: Vertex texture format supported - PF_A4R4G4B4
15:49:38: D3D9: Vertex texture format supported - PF_A1R5G5B5
15:49:38: D3D9: Vertex texture format supported - PF_A8R8G8B8
15:49:38: D3D9: Vertex texture format supported - PF_B8G8R8A8
15:49:38: D3D9: Vertex texture format supported - PF_A2R10G10B10
15:49:38: D3D9: Vertex texture format supported - PF_A2B10G10R10
15:49:38: D3D9: Vertex texture format supported - PF_DXT1
15:49:38: D3D9: Vertex texture format supported - PF_DXT2
15:49:38: D3D9: Vertex texture format supported - PF_DXT3
15:49:38: D3D9: Vertex texture format supported - PF_DXT4
15:49:38: D3D9: Vertex texture format supported - PF_DXT5
15:49:38: D3D9: Vertex texture format supported - PF_FLOAT16_RGB
15:49:38: D3D9: Vertex texture format supported - PF_FLOAT16_RGBA
15:49:38: D3D9: Vertex texture format supported - PF_FLOAT32_RGB
15:49:38: D3D9: Vertex texture format supported - PF_FLOAT32_RGBA
15:49:38: D3D9: Vertex texture format supported - PF_X8R8G8B8
15:49:38: D3D9: Vertex texture format supported - PF_X8B8G8R8
15:49:38: D3D9: Vertex texture format supported - PF_R8G8B8A8
15:49:38: D3D9: Vertex texture format supported - PF_DEPTH
15:49:38: D3D9: Vertex texture format supported - PF_SHORT_RGBA
15:49:38: D3D9: Vertex texture format supported - PF_FLOAT16_R
15:49:38: D3D9: Vertex texture format supported - PF_FLOAT32_R
15:49:38: D3D9: Vertex texture format supported - PF_SHORT_GR
15:49:38: D3D9: Vertex texture format supported - PF_FLOAT16_GR
15:49:38: D3D9: Vertex texture format supported - PF_FLOAT32_GR
15:49:38: D3D9: Vertex texture format supported - PF_SHORT_RGB
15:49:38: RenderSystem capabilities
15:49:38: -------------------------
15:49:38: RenderSystem Name: Direct3D9 Rendering Subsystem
15:49:38: GPU Vendor: ati
15:49:38: Device Name: ATI Radeon HD 4800 Series
15:49:38: Driver Version: 6.14.10.6936
15:49:38: * Fixed function pipeline: yes
15:49:38: * Hardware generation of mipmaps: yes
15:49:38: * Texture blending: yes
15:49:38: * Anisotropic texture filtering: yes
15:49:38: * Dot product texture operation: yes
15:49:38: * Cube mapping: yes
15:49:38: * Hardware stencil buffer: yes
15:49:38: - Stencil depth: 8
15:49:38: - Two sided stencil support: yes
15:49:38: - Wrap stencil values: yes
15:49:38: * Hardware vertex / index buffers: yes
15:49:38: * Vertex programs: yes
15:49:38: * Fragment programs: yes
15:49:38: * Geometry programs: no
15:49:38: * Supported Shader Profiles: hlsl ps_1_1 ps_1_2 ps_1_3 ps_1_4 ps_2_0 ps_2_a ps_2_b ps_2_x ps_3_0 vs_1_1 vs_2_0 vs_2_a vs_2_x vs_3_0
15:49:38: * Texture Compression: yes
15:49:38: - DXT: yes
15:49:38: - VTC: no
15:49:38: * Scissor Rectangle: yes
15:49:38: * Hardware Occlusion Query: yes
15:49:38: * User clip planes: yes
15:49:38: * VET_UBYTE4 vertex element type: yes
15:49:38: * Infinite far plane projection: yes
15:49:38: * Hardware render-to-texture: yes
15:49:38: * Floating point textures: yes
15:49:38: * Non-power-of-two textures: yes
15:49:38: * Volume textures: yes
15:49:38: * Multiple Render Targets: 4
15:49:38: - With different bit depths: yes
15:49:38: * Point Sprites: yes
15:49:38: * Extended point parameters: yes
15:49:38: * Max Point Size: 256
15:49:38: * Vertex texture fetch: yes
15:49:38: - Max vertex textures: 4
15:49:38: - Vertex textures shared: no
15:49:38: * Render to Vertex Buffer : no
15:49:38: * DirectX per stage constants: yes
15:49:38: ***************************************
15:49:38: *** D3D9 : Subsystem Initialised OK ***
15:49:38: ***************************************
15:49:38: ResourceBackgroundQueue - threading disabled
15:49:38: Particle Renderer Type 'billboard' registered
15:49:41: test.exe caused ACCESS_VIOLATION at C:\Documents and Settings\ivan\Мои документы\Visual Studio 2005\Projects\eng\bin\test.exe
File: "c:\documents and settings\ivan\мои документы\visual studio 2005\projects\eng\src\test\main.cpp", Line: 76
Function: Run() + 945 byte(s)
centrino
онлайн вариант представленой выше книги: pro ogre 3d programming
centrino
скрестил огра с stl port теперь огр умеет находить пути, содержащие кириллицу

изменения в коде огра:
Код
// OgreString.cpp

#if defined (STLPORT) && defined  (OGRE_COMPILER_MSVC)

#include <tchar.h>

int tolower( int C )
{
  return _mbctolower( C );
}

int toupper( int C )
{
  return _mbctoupper( C );
}

#endif






// OgreD3D9TextureManager.h

#if defined (STLPORT) && defined  (OGRE_COMPILER_MSVC)

namespace stlp_std
{

template <> struct hash<Ogre::D3D9Texture* >
{
  size_t operator()( Ogre::D3D9Texture* const &  ptr ) const
  {
    hash<char*> Ch;
    return Ch((char*)ptr);
  }
};
}

#endif


ссыль: ogre sources (copy 2).rar
centrino
centrino


ппц граждане blink.gif я думал ландшафт в максе делают, а оно вон как оказывается о_О

подскажите нубу, кто в этом разбирается, как создают ландшафт, как делать карту высот (в смысле как смоделировать какую-то конкретную местность, то что в фотошопе - это я знаю biggrin.gif), что такое детальная текстура?
ДмитрийТ
centrino, я сам пока что нуб но вот сайтик http://neoaxis-rus.com там пара статей вроде есть на эту тему, или посмотри/поспрашивай там на форуме.
centrino
вот что удалось найти по данному вопросу:
http://www.gardener.ru/?id=37
http://bimedev.ru/?tag=/3d+max

осталось неясно: как лучше экспортировать ландшафт в движок, как текстуру или как геометрию, и как, и в том и в другом случае, добавлять на карту статичные объекты, которые, по сути, тоже являются частью ландшафта? и как в таком случае быть с моделями домов, ведь внутри дома тоже можно перемещаться, так что дом - не совсем ландшафт? unsure.gif
Сахаров
Цитата(centrino @ 04.06.2009, 14:34) *
вот что удалось найти по данному вопросу:
http://www.gardener.ru/?id=37
http://bimedev.ru/?tag=/3d+max

пробовал брюс, терраген, ворлдбилдер. лучше из этих трёх брюс.
в максе+фотошоп можно так же запросто делать всё тоже самое, правда памяти это будет жрать больше. брюс умеет делать tessellation(в максе такого нет, там всё это дико тормозит), а плотность сетки указывается уже при экспорте. минус один - сетка получается регулярная в любом случае.


Цитата(centrino @ 04.06.2009, 14:34) *
осталось неясно: как лучше экспортировать ландшафт в движок, как текстуру или как геометрию, и как, и в том и в другом случае, добавлять на карту статичные объекты, которые, по сути, тоже являются частью ландшафта? и как в таком случае быть с моделями домов, ведь внутри дома тоже можно перемещаться, так что дом - не совсем ландшафт?


лучше его вообще не экспортировать, а мухрыжить на месте в игровом редакторе.(мячты)
с каких пор дома стали частью ландшафта?

напиши редактор, суть такова: вкидываеш, или рисуеш прям на месте 2 битмапы - 1-я карта высот, 2-я карта детализации, на выходе получаем не 15млн вершин(еслиб сетка была регулярная), а всего 700К например. совершенно неважно поддерживает tessellation двиг или нет, просто есть места на террайне которые совершенно незачем сильно детализировать, в тоже время есть места которые нуждаются в очень плотной сетке.
centrino
редактор-то написать можно, только вот я не представляю, что он должен редактировать smile.gif

попробовал загружать модельки:



test (copy 3).rar

в принципе можно переделать так, чтобы вместо модели указывать движку на битмапы карты высот, карты детализации и текстуру, для этого только надо приделать диалог и программно устанавливать параметры, которые движок читает из вот такого файла:

terrain.cfg
# The main world texture (if you wish the terrain manager to create a material for you)
WorldTexture=terrain_texture.bmp

# The detail texture (if you wish the terrain manager to create a material for you)

#number of times the detail texture will tile in a terrain tile
DetailTile=3

# Heightmap source
PageSource=Heightmap

# Heightmap-source specific settings
Heightmap.image=terrain.bmp

# If you use RAW, fill in the below too
# RAW-specific setting - size (horizontal/vertical)
#Heightmap.raw.size=128
# RAW-specific setting - bytes per pixel (1 = 8bit, 2=16bit)
#Heightmap.raw.bpp=1

# How large is a page of tiles (in vertices)? Must be (2^n)+1
PageSize=128

# How large is each tile? Must be (2^n)+1 and be smaller than PageSize
TileSize=65

# The maximum error allowed when determining which LOD to use
MaxPixelError=3

# The size of a terrain page, in world units
PageWorldX=7500
PageWorldZ=7500
# Maximum height of the terrain
MaxHeight=100

# Upper LOD limit
MaxMipMapLevel=5

#VertexNormals=yes
#VertexColors=yes
#UseTriStrips=yes

# Use vertex program to morph LODs, if available
VertexProgramMorph=yes

# The proportional distance range at which the LOD morph starts to take effect
# This is as a proportion of the distance between the current LODs effective range,
# and the effective range of the next lower LOD
LODMorphStart=0.2

# This following section is for if you want to provide your own terrain shading routine
# Note that since you define your textures within the material this makes the
# WorldTexture and DetailTexture settings redundant

# The name of the vertex program parameter you wish to bind the morph LOD factor to
# this is 0 when there is no adjustment (highest) to 1 when the morph takes it completely
# to the same position as the next lower LOD
# USE THIS IF YOU USE HIGH-LEVEL VERTEX PROGRAMS WITH LOD MORPHING
#MorphLODFactorParamName=morphFactor

# The index of the vertex program parameter you wish to bind the morph LOD factor to
# this is 0 when there is no adjustment (highest) to 1 when the morph takes it completely
# to the same position as the next lower LOD
# USE THIS IF YOU USE ASSEMBLER VERTEX PROGRAMS WITH LOD MORPHING
#MorphLODFactorParamIndex=4

# The name of the material you will define to shade the terrain
#CustomMaterialName=TestTerrainMaterial


я так думаю, что имеется возможность сохранить полученный материал и геометрию

p.s. вот тут чувак вроде выкладывал исходники своего редактора (правда я че-то их там не нашел biggrin.gif ) http://ogre3d.ru/e107_plugins/forum/forum_...pic.php?20424.0

а вот тут ваще полностью продемонстрирован процесс создания игры при помощи ogre http://www.ogre3d.ru/wik/pmwiki.php?n=Main...%e9%c8%e3%f0%fb


p.p.s. никак с масштабом не разберусь, если в максе выбрать метрическую систему, то в ogre какие-то бешеные цифры в попугаях получаются sad.gif
centrino
а тут вообще подробно рассматривается, как добавлять объекты и перетаскивать их мышью в любое место ландшафта wink_old.gif в общем мне жутко интересно, хотя грабить корованы вряд ли получится cool.gif
centrino
еще один интересный редактор ландшафта, судя по описанию http://www.artifexterra3d.com/

Цитата
Paged and animated grass support.
Support for transparent textures.
Open source C++ scene-loader class for easy project integration.
Open source PHP-GTK based artifex-scene to ogre-dotscene converter.
Mesh based decal cursor resembling the current brush in pattern, size and rotation.
180 degree brush flipping.
Editable project templates.
SQlite based storage system.
Normalmapping and dynamic lighting support.
Infinite custom object value pairs to edit game-content.
50 step Undosystem for all paint and terrain actions.
Artpad support, tested with Wacom Graphire2 and Intous3 pads.
Brushsystem with 10 different brushes, can be infinitely more.
Brushrotation, random, snap to 11.25 steps and degreewise.
Paintpressure is affected by the brightness of the brush you use.
Colourpainting with several different tools: Paint, Erase, Darken, Brighten, Blur, Sharpen, Contrast, Noise and filters: GaussianBlur, Dilate, Edge,Erode,Repair,UnsharpMask,Sharpen,Noise,Clear.
Terrain-shaping with 2 filters, and several different tools: Lower, Raise, Blur, Flatblur, Boil, Plane.
Adding and editing of meshes, rapid placement with space+click for random rotation/placement.
WYSIWYG texture adjusting, RGB, Saturation, Brightness, Contrast.
Backblending of baked splatting textures to reduce texture tile effects.
Texture-painting (splatting) with 9 different textures.
Tested with terrain-sizes of 15000*15000 ogre units.
Detailed documentation and help inside the terrain editor application.
Model pack with trees, plants, buildings.
And more...
centrino
ниасилил, пока пусть тут полежит: исходный код Ogre + OIS + OgreOde
для успешной сборки понадобятся Qt и STL Port



демка: ландшафт + свободная камера
управление: wasd + мышь, выход - esc

карту делал при помощи freewirld3d

Da Man
Ландшафт лучше делать через карту высот, с ней удобно работать и лод хорошо можно организовать
centrino
он и сделан как карта высот smile.gif

редактор говеный, все остальные редакторы для огра, что можно найти в сети - ничем не лучше, надо свой делать инструмент..
HappyMenses
Цитата(centrino @ 30.06.2009, 21:16) *
он и сделан как карта высот smile.gif

редактор говеный, все остальные редакторы для огра, что можно найти в сети - ничем не лучше, надо свой делать инструмент..

Выложи Release сборку демо, не задумывался что у некоторыз людей демка просто не запустится (как например у меня) dry.gif
Da Man
нету debug версий дллок!?
centrino
http://www.microsoft.com/downloads/details...;displaylang=en

хотя не уверен, что в него отладочные версии входят, на всякий случай: http://narod.ru/disk/10393086000/mscrt.rar.html
распаковать непосредственно к остальным бинам.

рекомпил этог дела займет минут 40
HappyMenses
есть у меня ддлки, но все равно почему то не грузится...
Da Man
Цитата
хотя не уверен, что в него отладочные версии входят

debug версий дллок Огра в Visual C++ Redistributable точно нет smile.gif я говорил о дллках огра с окончанием _d, что означает debug
centrino
Da Man, дллки огра собираются из исходников вместе с демкой, они есть в архиве.

релизная сборка: http://narod.ru/disk/10476929000/engine%20...y%204).rar.html
Da Man
Цитата
Da Man, дллки огра собираются из исходников вместе с демкой

я знаю) но демку я не смотрел, а всего лиш предположение высловил - "?!" означает, что не уверен, предполагаю wink.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2022 IPS, Inc.