Skip to content

Commit

Permalink
#283: Included flags for force vector display options to Graphics API…
Browse files Browse the repository at this point in the history
…. Extended GetConfigParam to return force vector display parameters. Implemented force vector display in D3D7Client. Still to do: text labels.
  • Loading branch information
mschweiger committed Oct 28, 2022
1 parent 0e51a10 commit 786f182
Show file tree
Hide file tree
Showing 8 changed files with 307 additions and 11 deletions.
8 changes: 8 additions & 0 deletions OVP/D3D7Client/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,14 @@ void Scene::Render ()
if (ptex) dev->SetTexture (0, 0);
if (!alpha) dev->SetRenderState (D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);

// render object vectors
if (*(DWORD*)gc->GetConfigParam(CFGPRM_FORCEVECTORFLAG) & BF_ENABLE) {
cam->SetFrustumLimits(1.0, 1e30);
for (pv = vobjFirst; pv; pv = pv->next)
pv->vobj->RenderVectors(dev);
cam->SetFrustumLimits(npl, fpl);
}

// render the internal parts of the focus object in a separate render pass
if (oapiCameraInternal() && vFocus) {
// switch cockpit lights on, external-only lights off
Expand Down
174 changes: 174 additions & 0 deletions OVP/D3D7Client/VObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "Camera.h"
#include "Texture.h"
#include "D3D7Util.h"
#include <algorithm>

using namespace oapi;

Expand Down Expand Up @@ -87,6 +88,11 @@ void vObject::Activate (bool isactive)
active = isactive;
}

bool veccomp(const vObject::BodyVectorRec& v1, const vObject::BodyVectorRec& v2)
{
return v1.dist < v2.dist; // sort from furthest to nearest
}

bool vObject::Update ()
{
if (!active) return false;
Expand All @@ -109,6 +115,9 @@ bool vObject::Update ()
// update the object's world matrix

CheckResolution();
UpdateRenderVectors();
std::sort(veclist.begin(), veclist.end(), veccomp);

return true;
}

Expand Down Expand Up @@ -165,3 +174,168 @@ void vObject::RenderSpot (LPDIRECT3DDEVICE7 dev, const VECTOR3 *ofs, float size,
dev->SetTextureStageState (0, D3DTSS_COLOROP, D3DTOP_MODULATE);
dev->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
}

void vObject::AddVector(const VECTOR3& v, const VECTOR3& orig, double rad, const std::string& label, const VECTOR3& col, float alpha, DWORD lcol, float lsize)
{
double len = length(v);
if (len < 2.0 * rad) return; // too short to be rendered

VECTOR3 cam = -cpos;
VECTOR3 vu = v / len;
double dist = length(vu - cam);

BodyVectorRec rec;
rec.v = v;
rec.orig = orig;
rec.rad = rad;
rec.dist = dist;
rec.col = col;
rec.alpha = alpha;
rec.label = label;
rec.lcol = lcol;
rec.lsize = lsize;

veclist.push_back(rec);
}

void vObject::RenderVectors(LPDIRECT3DDEVICE7 dev)
{
if (veclist.size()) {
float alpha, palpha = -1.0f;
dev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
dev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
dev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT);
dev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_POINT);
for (auto it = veclist.begin(); it != veclist.end(); it++) {
alpha = (*it).alpha;
if (alpha != palpha)
dev->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, D3DRGBA(1, 1, 1, alpha));
if (DrawVector(dev, (*it).v, (*it).orig, (*it).rad, (*it).col, alpha) && (*it).label.size()) {
double scale3 = ((*it).lsize >= 0 ? (*it).lsize : size);
//scene->Render3DLabel(mul(body->GRot(), ve->v + ve->v.unit() * (scale3 * 0.1)) + body->GPos(),
// ve->label, scale3, ve->lcol);
}
}
dev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
dev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
dev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
}
}

