Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ set(SOURCES
FileVersion.cpp
FindCmd.cpp
GeneralDataEnry.cpp
gp2ccline.cpp
gp2exe.cpp
gp2geom.cpp
GPPitDraw.cpp
GPTrack.cpp
GPTrackDraw.cpp
Expand Down
174 changes: 174 additions & 0 deletions GPTrack.cpp
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include "TrackSection.h"
#include "TrackObjectDefinition.h"
#include "CCLineSection.h"
#include "gp2cc.h" // shared compiled-track data structs (gp2cc_track / gp2cc_ccgeo)
#include "gp2geom.hpp" // semantic C++ track-geometry compiler + the gv() cosine helper
#include "gp2ccline.hpp" // C++ cc-line (racing-line) solver on the formula tables
#include "TrackCmd.h"
#include "InternalObject.h"
#include "JamFileEditor.h"
Expand Down Expand Up @@ -144,6 +147,8 @@ void GPTrack::Create()
PROFILE(showPitLane, TRUE)
PROFILE(showObjects, FALSE)
PROFILE(showCCLine, TRUE)
PROFILE(showComputed, FALSE)
PROFILE(showComputedCCLine, FALSE)

PROFILE(showHiddenAsGray, TRUE)
PROFILE(showTrackPie, FALSE)
Expand Down Expand Up @@ -412,6 +417,8 @@ GPTrack::~GPTrack()
WR_PROFILE(showPitLane)
WR_PROFILE(showObjects)
WR_PROFILE(showCCLine)
WR_PROFILE(showComputed)
WR_PROFILE(showComputedCCLine)

WR_PROFILE(showHiddenAsGray)
WR_PROFILE(showTrackPie)
Expand Down Expand Up @@ -4030,6 +4037,173 @@ void GPTrack::drawCCLine(Display *g)
}
}

// ---------------------------------------------------------------------------
// Compiled overlays (bit-exact, gp2geom) drawn ON TOP of the normal view.
// buildCompiledOverlay() rebuilds the .dat from the live track (RecreateData),
// runs the gp2geom geometry compiler (and the cc-line only if that overlay is
// on), and projects every segment into the editor's frame. The two draw
// functions then render the compiled road (edges + section dividers, BLUE)
// and the compiled racing line (line + sector ticks, ORANGE; selected sector
// bright YELLOW), each toggled independently.
//
// Coordinate map: gp2geom positions are 1/8-world-units (X8/Y8); GP2 steps 128
// world-units (=1024 X8) per segment while the editor uses 1 unit/segment, so
// scale = 1/128, anchored at track section 0's start, same heading orientation.
// Each point = centre + perpendicular(heading) * (offset / 8 world units).
// ---------------------------------------------------------------------------
namespace {
struct CompiledOverlay {
bool valid;
bool hasCC;
int n;
gp2cc_track gt; // compiled geometry
short bl[GP2CC_MAXSEG], a18[GP2CC_MAXSEG]; // cc-line bestLine / angle18
int cmdSeg[GP2CC_MAXSEG], numCmds; // first segment of each cc-command
double lex[GP2CC_MAXSEG], ley[GP2CC_MAXSEG]; // left edge (editor coords)
double rex[GP2CC_MAXSEG], rey[GP2CC_MAXSEG]; // right edge
double ccx[GP2CC_MAXSEG], ccy[GP2CC_MAXSEG]; // racing line
};
static CompiledOverlay ov; // shared between buildCompiledOverlay + the draw fns
}

