New vertex format Request[SOLVED]

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
belfegor
Posts: 383
Joined: Mon Sep 18, 2006 7:22 pm
Location: Serbia

New vertex format Request[SOLVED]

Post by belfegor »

I have made mesh with tangents and 2 tex coord info, and used it with my
shader "SpecularBumpMapWithLightMap4Lights.fx", it looks/works great in
my DX app but irrlicht cant load that mesh it throws message (something like):

Code: Select all

"Unknown data object in file mesh.x : SDec"
even if that could load i couldnt get effect that i have with DX app
(i know from previous expiriences, bad results), probably there must be also need for
new vertex format EVF_TANGENT_AND_TWO_TEX_COORDS and what more else?
(i am not familiar with irrlicht inner workings of reading/parsing .X files
they are prety advanced for me right now) am i right?

In 3ds MAX first i created mesh with diffuse tex. only (played with Unwrap
UVW modifier), then with same model (without diff. tex.) put some
lights and bake light map (now i have two models), then i convert them
with this code into one with neccesary tangent, binormal 2 tex coord info:

Code: Select all

#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9d.lib")

bool InitializeMeshes();
bool InitializeDirect3D(HWND hwnd);
void RenderScene();
void ShutdownDirect3D();

LPDIRECT3D9       d3d       = NULL;
LPDIRECT3DDEVICE9 d3dDevice = NULL;

ID3DXMesh*   MeshWithDiffuseTexCoord;
ID3DXMesh*   MeshWithLightMapTexCoord;
ID3DXMesh*   MeshToSave;

D3DVERTEXELEMENT9 SDec[] =
{
	{0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
	{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0},
	{0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,  0},
	{0, 36, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0},
	{0, 48, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
	{0, 56, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
	D3DDECL_END()
};


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
       {
		   case WM_KEYUP:
            if(wParam == VK_ESCAPE)
               PostQuitMessage(0);
            break;

         case WM_DESTROY:
         case WM_CLOSE:
            PostQuitMessage(0);
            break;
            default:
               break;
       }
    return DefWindowProc( hwnd, message, wParam, lParam );
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
   MSG msg; 
   HWND hwnd; 
   WNDCLASSEX windowClass;
   ZeroMemory(&windowClass, sizeof(windowClass));

   windowClass.cbSize          = sizeof(WNDCLASSEX); 
   windowClass.style           = CS_HREDRAW | CS_VREDRAW;
   windowClass.lpfnWndProc     = WndProc; 
   windowClass.cbClsExtra      = NULL;                       
   windowClass.cbWndExtra      = NULL;                       
   windowClass.hInstance       = hInstance;                 
   windowClass.hIcon           = LoadIcon(NULL, IDI_APPLICATION);
   windowClass.hCursor         = LoadCursor(NULL, IDC_ARROW); 
   windowClass.hbrBackground   = NULL;                
   windowClass.lpszMenuName    = NULL;         
   windowClass.lpszClassName   = L"Name";         
   windowClass.hIconSm         = LoadIcon(NULL, IDI_APPLICATION);
   if(!RegisterClassEx(&windowClass)) return 0;

   DWORD winStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_SYSMENU |WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
   hwnd = CreateWindowEx(
	   NULL,                                     
	   L"Name", L"App",   
	   winStyle,                        
	   100, 100, 640, 480,                                  
	   NULL, NULL,                                    
	   hInstance, NULL);

   if(!hwnd) return 0;

   ShowWindow(hwnd, SW_SHOW);
   UpdateWindow(hwnd);

   if(!InitializeDirect3D(hwnd)) 
   {
	   MessageBoxA(NULL, "There were errors in app. Exit!", NULL, NULL);
	   goto the_end;
   }

   while(TRUE)
   {
	   if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	   {
		   if(msg.message == WM_QUIT)
			   break;

		   TranslateMessage(&msg);
		   DispatchMessage(&msg);
	   }
	   RenderScene();
   }
the_end:
   ShutdownDirect3D();
   UnregisterClass(L"Name", windowClass.hInstance);
   return (int)msg.wParam;
}


bool InitializeDirect3D(HWND hwnd)
{
   D3DDISPLAYMODE DisplayMode;
   D3DPRESENT_PARAMETERS Present_Parameters;
   ZeroMemory(&Present_Parameters, sizeof(Present_Parameters));
   D3DCAPS9 D3DCaps;
   ZeroMemory(&Present_Parameters, sizeof(Present_Parameters));
   d3d = Direct3DCreate9(D3D_SDK_VERSION);
   if(d3d == NULL)
   {
	   MessageBoxA(NULL, "Error, couldn't initialize DirectX!?!", NULL, NULL);
	   return false;
   }
   if(FAILED(d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &DisplayMode)))
   {
	   MessageBoxA(NULL, "Error setting the display mode.", NULL, NULL);
	   return false;
   }
   if(FAILED(d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps)))
   {
	   MessageBoxA(NULL, "Failed to get device caps.", NULL, NULL);
	   return false;
   }
   DWORD VertexProcessing = 0;
   if(D3DCaps.VertexProcessingCaps != 0)
	   VertexProcessing |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
   else
	   VertexProcessing |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;


   Present_Parameters.Windowed               = TRUE; 
   Present_Parameters.SwapEffect             = D3DSWAPEFFECT_DISCARD;
   Present_Parameters.BackBufferFormat       = DisplayMode.Format;
   Present_Parameters.BackBufferCount        = 1;                 
   Present_Parameters.EnableAutoDepthStencil = TRUE;        
   Present_Parameters.AutoDepthStencilFormat = D3DFMT_D16;  

   if(FAILED(d3d->CreateDevice(
	   D3DADAPTER_DEFAULT, 
	   D3DDEVTYPE_HAL, hwnd,
	   VertexProcessing,
	   &Present_Parameters, &d3dDevice)))
   {
	   MessageBoxA(NULL, "CreateDevice() failed!", NULL, NULL);
	   return false;
   }
   d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
   if(!InitializeMeshes())return false;

   return true;
}


