Rendern an dll leiten / void Render()

Posted By: marcellus

Rendern an dll leiten / void Render() - 10/26/06 07:31

Hallo,

ich muss für die VisionStation, ist ein Projektionssystem, welches mehr räumliche Tiefe vermitteln soll, die Engine der A6 mit Hilfe des SDK und einer API der Herstellerfirma anpassen. Vereinfacht stellt sich der neue Vorgang des Renderns so dar:

Code:

SPIPreRender(..); // API für VisionStation rendert
AppRender(); // A6 rendert
SPIPostRender(); // API rendert noch einmal



Dieser Code muss in der Direct3D Funktion void Render() stehen.

Nun meine Fragen:

Wie lautet der Code der Engine?

Ist dies vielleicht dieser?

Code:
  
DLLFUNC int Render(void)
{
ENTITY* pEntity = (ENTITY*)ev->me;
BMAP* pSkin = (BMAP*)ev->render_map[0];
LPD3DXMESH pMesh = (LPD3DXMESH)ev->render_mesh;
LPD3DMATERIAL9 pMaterial = (LPD3DMATERIAL9)ev->render_d3dmaterial;
LPD3DXEFFECT pEffect = (LPD3DXEFFECT)ev->render_d3dxeffect;
IDirect3DDevice* pD3dDev = (IDirect3DDevice*)ev->pd3ddev;
Ogre_Render(pD3dDev,pMesh,pSkin,pMaterial,pEffect); // your own render function
return 1; // tell A6 not to render this entity
}



Code stammt von diesem Thread:

http://www.coniserver.net/ubbthreads/sho...true#Post697135

Wie implementiere ich dies in WDL, d.h. wie leite ich den Rendervorgang um?

Besten Dank schon mal im voraus.

Gruß,

marcellus
Posted By: FBL

Re: Rendern an dll leiten / void Render() - 10/26/06 07:38

in WDL bzw C-Script? Garnicht. Das mußt du per DLL machen.
Mit dem obigen Code, kannst du ein Entity mit einem anderen Renderer wie Ogre, Irrlicht, Torque darstellen.
Posted By: marcellus

Re: Rendern an dll leiten / void Render() - 10/26/06 08:20

Ich habe anscheinend meine Lösung gefunden. Ich werde es mal mit den Befehlen render_sky und render_world ausprobieren. Somit benötige ich den Code der Engine gar nicht. Mal schauen ob es funktioniert, sonst melde ich mich noch einmal.

Dass ich die Render-Funktionen in der dll schreibe war mir schon klar.
Posted By: jcl

Re: Rendern an dll leiten / void Render() - 10/26/06 09:33

Korrekt. Wenn Sie nicht einzelne Entities, sondern unabhaengige Szenerien rendern, brauchen Sie nicht den obigen Code, sondern die Render-Events der Engine.
Posted By: marcellus

Re: Rendern an dll leiten / void Render() - 10/26/06 12:49

Danke für die Antworten.

Nach genauerer Studie der API von Elumens (VisionStation) habe ich festgestellt, dass ich das doch nicht über die Events realisieren kann. Denn es gibt da ein paar Besonderheiten (Siehe fettgeschriebenen Code).

//Methode in der dll (Direct3D)