bool GPTrack::buildCompiledOverlay()
{
ov.valid = false; ov.hasCC = false;
if (TrackSections == NULL || TrackSections->size() == 0) return false;

RecreateData(); // live track -> trackdata[]
if (gp2geom::compileGeometry(trackdata, 65535, ov.gt) != 0) return false;
int n = ov.gt.n;
if (n <= 1) return false;
ov.n = n;

// editor frame: scale 1/128, anchored at section 0's start.
TrackSection *s0 = (TrackSection *)TrackSections->elementAt(0);
double ox = s0->getStartX(), oy = s0->getStartY();
double bwx = ov.gt.X8[0] / 8.0, bwy = ov.gt.Y8[0] / 8.0;
const double ES = 1.0 / 128.0;

for (int i = 0; i < n; i++) {
double cosh = gp2geom::gv(ov.gt.angle[i]) / 16384.0;
double sinh = gp2geom::gv(0x4000 - ov.gt.angle[i]) / 16384.0;
double pvx = -sinh, pvy = cosh; // unit perpendicular (worldX, worldY)
double px = ov.gt.X8[i] / 8.0, py = ov.gt.Y8[i] / 8.0;
double wl = ov.gt.widthL[i] / 8.0, wr = ov.gt.widthR[i] / 8.0;
// edge sign matches the normal view's getLeftSide (a-90 => -pv) / getRightSide
// (a+90 => +pv); otherwise widthL/widthR render on the mirror-opposite side.
ov.lex[i] = ox + (px - pvx * wl - bwx) * ES; ov.ley[i] = oy + (py - pvy * wl - bwy) * ES;
ov.rex[i] = ox + (px + pvx * wr - bwx) * ES; ov.rey[i] = oy + (py + pvy * wr - bwy) * ES;
}

if (showComputedCCLine) {
static gp2cc_ccgeo cg;
cg.n = n;
for (int i = 0; i < n; i++) {
cg.segAngle[i] = ov.gt.angle[i];
cg.cx8[i] = ov.gt.Y8[i];
cg.cy8[i] = ov.gt.X8[i];
cg.f14[i] = ov.gt.f14[i];
}
ov.numCmds = 0;
gp2geom::computeCcLine(cg, trackdata, 65535, ov.gt.ccoff, ov.bl, ov.a18, ov.cmdSeg, &ov.numCmds);
for (int i = 0; i < n; i++) {
double cosh = gp2geom::gv(ov.gt.angle[i]) / 16384.0;
double sinh = gp2geom::gv(0x4000 - ov.gt.angle[i]) / 16384.0;
double pvx = -sinh, pvy = cosh;
double px = ov.gt.X8[i] / 8.0, py = ov.gt.Y8[i] / 8.0;
double cc = ov.bl[i] / 8.0;
ov.ccx[i] = ox + (px + pvx * cc - bwx) * ES; ov.ccy[i] = oy + (py + pvy * cc - bwy) * ES;
}
ov.hasCC = true;
}

ov.valid = true;
return true;
}

// Compiled-track overlay: bit-exact road edges + a perpendicular divider at each
// TrackSection boundary, in BLUE. Numbers / start-finish stay with the normal view.
void GPTrack::drawCompiledTrack(Display *g)
{
if (!ov.valid) return;
int n = ov.n;

CPen *trackPen = new CPen(PS_SOLID, 1, RGB(0, 96, 255)); // blue
g->SelectObject(trackPen);

for (int i = 0; i < n; i++) { // road edges
int j = (i + 1) % n;
g->drawLine(ov.lex[i], ov.ley[i], ov.lex[j], ov.ley[j]);
g->drawLine(ov.rex[i], ov.rey[i], ov.rex[j], ov.rey[j]);
}

// section dividers: cumulative getLength() gives each section's first segment
// (skip index==-99 sections that emit no geometry command, as WriteTrack does).
int nsec = TrackSections->size();
int seg = 0;
for (int k = 0; k < nsec; k++) {
TrackSection *t = (TrackSection *)TrackSections->elementAt(k);
if (t->index == -99) continue;
int s = seg;
seg += (int)t->getLength();
if (s < 0 || s >= n) continue;
g->drawLine(ov.lex[s], ov.ley[s], ov.rex[s], ov.rey[s]);
}

g->setColor(0); // deselect before delete
delete trackPen;
}

// Compiled-cc-line overlay: bit-exact racing line + a perpendicular tick at each
// cc-sector start, in ORANGE; the SELECTED sector over-drawn in bright YELLOW.
// CCLineSection[c] starts at cmdSeg[c+1] -- cmdSeg[0] is the seed/start command
// (the editor's CCLineStart header), not a user-editable sector.
void GPTrack::drawCompiledCcLine(Display *g)
{
if (!ov.valid || !ov.hasCC) return;
int n = ov.n;

CPen *linePen = new CPen(PS_SOLID, 1, RGB(255, 140, 0)); // orange
g->SelectObject(linePen);
for (int i = 0; i < n; i++) {
int j = (i + 1) % n;
g->drawLine(ov.ccx[i], ov.ccy[i], ov.ccx[j], ov.ccy[j]);
}
g->setColor(0);
delete linePen;

int nSec = (CCLineSections != NULL) ? CCLineSections->size() : 0;
CPen *tickPen = new CPen(PS_SOLID, 1, RGB(255, 140, 0)); // orange tick
CPen *selPen = new CPen(PS_SOLID, 2, RGB(255, 255, 0)); // bright yellow (selected)
for (int c = 0; c < nSec; c++) {
int ci = c + 1; // +1: skip the seed command
if (ci >= ov.numCmds) break;
int s = ov.cmdSeg[ci];
if (s < 0 || s >= n) continue;
CCLineSection *sec = (CCLineSection *)CCLineSections->elementAt(c);
BOOL sel = (sec != NULL) && sec->isSelected();

if (sel) { // highlight the selected sector
int len = (int)sec->getLength();
g->SelectObject(selPen);
for (int k = 0; k < len; k++) {
int i = (s + k) % n, j = (i + 1) % n;
g->drawLine(ov.ccx[i], ov.ccy[i], ov.ccx[j], ov.ccy[j]);
}
}

double cosh = gp2geom::gv(ov.gt.angle[s]) / 16384.0; // tick perpendicular
double sinh = gp2geom::gv(0x4000 - ov.gt.angle[s]) / 16384.0;
double tlen = 3.0;
double tx = -sinh * tlen, ty = cosh * tlen;
g->SelectObject(sel ? selPen : tickPen);
g->drawLine(ov.ccx[s] - tx, ov.ccy[s] - ty, ov.ccx[s] + tx, ov.ccy[s] + ty);
}
g->setColor(0); // deselect before delete
delete tickPen;
delete selPen;
}