void RenderScene()
{
   d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET,  D3DCOLOR_XRGB(0, 0, 64), 1.0f, 0);
   d3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 64), 1.0f, 0);
   d3dDevice->BeginScene();

   // Do nothing
    
   d3dDevice->EndScene();
   d3dDevice->Present(NULL, NULL, NULL, NULL);
}


void ShutdownDirect3D()
{
	if(MeshWithDiffuseTexCoord != NULL)
	{
		MeshWithDiffuseTexCoord->Release();
		MeshWithDiffuseTexCoord = NULL;
	}
	if(MeshWithLightMapTexCoord != NULL)
	{
		MeshWithLightMapTexCoord->Release();
		MeshWithLightMapTexCoord = NULL;
	}
	if(MeshToSave != NULL)
	{
		MeshToSave->Release();
		MeshToSave = NULL;
	}
   if(d3dDevice != NULL)
   {
	   d3dDevice->Release();
	   d3dDevice = NULL;
   }
   if(d3d != NULL)
   {
	   d3d->Release();
	   d3d = NULL;
   }
}

bool InitializeMeshes()
{
	if(FAILED(D3DXLoadMeshFromX(
		L"DiffTexCoordMesh.X", 
		D3DXMESH_MANAGED, 
		d3dDevice,
		NULL, NULL, NULL, NULL, 
		&MeshWithDiffuseTexCoord)))
	{
		MessageBoxA(NULL, "Failed to load mesh : DiffTexCoordMesh.X!", NULL, NULL);
		return false;
	}
	if(FAILED(D3DXLoadMeshFromX(
		L"LightMapTexCoordMesh.X", 
		D3DXMESH_MANAGED, 
		d3dDevice,
		NULL, NULL, NULL, NULL, 
		&MeshWithLightMapTexCoord)))
	{
		MessageBoxA(NULL, "Failed to load mesh : LightMapTexCoordMesh.X!", NULL, NULL);
		return false;
	}
	if(FAILED(MeshWithDiffuseTexCoord->CloneMesh(
		D3DXMESH_DYNAMIC, SDec, d3dDevice, &MeshToSave)))
	{
		MessageBoxA(NULL, "Failed to CloneMesh()!", NULL, NULL);
		return false;
	}
	struct MeshVertex
	{
		D3DXVECTOR3 Pos;
		D3DXVECTOR3 Normal;
		FLOAT U1, V1;
	};
	struct LMBMMeshVertex
	{
		D3DXVECTOR3 Position;
		D3DXVECTOR3 Normal;
		D3DXVECTOR3 Tangent;
		D3DXVECTOR3 Binormal;
		FLOAT U1, V1;
		FLOAT U2, V2;
	};
	MeshVertex*      NormalVertex;
	LMBMMeshVertex*  LMBMVertex;
	MeshWithLightMapTexCoord->LockVertexBuffer(0L, (LPVOID*)&NormalVertex);
	MeshToSave->LockVertexBuffer(0L, (LPVOID*)&LMBMVertex);
	DWORD NumOfVert = MeshToSave->GetNumVertices();
	for(DWORD k = 0; k < NumOfVert; k++)
	{
		LMBMVertex[k].U2     = NormalVertex[k].U1;
		LMBMVertex[k].V2     = NormalVertex[k].V1;
	}
	if(FAILED(D3DXComputeTangent(
		MeshToSave, NULL, NULL, NULL, TRUE, NULL)))
	{
		MessageBoxA(NULL, "Failed to D3DXComputeTangent()!", NULL, NULL);
		return false;
	}
	MeshWithLightMapTexCoord->UnlockVertexBuffer();
	MeshToSave->UnlockVertexBuffer();
	if(FAILED(D3DXSaveMeshToX(L"TangentAnd2TexCoordMesh.x", MeshToSave, NULL, NULL, NULL, NULL, D3DXF_FILEFORMAT_TEXT)))
	{
		MessageBoxA(NULL, "Failed to D3DXSaveMeshToX()!", NULL, NULL);
		return false;
	}
	return true;
}
can you update irrlicht to load this model (i saved it as text file
so you can easely examine it):

