# New ReleaseD3D9Client Development

#### asbjos

##### tuanibrO
The graphics client MFD sketchpad seems to only support polygons up to 64-gons (skp->Polygon()), while the inline graphics seems to be unlimited.
Is the same possible for the D3D9 client? Or can the maximum at least be increased? (I need an approx 600-gon )

D3D9 64-gon:

D3D9 65-gon:

Inline client 2000-gon:

The demo MFD is attached, if you want to experiment yourself.

#### Attachments

• GraphicsMFDPolygonFillTest.zip
9.5 KB · Views: 0

#### jarmonik

Beta Tester
The graphics client MFD sketchpad seems to only support polygons up to 64-gons (skp->Polygon()), while the inline graphics seems to be unlimited.
Is the same possible for the D3D9 client? Or can the maximum at least be increased? (I need an approx 600-gon )

Yes, it's been limited to 64-gon since it's a pretty heavy process to triangulate a polygon for a hardware rendering. What exactly are you doing that requires a polygon ? Would it be possible to use ellipse instead ? Of course, I can increase the limit to 1024-gon but I have no idea how it's going to work. D3D9 Has a "CreateTriangles()" function for more efficient drawing and "void SetWorldTransform(const FMATRIX4 *pWT = NULL)" also exists.

#### asbjos

##### tuanibrO
I'm using skp->Polygon for making the daylight fill in a non-rectangular map.