void GPTrack::drawPitlane(Display *g)
{
if (TrackSections == NULL || TrackSections->size() == 0) return;
Expand Down
9 changes: 9 additions & 0 deletions GPTrack.h
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ class GPTrack : public CWnd
drawPitlane(Display *g);
void
drawCCLine(Display *g);
// Compiled overlays (bit-exact, gp2geom). buildCompiledOverlay() recompiles the
// track once per repaint and fills the shared overlay arrays; the two draw
// functions render the track (edges + dividers) and the cc-line (racing line +
// sector marks) on top of the normal view. Returns false if compile failed.
bool buildCompiledOverlay();
void drawCompiledTrack(Display *g);
void drawCompiledCcLine(Display *g);
void
drawCameras(Display *g);
void
Expand Down Expand Up @@ -243,6 +250,8 @@ class GPTrack : public CWnd
BOOL showPitLane;
BOOL showObjects;
BOOL showCCLine;
BOOL showComputed; // compiled-track overlay (bit-exact road edges + dividers)
BOOL showComputedCCLine; // compiled-cc-line overlay (bit-exact racing line + sector marks)
BOOL showHiddenAsGray;
BOOL showTrackPie;
BOOL showCameras;
Expand Down
7 changes: 7 additions & 0 deletions TrackEditor.rc
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ BEGIN
BUTTON ID_AIRVIEW
BUTTON ID_DRAWAXIS
BUTTON ID_VIEWCAMERAS
SEPARATOR
BUTTON ID_VIEW_COMPILED
BUTTON ID_VIEW_COMPILED_CCLINE
END

IDR_OBJECT TOOLBAR 16, 15
Expand Down Expand Up @@ -472,6 +475,8 @@ BEGIN
MENUITEM "Show Track", VIEW_TRACK
MENUITEM "Show Pitlane", VIEW_PITLANE
MENUITEM "Show CC Line", VIEW_CCLINE
MENUITEM "Compiled Track Overlay", ID_VIEW_COMPILED
MENUITEM "Compiled CC-Line Overlay", ID_VIEW_COMPILED_CCLINE
MENUITEM "Show Objects", VIEW_OBJECTS
MENUITEM "Show Fences", VIEW_WALLS
MENUITEM "Show Pit Fences", ID_SHOW_SHOWPITFENCES
Expand Down Expand Up @@ -1746,6 +1751,8 @@ BEGIN
VIEW_PITLANE "Show Pitlane data\nShow Pit lane"
VIEW_TRACK "Show track data\nShow Track"
VIEW_CCLINE "Show Driving Line\nDriving Line"
ID_VIEW_COMPILED "Toggle compiled track overlay\nCompiled Track Overlay"
ID_VIEW_COMPILED_CCLINE "Toggle compiled CC-line overlay\nCompiled CC-Line Overlay"
VIEW_OBJECTS "Show trackside objects\nShow Objects"
END

Expand Down
18 changes: 18 additions & 0 deletions TrackEditor.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,19 @@
<ClCompile Include="gp2exe.cpp" />
<ClCompile Include="GPPitDraw.cpp" />
<ClCompile Include="GPTrack.cpp" />
<ClCompile Include="gp2geom.cpp">
<LanguageStandard>stdcpp17</LanguageStandard>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<!-- the cosine table is generated at compile time; raise MSVC's constexpr
step budget so the 4098-entry build fits. -->
<AdditionalOptions>/constexpr:steps4000000 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<ClCompile Include="gp2ccline.cpp">
<LanguageStandard>stdcpp17</LanguageStandard>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<!-- includes both formula tables (cos+atan); same constexpr budget. -->
<AdditionalOptions>/constexpr:steps4000000 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<ClCompile Include="GPTrackDraw.cpp" />
<ClCompile Include="HyperLinkButton.cpp" />
<ClCompile Include="Info.cpp" />
Expand Down Expand Up @@ -279,6 +292,11 @@
<ClInclude Include="FindCmd.h" />
<ClInclude Include="GeneralDataEnry.h" />
<ClInclude Include="GPTrack.h" />
<ClInclude Include="gp2cc.h" />
<ClInclude Include="gp2geom.hpp" />
<ClInclude Include="gp2cos.hpp" />
<ClInclude Include="gp2ccline.hpp" />
<ClInclude Include="gp2atan.hpp" />
<ClInclude Include="htmlhelp.h" />
<ClInclude Include="ImportDataElement.h" />
<ClInclude Include="Info.h" />
Expand Down
38 changes: 38 additions & 0 deletions TrackEditorScrollView.cpp
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ ON_COMMAND(ID_TRACK_TOOL, OnTrackTool)
ON_COMMAND(ID_ZOOMTOOL, OnZoomtool)
ON_UPDATE_COMMAND_UI(VIEW_CCLINE, OnUpdateCcline)
ON_COMMAND(VIEW_CCLINE, OnCcline)
ON_UPDATE_COMMAND_UI(ID_VIEW_COMPILED, OnUpdateViewCompiled)
ON_COMMAND(ID_VIEW_COMPILED, OnViewCompiled)
ON_UPDATE_COMMAND_UI(ID_VIEW_COMPILED_CCLINE, OnUpdateViewCompiledCCLine)
ON_COMMAND(ID_VIEW_COMPILED_CCLINE, OnViewCompiledCCLine)
ON_UPDATE_COMMAND_UI(ID_VIEW_OBJ_BITMAPS, OnUpdateViewObjBitmaps)
ON_UPDATE_COMMAND_UI(ID_ZOOMTOOL, OnUpdateZoomtool)
ON_UPDATE_COMMAND_UI(ID_POINTER, OnUpdatePointer)
Expand Down Expand Up @@ -464,6 +468,14 @@ void TrackEditorScrollView::OnMyDraw(CDC* pDC)
track->drawCameras(display);
track->drawBlackFlags(display);
track->DrawCCDataLog(display);
// bit-exact compiled overlays drawn ON TOP of the normal view, each
// toggled independently. Compile once, both overlays share the result.
if (track->showComputed || track->showComputedCCLine) {
if (track->buildCompiledOverlay()) {
if (track->showComputed) track->drawCompiledTrack(display);
if (track->showComputedCCLine) track->drawCompiledCcLine(display);
}
}
}