http://www.geocities.com/ejebemtisestru ... oordMesh.x

if you wish i can provide test DX app to see effect.

also i think Bitplain said to upload models that work with MView but
not with irrlicht so here it is.
Any test app that i have tried with irrlicht (bump mapping/ parallax)
have incorrect lighting, strange artifacts but works great with pure DX
based apps.Very disapointing.:cry:

Hope you can understand what i want.

Belfegor.

PS. i have tried it with irlicht with DX calls, it works but i lose all texture
on models that i have loaded with irrlicht (only geometries are shown
with their vertex colors but no texture) probably have something to
do with renderStates but what/where? :P
Last edited by belfegor on Fri Jul 27, 2007 9:24 am, edited 1 time in total.
Small FPS demo made using Irrlicht&NewtonDEMO
InfoHERE
Its at very early stage but i think im crazy enough to finish it all alone.
belfegor
Posts: 383
Joined: Mon Sep 18, 2006 7:22 pm
Location: Serbia

Post by belfegor »

Anyone. C'mon people, i dont have plague or something. Do I?
Or you need more info? Or noone needs Lightmaped mesh with specular bump map effect? :cry:

Or you all using OpenGL and Linux?
Small FPS demo made using Irrlicht&NewtonDEMO
InfoHERE
Its at very early stage but i think im crazy enough to finish it all alone.
beshrkayali
Posts: 85
Joined: Mon Jun 11, 2007 11:22 am
Location: Damascus - Syria
Contact:

Post by beshrkayali »

:?:
Klasker
Posts: 230
Joined: Thu May 20, 2004 8:53 am
Contact:

Post by Klasker »

A while back I made a patch for custom vertex types in Irrlicht, but it is for OpenGL only and for an older version of Irrlicht. Not very convenient in your situation, but you can give it a try if you want. :arrow: Link. If you are savvy enough maybe you can even add support for it in the DX driver as well.

It is not the most elegant solution, though. A more generalized way of sending vertex data to the video driver would be a good idea. Like, sendVertexPositions(), sendVertexNormals(), etc, ending with a doneVertexTransfer() or something.
belfegor
Posts: 383
Joined: Mon Sep 18, 2006 7:22 pm
Location: Serbia

Post by belfegor »

Thanks Klasker, i will try it. Now i have at least some reference to
start with.
Small FPS demo made using Irrlicht&NewtonDEMO
InfoHERE
Its at very early stage but i think im crazy enough to finish it all alone.
belfegor
Posts: 383
Joined: Mon Sep 18, 2006 7:22 pm
Location: Serbia

Post by belfegor »

I have found workaround for this problem.
In "IrrCompileConfig" comment out OpenGL, Software, DX8 dr.that
i dont use and theni have added one function to video driver
something like"preCustomRender". In CD3D9Driver :

Code: Select all

// I forgat exact names but its something like this
void CD3D9Driver::preCustomRender()
{
	setVertexShader((E_VERTEX_TYPE)666);
	if(!set3DRenderMode())
	{
		os::Printer::log("Set3RenderMode() Failed", ELL_WARNING);
	}
}

and

void CD3D9Driver::setVertexShader(E_VERTEX_TYPE newType)
{
	if(newType != LastVertexType)
		LastVetexType = newType;
	...
	case 666:
		break;
	...
}


and now i create custom scene nodes and set proper OnRegisterSceneNode pass
(in my case SpecBumpMapWithLightMap):

Code: Select all

scene::ESNRP_SOLID
and then in render func.:

Code: Select all

...
Driver->SetTransform(video::ETS_WORLD, AbsoluteTransformation);
Driver->preCustomRender();
...
and then i can use:

Code: Select all

...
D3DXMATRIXA16 world = D3DXMATRIXA16(AbsoluteTransformation.pointer());
Effect->SetTehnique("Parallax");//or whatever
Effect->SetMatrix("world", &world);
...
data.D3D9.D3D9Dev->DrawPrimitive...();
or:

Code: Select all

XMesh->DrawSubset(0);
with DX fx file effects with multipass and everything.
I know its not proper think to do but it works. Acctualy i dont need
new vertex format when i have found this. If someone is interested
i could code snniped it with detailed description and examples.
Small FPS demo made using Irrlicht&NewtonDEMO
InfoHERE
Its at very early stage but i think im crazy enough to finish it all alone.
Post Reply