bool vObject::DrawVector(LPDIRECT3DDEVICE7 dev, const VECTOR3& end, const VECTOR3& orig, double rad, const VECTOR3& col, float opac)
{
static const float EPS = 1e-2f;
static const int nseg = 8;
static const int nVtx = nseg * 5;
static const int nIdx0 = nseg * 6 + nseg * 3;
static const int nIdx1 = nIdx0 + (nseg - 2) * 3;
static D3DMATERIAL7 pmtrl, mtrl = {
{0,0,0,1},
{0,0,0,1},
{0.5,0.5,0.5,1},
{0,0,0,1},
10.0
};
int i, nIdx;
WORD* Idx;
static D3DVERTEX* Vtx0 = 0, * Vtx = 0;
static WORD* Idx0 = 0, * Idx1 = 0;
if (!Vtx0) { // create vector mesh template (pointing to +y)
int i0, i1;
Vtx0 = new D3DVERTEX[nVtx];
Vtx = new D3DVERTEX[nVtx];
Idx0 = new WORD[nIdx0];
Idx1 = new WORD[nIdx1];
for (i = 0; i < nseg; i++) {
Vtx0[i + 2 * nseg].x = Vtx0[i + 3 * nseg].x = 2.0f * (Vtx0[i].x = Vtx0[i + nseg].x = Vtx0[i].nx = Vtx0[i + nseg].nx = (float)cos(PI2 * (double)i / (double)nseg));
Vtx0[i + 2 * nseg].z = Vtx0[i + 3 * nseg].z = 2.0f * (Vtx0[i].z = Vtx0[i + nseg].z = Vtx0[i].nz = Vtx0[i + nseg].nz = (float)sin(PI2 * (double)i / (double)nseg));
Vtx0[i + 4 * nseg].x = Vtx0[i + 4 * nseg].z = 0.0f;
Vtx0[i].y = 0.0f; Vtx0[i + nseg].y = Vtx0[i + 2 * nseg].y = Vtx0[i + 3 * nseg].y = Vtx0[i + 4 * nseg].y = 1.0f;
Vtx0[i + 3 * nseg].nx = Vtx0[i + 4 * nseg].nx = (float)(0.894 * cos(PI2 * (double)(i + 0.5) / (double)nseg));
Vtx0[i + 3 * nseg].nz = Vtx0[i + 4 * nseg].nz = (float)(0.894 * sin(PI2 * (double)(i + 0.5) / (double)nseg));
Vtx0[i + 3 * nseg].ny = Vtx0[i + 4 * nseg].ny = 0.447f;
Vtx0[i].ny = Vtx0[i + nseg].ny = Vtx0[i + 2 * nseg].nx = Vtx0[i + 2 * nseg].nz = 0.0f;
Vtx0[i + 2 * nseg].ny = -1.0f;
}
for (i = i0 = 0, i1 = 6 * (nseg - 1); i < nseg; i++) { // stem
Idx0[i0++] = Idx1[i1++] = (WORD)i;
Idx0[i0++] = Idx1[i1++] = (WORD)(i + nseg);
Idx0[i0++] = Idx1[i1++] = (WORD)((i + 1) % nseg + nseg);
Idx0[i0++] = Idx1[i1++] = (WORD)i;
Idx0[i0++] = Idx1[i1++] = (WORD)((i + 1) % nseg + nseg);
Idx0[i0++] = Idx1[i1++] = (WORD)((i + 1) % nseg);
}
for (i = 0, i1 = nseg * 3; i < nseg - 2; i++) { // tip base
Idx1[i1++] = nseg * 2;
Idx1[i1++] = nseg * 2 + 1 + i;
Idx1[i1++] = nseg * 2 + 2 + i;
}
for (i = i1 = 0, i0 = nseg * 6; i < nseg; i++) { // tip
Idx0[i0++] = Idx1[i1++] = nseg * 3 + i;
Idx0[i0++] = Idx1[i1++] = nseg * 4 + i;
Idx0[i0++] = Idx1[i1++] = 3 * nseg + (i + 1) % nseg;
}
}

float w = (float)rad;
float h = (float)length(end);
if (h < EPS) return false;
float hb = max(h - 4.0f * w, 0);
DWORD bZbuf;

memcpy(Vtx, Vtx0, nVtx * sizeof(D3DVERTEX));

for (i = 0; i < nseg; i++) {
Vtx[i + 3 * nseg].y = Vtx[i + 2 * nseg].y = Vtx[i + nseg].y = hb;
Vtx[i + 4 * nseg].y = h;
Vtx[i].x = Vtx[i + nseg].x *= w, Vtx[i].z = Vtx[i + nseg].z *= w;
Vtx[i + 3 * nseg].x = Vtx[i + 2 * nseg].x *= w, Vtx[i + 3 * nseg].z = Vtx[i + 2 * nseg].z *= w;
}

// rotate vector
VECTOR3 d = end / h;
double tht = acos(d.y), phi = atan2(d.z, d.x);
float cost = (float)cos(tht), sint = (float)sin(tht);
float cosp = (float)cos(phi), sinp = (float)sin(phi);
D3DMATRIX W, R = { cost * cosp, -sint, cost * sinp, 0,
sint * cosp, cost, sint * sinp, 0,
-sinp, 0 , cosp, 0,
0, 0, 0, 1 };

// shift vector
R._41 = (float)orig.x;
R._42 = (float)orig.y;
R._43 = (float)orig.z;
D3DMAT_MatrixMultiply(&W, &mWorld, &R);
dev->SetTransform(D3DTRANSFORMSTATE_WORLD, &W);

MATRIX3 grot;
VECTOR3 gpos;
oapiGetRotationMatrix(hObj, &grot);
VECTOR3 cp = tmul(grot, -cpos);
if (dotp(d, unit(end - cp)) > 0)
Idx = Idx1, nIdx = nIdx1;
else
Idx = Idx0, nIdx = nIdx0;

mtrl.emissive.r = 0.5f * (mtrl.diffuse.r = (float)col.x);
mtrl.emissive.g = 0.5f * (mtrl.diffuse.g = (float)col.y);
mtrl.emissive.b = 0.5f * (mtrl.diffuse.b = (float)col.z);
if (opac < 1.0f)
mtrl.emissive.a = mtrl.diffuse.a = mtrl.ambient.a = mtrl.specular.a = opac;
dev->GetMaterial(&pmtrl);
dev->SetMaterial(&mtrl);
dev->SetTexture(0, 0);
dev->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, TRUE);
dev->GetRenderState(D3DRENDERSTATE_ZENABLE, &bZbuf);
if (bZbuf) dev->SetRenderState(D3DRENDERSTATE_ZENABLE, FALSE);
dev->DrawIndexedPrimitive(
D3DPT_TRIANGLELIST, D3DFVF_VERTEX, Vtx, nVtx, Idx, nIdx, 0);
dev->SetMaterial(&pmtrl);
dev->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, FALSE);
dev->SetTransform(D3DTRANSFORMSTATE_WORLD, &mWorld);
if (bZbuf) dev->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE);
if (opac < 1.0f)
mtrl.emissive.a = mtrl.diffuse.a = mtrl.ambient.a = mtrl.specular.a = 1.0f;
return true;
}
29 changes: 29 additions & 0 deletions OVP/D3D7Client/VObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ class vObject: public oapi::VisObject {
*/
virtual bool Update ();

/**
* \brief Set up any vectors (forces, coordinate axes) to be drawn in the
* next render pass.
*/
virtual void UpdateRenderVectors() {}

/**
* \brief Level-of-detail check
* \default None.
Expand Down Expand Up @@ -167,9 +173,31 @@ class vObject: public oapi::VisObject {
*/
virtual void RenderBeacons (LPDIRECT3DDEVICE7 dev) {}

/**
* \brief structure for rendering vectors
*/
struct BodyVectorRec {
VECTOR3 v; ///< vector definition in local object frame
VECTOR3 orig; ///< vector origin in local object frame
double rad; ///< vector arrow radius
double dist; ///< camera distance
VECTOR3 col; ///< colour components
float alpha; ///< alpha component
std::string label; ///< vector label
DWORD lcol;
float lsize; ///< length scale
};

void RenderVectors(LPDIRECT3DDEVICE7 dev);

protected:
void RenderSpot (LPDIRECT3DDEVICE7 dev, const VECTOR3 *ofs, float size, const VECTOR3 &col, bool lighting, int shape);

void AddVector(const VECTOR3& v, const VECTOR3& orig, double rad, const std::string& label, const VECTOR3& col, float alpha = 1.0f, DWORD lcol = 0, float lsize = -1.0);

bool DrawVector(LPDIRECT3DDEVICE7 dev, const VECTOR3& end, const VECTOR3& orig, double rad,
const VECTOR3& col, float opac);

static const oapi::D3D7Client *gc; // graphics client instance pointer
static LPDIRECTDRAWSURFACE7 blobtex[3]; // beacon textures

Expand All @@ -181,6 +209,7 @@ class vObject: public oapi::VisObject {
double size; // object radius [m]
double cdist; // current camera distance
VECTOR3 cpos; // camera-relative object position
std::vector<BodyVectorRec> veclist; ///< list of body vectors to be rendered
};

#endif // !__VOBJECT_H
50 changes: 50 additions & 0 deletions OVP/D3D7Client/VVessel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,56 @@ bool vVessel::Update ()
return true;
}

