Page 1 of 1

New vertex format Request[SOLVED]

Posted: Fri Jul 20, 2007 11:32 am
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

Posted: Mon Jul 23, 2007 11:57 am
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?

Posted: Mon Jul 23, 2007 12:20 pm
by beshrkayali
:?:

Posted: Mon Jul 23, 2007 1:24 pm
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.

Posted: Mon Jul 23, 2007 1:33 pm
by belfegor
Thanks Klasker, i will try it. Now i have at least some reference to
start with.

Posted: Fri Jul 27, 2007 9:22 am
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.