void Render()
{
// Setup the world, view, and projection matrices
SetupMatrices();

if( gDome )
{
gDome->SPIBegin();

gDome->SPIPreRender( SPI_3C_LEFT );
AppRender(); //Render der A6
gDome->SPIPostRender();

gDome->SPIPreRender( SPI_3C_RIGHT );
AppRender();
gDome->SPIPostRender();

gDome->SPIPreRender( SPI_3C_TOP );
AppRender();
gDome->SPIPostRender();

gDome->SPIEnd();

gDome->SPIFlush( SPI_3_CHANNEL, SPI_RENDER_NORMAL );
}

else
{
AppRender();
}

// Present the backbuffer contents to the display
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

Mit AppRender ist die Routine der A6 gemeint. Nun gibt es folgende Fussangeln:


  • Das ganze gerender findet zwischen SPIBegin() und SPIEnd() statt.
  • In der AppRender() darf kein Present() vorkommen. Da wird in der API ausdrücklich darauf hingewiesen. Ich gehe mal davon aus, dass die Engine dies aber macht.


Nun müsste ich also die Rendermethode der A6 Engine in die Methode AppRender() ohne Present() abbilden und im C-Script A6 mitteilen, dass alles über die dll gerendert werden muss. Ist dies so möglich und wie teile ich dies im C-Script mit? render_sky?

Schönen Gruß,

Marcel
Posted By: jcl

Re: Rendern an dll leiten / void Render() - 10/26/06 13:53

Ja, es gibt keine AppRender Funktion, die A6 externen APIs zur Verfuegung stellt. Diese Aufgabenstellung hat sich bisher noch nicht ergeben, ansonsten waere es kein Problem, eine solche Funktion zu implementieren.

Ich nehme an, dass Ihre Applikation den View auf 3 verschiedene Beamer rendert. Machen Sie folgendes:

- Definieren Sie sich 3 Views. Setzen Sie diese auf die Parameter Ihrer 3 Beamer. Ihr SetupMatrices() kann die Engine nicht verwenden.
- Benutzen Sie RenderSky fuer gDome->SPIPreRender und RenderEntities fuer gDome->SPIPostRender. Diese Events werden jetzt pro Frame 3x aufgerufen.
- Werfen Sie den Present() aus Ihrem Code heraus. Present() wird von A6 automatisch nach dem letzten RenderEntities aufgerufen.
Posted By: marcellus

Re: Rendern an dll leiten / void Render() - 10/26/06 18:00

Das interessante ist ja, dass die 3 Views alle an einen Beamer mit einer Speziallinse geschickt werden. Das Bild von dem Beamer wird in eine Halbkugel projiziert.

Quote:

Ja, es gibt keine AppRender Funktion, die A6 externen APIs zur Verfuegung stellt.




Diese AppRender Funktion müsste ich in die dll implementieren, dass wäre quasi Ihr Code.

Quote:

- Werfen Sie den Present() aus Ihrem Code heraus. Present() wird von A6 automatisch nach dem letzten RenderEntities aufgerufen.




Das ist ja gut, na dann werde ich dass mal mit den Events ausprobieren. Ich melde mich dann ob es funktionier hat.

Viele Grüße,

Marcel
Posted By: TSG_Christof

Re: Rendern an dll leiten / void Render() - 10/28/06 05:29

Oh mann respekt also euer fachwissen möchte mann haben lol
Posted By: marcellus

Re: Rendern an dll leiten / void Render() - 10/29/06 21:25

Ich bin es wieder. Ich habe mir jetzt mal eine dll gebacken. Die wird auch brav von der Engine akzeptiert, jedoch sitzte ich vor einem schwarzen Bildschirm und mein Rechner spricht auch nicht mehr mit mir. Er ist aber nicht abgestürzt, sondern er hört die Tastatur nicht mehr so gut, er ist also quasi etwas taub. Nun vermute ich, dass es mehrere verschiedene Bauststellen gibt, denn es werden verschiedene dll's benutzt. Aber nun zu meinen Fragen:

Wie oft und wo kann ich meine Render Events setzten? Ich habe den Code in der main() Funktion geschrieben, siehe hier:

dllfunction initDOME();
dllfunction initSPI();
dllfunction closeSPI();
dllfunction preRenderLEFT();
dllfunction preRenderRIGHT();
dllfunction preRenderTOP();
dllfunction postRender();

....

function main()
{
appdll_handle = dll_open("visionStation.dll");
MAX_PARTICLES = 10000;
if (curlevel==1){ level_load(welt);}
else{ level_load(welt);}
initDome();
while(1){
initSPI();
render_sky = preRenderLEFT();
render_entities = postRender();
render_sky = preRenderRIGHT();
render_entities = postRender();
render_sky = preRenderTOP();
closeSPI();
}
//init_rand();
wait(2);
}

Muss ich dass in eine while(1) Schleife packen? Ich möchte gerne, dass pro Frame 9 mal (unterschiedliche Blickwinkel) gerendert wird.

Für Antworten bin ich dankbar. Falls noch Infos fehlen, einfach melden.

Gruß,

marcellus
Posted By: TWO

Re: Rendern an dll leiten / void Render() - 10/30/06 05:04

So weit ich mich erinnern kann sollte das Event auserhalb einer Funktion gesetzt werden, und ohne Klammern

function main()
{
initSPI();
closeSPI();
}

render_sky = preRenderLEFT;
render_entities = postRender;
render_sky = preRenderRIGHT;
render_entities = postRender;
render_sky = preRenderTOP;

Das Event sollte überprüfen ob die API am Laufn is. Und wenn du ein Event zweifach setzt überschreibt AFAIK das Zweite das Erste.

Versuch mal eine Wrapperfunktion die je nach view eine andere Funktion aufruft, bzw die camera jeden frame während des zeichnens mehr fach versetzt.
Posted By: jcl

Re: Rendern an dll leiten / void Render() - 10/30/06 09:34

Oje, da sehe ich gleich eine ganze Menge von Fehlern.

dll_open brauchen Sie nicht. Kopieren Sie Ihre DLL in den acknex_plugins ordner.

Ihre while-Schleife ist eine klassische Endlosschleife und laesst Ihrem PC ertauben. Setzen Sie Ihre Events nur einmal und nicht in einer Schleife. Ich weiss zwar nicht, was initSPI(); und closeSPI(); machen, vermute aber stark, dass sie keinesfalls in die main-Funktion gehoeren, sondern eher an den Anfang des ersten und an den Schluss des letzten Render-Event.

Die Render-Events dagegen duerfen Sie zwar in der Main-Funktion setzen, jedoch keinesfalls - so wie Sie's getan haben - dort aufrufen. Denn auch das fuehrt sicherlich zum Absturz. Und da es nur zwei Events gibt und nicht fuenf, muessen Sie in Ihrem Event selbst unterscheiden, welcher View gerade gerendert wird - fragen Sie dazu ev->render_view ab.
Posted By: marcellus

Re: Rendern an dll leiten / void Render() - 12/19/06 17:09

So ich bin es mal wieder. Hatte Zeit mich mal diesem Problem zu widmen.

Ich habe das jetzt mal nur mit einem Kanal (View) ausprobiert. Doch nun habe ich das Problem, dass die Welt der Engine nicht in meinem "g_pd3dDevice" ist. In diesem Objekt müsste ein komplett gerenderter Frame inklusive BeginScene und EndScene sein.

Im WDL steht: -------------------------------

function main()
{
MAX_PARTICLES = 10000;
if (curlevel==1){ level_load(welt);}
else{ level_load(welt);}
initDome();
wait(2);
}

render_sky = initSPI();
render_entities = closeSPI();

------------------------------

In der dll steht: -----------

VOID SetupMatrices()
{
// For our world matrix, we will just leave it as the identity
D3DXMATRIXA16 matWorld;
D3DXMatrixRotationY( &matWorld, timeGetTime()/1000.0f );
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

// Set up our view matrix. A view matrix can be defined given an eye point,
// a point to lookat, and a direction for which way is up. Here, we set the
// eye five units back along the z-axis and up three units, look at the
// origin, and define "up" to be in the y-direction.
D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-3.0f );
D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
D3DXMATRIXA16 matView;
D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

// For the projection matrix, we set up a perspective transform (which
// transforms geometry from 3D view space to 2D viewport space, with
// a perspective divide making objects smaller in the distance). To build
// a perpsective transform, we need the field of view (1/4 pi is common),
// the aspect ratio, and the near and far clipping planes (which define at
// what distances geometry should be no longer be rendered).
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}