void vVessel::UpdateRenderVectors()
{
veclist.clear();

DWORD flag = *(DWORD*)gc->GetConfigParam(CFGPRM_FORCEVECTORFLAG);
if (flag & BF_ENABLE) {
VESSEL* vessel = oapiGetVesselInterface(hObj);
static double shift = 1e3, lshift = log(shift);
bool logscale = ((flag & BF_LOGSCALE) != 0);
double len, scale, scale2 = size * 0.02;
scale = (logscale ? 1.0 : size / (vessel->GetMass() * 9.81));
double m = vessel->GetMass(); // DEBUG
double pscale = *(float*)gc->GetConfigParam(CFGPRM_FORCEVECTORSCALE);
float alpha = *(float*)gc->GetConfigParam(CFGPRM_FORCEVECTOROPACITY);
char cbuf[256];
VECTOR3 F;

if ((flag & BF_WEIGHT) && vessel->GetWeightVector(F)) {
sprintf(cbuf, "G = %fN", len = length(F));
if (logscale) len = log(len + shift) - lshift; else len *= scale;
AddVector(unit(F) * (len * pscale), _V(0, 0, 0), scale2, std::string(cbuf), _V(1, 1, 0), alpha, D3DRGB(1, 1, 0));
}
if ((flag & BF_THRUST) && vessel->GetThrustVector(F)) {
sprintf(cbuf, "T = %fN", len = length(F));
if (logscale) len = log(len + shift) - lshift; else len *= scale;
AddVector(unit(F) * (len * pscale), _V(0, 0, 0), scale2, std::string(cbuf), _V(0, 0, 1), alpha, D3DRGB(0.5, 0.5, 1));
}
if ((flag & BF_LIFT) && vessel->GetLiftVector(F)) {
sprintf(cbuf, "L = %fN", len = length(F));
if (logscale) len = log(len + shift) - lshift; else len *= scale;
AddVector(unit(F) * (len * pscale), _V(0, 0, 0), scale2, std::string(cbuf), _V(0, 1, 0), alpha, D3DRGB(0.5, 1, 0.5));
}
if ((flag & BF_DRAG) && vessel->GetDragVector(F)) {
sprintf(cbuf, "D = %fN", len = length(F));
if (logscale) len = log(len + shift) - lshift; else len *= scale;
AddVector(unit(F) * (len * pscale), _V(0, 0, 0), scale2, std::string(cbuf), _V(1, 0, 0), alpha, D3DRGB(1, 0.5, 0.5));
}
if ((flag & BF_TOTAL) && vessel->GetForceVector(F)) {
sprintf(cbuf, "F = %fN", len = length(F));
if (logscale) len = log(len + shift) - lshift; else len *= scale;
AddVector(unit(F) * (len * pscale), _V(0, 0, 0), scale2, std::string(cbuf), _V(1, 1, 1), alpha, D3DRGB(1, 1, 1));
}
if ((flag & BF_TORQUE) && vessel->GetTorqueVector(F)) {
sprintf(cbuf, "M = %fNm", len = length(F));
if (logscale) len = log(len + 1e-5) - log(1e-5); else len *= scale * 1e5;
AddVector(unit(F) * (len * pscale), _V(0, 0, 0), scale2, std::string(cbuf), _V(1, 0, 1), alpha, D3DRGB(1, 0, 1));
}
}
}