TrackSection* t = track->getTrackSelection();
Expand Down Expand Up @@ -1026,6 +1038,32 @@ void TrackEditorScrollView::OnCcline()
OnDrivingLine();
}

void TrackEditorScrollView::OnUpdateViewCompiled(CCmdUI* pCmdUI)
{
UPDATE_TRACK(showComputed);
}

void TrackEditorScrollView::OnViewCompiled()
{
CTrackEditorDoc* pDoc = GetDocument();
GPTrack* mytrack = pDoc->getTrack();
mytrack->showComputed = !mytrack->showComputed;
repaint();
}

void TrackEditorScrollView::OnUpdateViewCompiledCCLine(CCmdUI* pCmdUI)
{
UPDATE_TRACK(showComputedCCLine);
}

void TrackEditorScrollView::OnViewCompiledCCLine()
{
CTrackEditorDoc* pDoc = GetDocument();
GPTrack* mytrack = pDoc->getTrack();
mytrack->showComputedCCLine = !mytrack->showComputedCCLine;
repaint();
}

void TrackEditorScrollView::OnUpdateViewObjBitmaps(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
Expand Down
8 changes: 8 additions & 0 deletions TrackEditorScrollView.h
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ class TrackEditorScrollView : public CScrollView
OnUpdateCcline(CCmdUI* pCmdUI);
afx_msg void
OnCcline();
afx_msg void
OnUpdateViewCompiled(CCmdUI* pCmdUI);
afx_msg void
OnViewCompiled();
afx_msg void
OnUpdateViewCompiledCCLine(CCmdUI* pCmdUI);
afx_msg void
OnViewCompiledCCLine();
afx_msg void
OnUpdateViewObjBitmaps(CCmdUI* pCmdUI);
afx_msg void
Expand Down
Loading