DLLFUNC void initDOME(void)
{

g_pd3dDevice = (LPDIRECT3DDEVICE9)draw_begin();
if (!g_pd3dDevice) return;

// Turn on the zbuffer
g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

// Turn on ambient lighting
g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );

// We need the projection matrix to exist in a nice form before creating the
// dome object, so we call SetupMatrices() here.
SetupMatrices();

if( !gDome )
{
gDome = new SPIDX9Dome( g_pd3dDevice, 512, 512, 21, SPI_1_CHANNEL );
}
}

DLLFUNC void initSPI(void){
SetupMatrices();
gDome->SPIBegin();
gDome->SPIPreRender(SPI_1C_FRONT);
}

DLLFUNC void closeSPI(void){

gDome->SPIPostRender();
gDome->SPIEnd();
gDome->SPIFlush( SPI_1_CHANNEL, SPI_RENDER_NORMAL );
}

-------------

Die dll funktioniert, da ist kein Bug drin, wird auch alles aufgerufen und es existieren keine null-Objekte.

3D Gamesstudio startet auch anstandslos und ich erhalte einen blauen Bildschirm, wie in der Beispielapplikation der API. Das einzige was fehlt, ist die 3D Welt der Engine. Gibt es da nicht eine Code der die Renderfunktion aufruft bzw. abbildet.

SetupMatrices ist sehr wichtig, denn sie ist für die Berechnung der Verzerrung zuständig.

Schönen Gruß und frohe Weihnachten

Marcel
Posted By: jcl

Re: Rendern an dll leiten / void Render() - 12/20/06 12:12

Setzen von World-Matrix und Renderstates macht hier keinen Sinn. Diese sind ja an Entities gekoppelt und koennen daher nicht global gesetzt werden, sondern nur individuell per Entity waehrend des Renderns. Und beim Setzen der Renderevents gibt's wieder den ueblichen Anfaengerfehler mit dem Verwechseln von Funktionspointern und Funktionsaufrufen. Lassen Sie die Klammern weg.

Ansonsten koennte das Ganze auf den ersten Blick zumindest von der Programmstruktur her funktionieren. Im Detail kann ich den Code nicht kommentieren, da ich nicht weiss, wozu das Dome-Objekt dient und was die einzelnen Funktionen tun.

Ich will Ihnen nicht zu nahe treten, aber vielleicht ist es sinnvoll, sich erst einmal gruendlich in C/C++ und DirectX einzuarbeiten, bevor Sie sich an ein solches Projekt wagen. An dem Code sehe ich, dass Sie noch nicht viel Erfahrung mit dem Programmieren haben. Da ist die Einbindung eines DirectX-bsierten Treibers vielleicht eine zu harte Nuss.
Posted By: marcellus

Re: Rendern an dll leiten / void Render() - 12/20/06 14:44

Danke für die Antwort, jetzt wo Sie es sagen, werde ich die Klammern mal weg lassen.

Ich muss zugeben, dass ich mit C/C++ und DirectX noch nie programmiert habe. Jedoch programmiere ich schon ca. 5 Jahre in Java. Und, wieso sollte man seinen Horizont nicht erweitern. Ich werde mich mal gründlich mit der Zeigerproblematik in C++ und mit den DirectX Objekten auseinandersetzen.

Ich melde mich dann mal. wenn es funktioniert.

Bis die Tage,

Marcel
© 2024 lite-C Forums