void vVessel::LoadMeshes ()
{
if (nmesh) ClearMeshes();
Expand Down
5 changes: 5 additions & 0 deletions OVP/D3D7Client/VVessel.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ class vVessel: public vObject {
*/
bool Update ();

/**
* \brief Set up the vessel vectors (forces, frame axes) to render
*/
void UpdateRenderVectors();

/**
* \brief Object render call
* \param dev render device
Expand Down
36 changes: 35 additions & 1 deletion Orbitersdk/include/GraphicsAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,35 @@ typedef void *HDC;
*/
#define CFGPRM_TILEPATCHRES 0x001B

#define CFGPRM_TILELOADFLAGS 0x001C
/**
* Bitflags for planetary tile file load behaviour
* - bit 1: load from individual tiles in directory tree
* - bit 2: load from compressed archive file
* \par Parameter type:
* DWORD
*/
#define CFGPRM_TILELOADFLAGS 0x001C

/**
* Bit flags for force vector display options.
* \par Parameter type:
* DWORD
*/
#define CFGPRM_FORCEVECTORFLAG 0x001D

/**
* Force vector display scaling factor
* \par Parameter type:
* float
*/
#define CFGPRM_FORCEVECTORSCALE 0x001E

/**
* Force vector display opacity value
* \par Parameter type:
* float
*/
#define CFGPRM_FORCEVECTOROPACITY 0x001F
/// @}

/**
Expand Down Expand Up @@ -222,6 +244,18 @@ typedef void *HDC;
#define PLN_SURFMARK (PLN_BMARK | PLN_RMARK | PLN_LMARK)
/// @}

/// \defgroup bfflag Bit flags for vessel force vector render options
/// @{
#define BF_ENABLE 0x0001 ///< Enable force vectors
#define BF_LOGSCALE 0x0002 ///< Use logarithmic scale (instead of linear scale)
#define BF_WEIGHT 0x0004 ///< Show weight vector
#define BF_THRUST 0x0008 ///< Show thrust vector
#define BF_LIFT 0x0010 ///< Show lift vector
#define BF_DRAG 0x0020 ///< Show drag vector
#define BF_TOTAL 0x0040 ///< Show total force vector
#define BF_TORQUE 0x0080 ///< Show torque vector
/// @}

/// \defgroup bltflag Bit flags for blitting operations
/// @{
#define BLT_SRCCOLORKEY 0x1 ///< Use source surface colour key for transparency
Expand Down
Loading

0 comments on commit 786f182

Please sign in to comment.