Thanks for the hint about CreateTriangles. Do you know of any samples I could look at for implementing? Never heard about it before, and I find it difficult to understand from the API (I'm not a professional programmer ).

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

I also see that there is the CreatePoly function. I tried to implement it, using:
C++:
#include "gcAPI.h"

{
double radius = double(W / 2) * 0.95; // almost fill MFD, but not quite.

oapi::FVECTOR2 myPolygon[MAX_POLYGON_SIDES];

for (int i = 0; i < numberOfSides; i++)
{
myPolygon[i].x = W / 2 + radius * cos(double(i) / double(numberOfSides) * PI2);
myPolygon[i].y = H / 2 + radius * sin(double(i) / double(numberOfSides) * PI2);
}

HPOLY myPoly = gcCreatePoly(NULL, myPolygon, numberOfSides);
skp2->QuickBrush(0xA0000088);
skp2->QuickPen(0xA000FF00);
skp2->DrawPoly(myPoly);
}
But I don't get anything in the MFD.
Should be noted that I get the compile error: C:\Orbiter2016\Orbitersdk\include\gcConst.h(466,1): error C2440: 'return': cannot convert from 'oapi::FVECTOR4' to 'oapi::FVECTOR4 &', which references the code block
C++:
inline FVECTOR4& operator*= (float f)
{
return FVECTOR4(x * f, y * f, z * f, w);
}
So I simply commented it out. Not sure if that's allowed, though.

Last edited:

#### Gargantua2024

##### Well-known member
Hello, I have a problem: Whenever I open Orbiter in D3D9 mode, I notice that the clouds on Venus have trouble rendering properly (screenshot below). Any ideas?

#### jarmonik

Beta Tester
I'm using skp->Polygon for making the daylight fill in a non-rectangular map.
That's a lot more complicated that I ever though. I have attached a new DLL (place to /Plugins/) into the post where n-gon limit should be increased to 1024. It's an N^2 process so with 600-gon the inner loop that will process the "ears" will run 360'000 times. At least the stock MapMFD is causing a performance impact, there is a small freeze every time when the MFD is updated.

A Modern method to draw something like that would be a solution that would allow the source data to remain constant. Only a projection parameters would change over time. GPU can do trigonometric calculations without problems, so, pretty complex projections are possible. One problem would be dis-continuities, for an example if the vessel remains centered and the background map rotates and the coastal lines are continuous, then some horizontal lines would appear where the coastal line jumps from left edge to right edge. But if the map would be a 3D having a front and back sides meaning that coastal geometry would repeat twice so technically full circle would be 720 degrees.

I have never given much thought for a map rojections like that, you might have more insight, would it be possible to keep the source data constant and do projection calculations on a shader/client side with the GPU ?

Thanks for the hint about CreateTriangles. Do you know of any samples I could look at for implementing? Never heard about it before, and I find it difficult to understand from the API (I'm not a professional programmer ).

I used a following code the create a color picker seen over here: https://www.orbiter-forum.com/threads/d3d9client-development.16787/post-262584

C++:
float a = 0.0f;
float s = float(PI2/6.0);

oapi::TriangleVtx Vtx[8];
oapi::FVECTOR2 Pol[6];

for (int i = 0; i < 6; i++) {
Pol[i].x = cos(a);
Pol[i].y = sin(a);
Vtx[i + 1].pos.x = Pol[i].x;
Vtx[i + 1].pos.y = Pol[i].y;
Vtx[i + 1].color = gcColor(&HUEtoRGB(a));
a += s;
}

// Center vertex
Vtx[0].pos.x = 0.0f;
Vtx[0].pos.y = 0.0f;
Vtx[0].color = 0xFFFFFFFF;    // White
Vtx[7] = Vtx[1];

hPoly[0] = gcCreateTriangles(NULL, Vtx, 8, PF_FAN);

gcCreatePoly function only creates polylines it doesn't create filled polygon. I see nothing wrong in the code except object allocation, one "global" object should be used but it doesn't explain the lack out output. I need to run some tests...

EDIT: There is one example program located in OrbiterSDK/samples/DrawOrbits/ which will use gcCreatePoly() pre-created "unit" Orbit templates to draw orbital lines in a planetarium view.

C++:
#include "gcAPI.h"

HPOLY g_myPoly = NULL;   // Allocate one global object

{
double radius = double(W / 2) * 0.95; // almost fill MFD, but not quite.

oapi::FVECTOR2 myPolygon[MAX_POLYGON_SIDES];

for (int i = 0; i < numberOfSides; i++)
{
myPolygon[i].x = W / 2 + radius * cos(double(i) / double(numberOfSides) * PI2);
myPolygon[i].y = H / 2 + radius * sin(double(i) / double(numberOfSides) * PI2);
}

g_myPoly = gcCreatePoly(g_myPoly, myPolygon, numberOfSides);
skp2->QuickBrush(0xA0000088);
skp2->QuickPen(0xA000FF00);
skp2->DrawPoly(myPoly);
}

#### Attachments

• D3D9Client.zip
528.2 KB · Views: 3
Last edited:

#### jarmonik

Beta Tester
Triangle strip PF_STRIP layout should be following: (this is probably one of those feature that's never been tested)

Code:
0---2---4---
| \ | \ | \
1---3---5---

or

1---3---5---
| \ | \ | \
0---2---4---

#### jarmonik

Beta Tester
Hello, I have a problem: Whenever I open Orbiter in D3D9 mode, I notice that the clouds on Venus have trouble rendering properly (screenshot below). Any ideas?
Ok, Thanks, Will look into it...

#### Marg

##### Active member
Just wanted to write that I still often (chance ~25 - 30%) do not have vessel shadows (and self shadows). If I reload scenario, it's OK. I use Gattispilot's shuttle's, but it should have nothing to do with this, I think, because reloading works. What causes this is possibly buried deep in a code.

#### Abloheet

Hello, I have a problem: Whenever I open Orbiter in D3D9 mode, I notice that the clouds on Venus have trouble rendering properly (screenshot below). Any ideas?
View attachment 22744

This seems to be the problem with a Venus terrain addon for orbiter 2016. The clouds supplied with the addon are known to be buggy. The terrain and textures work fine. You have to go to the Venus.cfg file in Config folder and remove the CloudFormat = 2 line under Visualisation Parameters. Then it will use Orbiter stock .tex clouds, which work fine

#### Gargantua2024

##### Well-known member
This seems to be the problem with a Venus terrain addon for orbiter 2016. The clouds supplied with the addon are known to be buggy. The terrain and textures work fine. You have to go to the Venus.cfg file in Config folder and remove the CloudFormat = 2 line under Visualisation Parameters. Then it will use Orbiter stock .tex clouds, which work fine
Got the clouds working again! Thanks
(Replaced the stock 2016 clouds with those on Venus 8 level texture since they're the same format)

#### Ripley

##### Tutorial translator
Donator
Got the clouds working again! Thanks
(Replaced the stock 2016 clouds with those on Venus 8 level texture since they're the same format)

#### Gargantua2024

##### Well-known member
I did follow Abloheet's advice....I just notice that the default 2016 cloud is named "Venus_cloud.tex", so I easily replaced it with the one built for 2010.

I just liked that texture way back when my version of Orbiter is 2010

#### asbjos

##### tuanibrO
Thank you for the help, jarmonik!

The supplied dll works great. I in fact do not notice a difference, even with 400-600 polygon sides (skp->Polygon), although I use a quite low MFD refresh rate (0.1 s), so there may be a difference that is not apparent at this rate.

There is some flickering of specific triangles though, but this also happens with the inline client (although not as frequently). It seems to occur when the vertices are not evenly spaced.
I assume that this will be fixed by using the gcCreateTriangles function, when the graphics client does not need to guess the geometry of my shape, but I can control them manually.

So onto that problem:

I tried to implement your gcCreatePoly example, but the MFD does not display any lines. I suspect it has something to do with me commenting out the FVECTOR4& operateor*= function (see end of my previous post). So can you please explain how one would fix the compile error?

I also tried to compile your basic example of the hexagon using gcCreateTriangles, but I get a compile error displaying the following information:
1>LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library 1>GraphicsMFDPolygonFillTest.obj : error LNK2001: unresolved external symbol "void * __cdecl gcCreateTriangles(void *,struct gcCore::TriangleVtx const *,int,unsigned long)" ([email protected]@[email protected]@@[email protected]) 1>..\..\..\..\Modules\Plugin\GraphicsMFDPolygonFillTest.dll : fatal error LNK1120: 1 unresolved externals 1>Done building project "GraphicsMFDPolygonFillTest.vcxproj" -- FAILED.
I've added gcAPI.lib, in addition to the default Orbiter libraries. Do I need an extra library, or maybe a special VS setting?

As for your thoughts about using a constant daylight shape, and transforming it, I'm too new to the field of graphics to give you an answer.
But most/all of the map projections in my MFD are reasonably simple, mostly being combinations of trigonometric functions, and some using higher powers (up to 9) and square roots, numeric iteration (Newton's method to solve an equation), and logarithms.

#### jarmonik

Beta Tester
But most/all of the map projections in my MFD are reasonably simple, mostly being combinations of trigonometric functions, and some using higher powers (up to 9) and square roots, numeric iteration (Newton's method to solve an equation), and logarithms.
Thanks, I took a quick look into that and even though it's a little a bit more complex than I hoped it should be still well do-able with the GPU, but I still need to study it in more detail. In what kind of format the coastal line data is in ? Is it in polar coordinates (lng, lat) or 2D cylindrical projection (x, y) or something else ?

As for the compilation error, Sorry About That, it looks like the gcCreateTriangles is missing from gcAPI.lib for some unknown reason. Since, we do rely on automation, it's possible that auto-merge has messed something up. I no longer have Visual Studio 2008 on my new computer, so, I can't recompile the gcAPI.lib without finding and installing that old compiler. Also the gcAPI is no longer being developed since it's been replaced by new gcCore interface that is much easier to maintain. So, the "CreateTriangles" is available under that interface. To use it you no longer need the gcAPI.h nor gcAPI.lib just the gcConst.h

Here's the above example translated to gcCore

C++:
#include "gcConst.h"

gcCore *pCore = gcGetCoreInterface();

if (pCore) {

float a = 0.0f;
float s = float(PI2 / 6.0);

gcCore::TriangleVtx Vtx[8];
oapi::FVECTOR2 Pol[6];

for (int i = 0; i < 6; i++) {
Pol[i].x = cos(a);
Pol[i].y = sin(a);
Vtx[i + 1].pos.x = Pol[i].x;
Vtx[i + 1].pos.y = Pol[i].y;
Vtx[i + 1].color = pCore->Color(&HUEtoRGB(a));
a += s;
}

// Center vertex
Vtx[0].pos.x = 0.0f;
Vtx[0].pos.y = 0.0f;
Vtx[0].color = 0xFFFFFFFF;    // White
Vtx[7] = Vtx[1];

hPoly[0] = pCore->CreateTriangles(NULL, Vtx, 8, PF_FAN);
}

#### GLS

Also the gcAPI is no longer being developed since it's been replaced by new gcCore interface that is much easier to maintain.
Is this finished now?

#### jarmonik

Beta Tester
Is this finished now?

Depends on what you mean by finished. I guess it's never really finished but it should be reasonably stable now.

I made some tests and trials with the "CreatePoly" and "CreateTriangles" functions and they seem to work as intended.

C++:
// Run Different Kind of Tests
//

hTgt = oapiCreateSurfaceEx(768, 512, OAPISURFACE_RENDERTARGET);

if (!hTgt) return;

gcCore *pCore = gcGetCoreInterface();

if (!pCore) return;

float a = 0.0f;
float s = float(PI2 / 6.0);

gcCore::TriangleVtx Vtx[8];
oapi::FVECTOR2 Pol[6];

for (int i = 0; i < 6; i++) {
Pol[i].x = cos(a);
Pol[i].y = sin(a);
Vtx[i + 1].pos.x = Pol[i].x;
Vtx[i + 1].pos.y = Pol[i].y;
a += s;
}

//                 AABBGGRR
Vtx[1].color = 0xFFFF0000;
Vtx[2].color = 0xFFFFFF00;
Vtx[3].color = 0xFF00FF00;
Vtx[4].color = 0xFF00FFFF;
Vtx[5].color = 0xFF0000FF;
Vtx[6].color = 0xFFFF00FF;

// Center vertex
Vtx[0].pos.x = 0.0f;
Vtx[0].pos.y = 0.0f;
Vtx[0].color = 0xFFFFFFFF;    // White
Vtx[7] = Vtx[1];

HPOLY hColors = pCore->CreateTriangles(NULL, Vtx, 8, PF_FAN);
HPOLY hOutline = pCore->CreatePoly(NULL, Pol, 6, PF_CONNECT);
HPOLY hOutline2 = pCore->CreatePoly(NULL, Pol, 6);

Vtx[0].color = 0xFFFF0000;
Vtx[1].color = 0xFFFFFF00;
Vtx[2].color = 0xFFF0FF00;
Vtx[3].color = 0xFF00FFFF;
Vtx[4].color = 0xFF0000FF;
Vtx[5].color = 0xFFFF00FF;

Vtx[0].pos = FVECTOR2(-1, 0);
Vtx[1].pos = FVECTOR2(-1, 1);
Vtx[2].pos = FVECTOR2(0, 0);
Vtx[3].pos = FVECTOR2(0, 1);
Vtx[4].pos = FVECTOR2(1, 0);
Vtx[5].pos = FVECTOR2(1, 1);

HPOLY hStrip = pCore->CreateTriangles(NULL, Vtx, 6, PF_STRIP);

Vtx[0].color = 0xFF00FF00;    // Green
Vtx[1].color = 0xFF00FF00;      // Green
Vtx[2].color = 0xFFFF00FF;    // Mangenta
Vtx[3].color = 0xFFFF00FF;      // Mangenta
Vtx[4].color = 0xFF0000FF;    // Blue
Vtx[5].color = 0xFF0000FF;      // Blue

Vtx[0].pos = FVECTOR2(-1, 1);
Vtx[1].pos = FVECTOR2(-1, 0);
Vtx[2].pos = FVECTOR2(0, 1);
Vtx[3].pos = FVECTOR2(0, 0);
Vtx[4].pos = FVECTOR2(1, 1);
Vtx[5].pos = FVECTOR2(1, 0);

HPOLY hStrip2 = pCore->CreateTriangles(NULL, Vtx, 6, PF_STRIP);

IVECTOR2 pos0 = { 128, 128 };
IVECTOR2 pos1 = { 128, 384 };
IVECTOR2 pos2 = { 384, 128 };
IVECTOR2 pos3 = { 640, 128 };
IVECTOR2 pos4 = { 384, 384 };

pSkp->ColorFill(FVECTOR4((DWORD)0xFFFFFFFF), NULL);

pSkp->QuickBrush(0xA0000088);
pSkp->QuickPen(0xA0000000, 3.0f);
pSkp->PushWorldTransform();

pSkp->SetWorldScaleTransform2D(&FVECTOR2(100.0f, 100.0f), &pos0);
pSkp->DrawPoly(hColors);
pSkp->DrawPoly(hOutline);

pSkp->SetWorldScaleTransform2D(&FVECTOR2(100.0f, 100.0f), &pos1);
pSkp->DrawPoly(hOutline2);

pSkp->SetWorldScaleTransform2D(&FVECTOR2(100.0f, 100.0f), &pos2);
pSkp->DrawPoly(hStrip);

pSkp->SetWorldScaleTransform2D(&FVECTOR2(100.0f, 100.0f), &pos3);
pSkp->DrawPoly(hStrip2);

pSkp->SetWorldScaleTransform2D(&FVECTOR2(100.0f, 100.0f), &pos4);
pSkp->QuickPen(0xFF000000, 25.0f);
pSkp->DrawPoly(hOutline);

pSkp->PopWorldTransform();

pCore->DeletePoly(hOutline);
pCore->DeletePoly(hOutline2);
pCore->DeletePoly(hStrip);
pCore->DeletePoly(hStrip2);

clbkSaveSurfaceToImage(hTgt, "SketchpadOutput2", ImageFileFormat::IMAGE_PNG);

#### Attachments

18.4 KB · Views: 7

#### Abloheet

I did follow Abloheet's advice....I just notice that the default 2016 cloud is named "Venus_cloud.tex", so I easily replaced it with the one built for 2010.

I just liked that texture way back when my version of Orbiter is 2010

The default 2016 Venus_cloud.tex should be same as the Orbiter 2010 Venus_cloud.tex, as fas as I remember.. The stock Orbiter 2010 Venus_cloud.tex could be lower resolution, level 6 .tex, and the addon link you posted is one of best Venus textures for Orbiter 2010. I guess 4th rock replicated the surface textures from this mod's source into the Venus 2016 tile format, included terrain, but messed up the cloud conversion from stock Orbiter 2016 .tex level 6 clouds.

So, now you have best of both worlds. Best surface and terrain for 2016 from 4th rock's addon, and best clouds from the level 8 .tex

#### GLS

Depends on what you mean by finished. I guess it's never really finished but it should be reasonably stable now.
Well, then I have to try it out.

BTW, anyway that font width control is added?

#### jarmonik

Beta Tester
There is a new build 4.10 out for Orbiter 2016
• n-gon limit increased to 1024
• CreateSketchpadFont(int height, char *face, int width, int weight, int style, float spacing) function added.
• Allows to define font width, charter spacing and style
• See "gcFont::" namespace for style combinations, gcFont::CRISP and gcFont::ANTIALIAS allows to override application settings and define anti-aliasing behavior in per font basis.
• Do not use "*" hack in a font "face" name.