speed-dreams/src/tools/trackgen/track.cpp

3301 lines
151 KiB
C++

/***************************************************************************
file : track.cpp
created : Sun Dec 24 12:14:18 CET 2000
copyright : (C) 2000 by Eric Espie
email : eric.espie@torcs.org
version : $Id$
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/** @file
@author <a href=mailto:eric.espie@torcs.org>Eric Espie</a>
@version $Id$
*/
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#ifndef WIN32
#include <unistd.h>
#endif
#include <cmath>
#include <robottools.h>
#include <tgfclient.h>
#include <track.h>
#include "ac3d.h"
#include "util.h"
#include "trackgen.h"
struct tTexElt
{
char *name;
char *namebump;
char *nameraceline;
int mipmap; // Not yet used.
unsigned int texid;
tTexElt *next;
};
struct tDispElt
{
int start;
int nb;
Ac3d::Surface::SURF surfType;
char *name;
int id;
tTexElt *texture;
tDispElt *next;
};
struct tGroup
{
int nb;
tDispElt *dispList;
};
static tGroup *Groups;
static int ActiveGroups;
static int GroupNb;
#define LMAX TrackStep
static float *trackvertices;
static float *tracktexcoord;
static unsigned int *trackindices;
static tdble TrackStep = DEFAULT_TRACK_STEP;
#ifndef sqr
#define sqr(x) ((x) * (x))
#endif
static void initPits(tTrack *theTrack, void *TrackHandle, tTrackPitInfo *pits)
{
tTrackSeg *curMainSeg;
tTrackSeg *curPitSeg = nullptr;
tTrackSeg *pitBuildingsStart = nullptr;
const char *segName;
tTrkLocPos curPos;
int i;
bool found = false;
bool changeSeg = false;
tdble offset = 0;
tdble toStart = 0;
static char path2[256];
sprintf(path2, "%s/%s", TRK_SECT_MAIN, TRK_SECT_PITS);
// In TR_PIT_NO_BUILDING, the pit positions are located exactly the same,
// as in the TR_PIT_ON_TRACK_SIDE. It differs only later, showing/not showing
// the buildings.
switch (pits->type)
{
case TR_PIT_ON_TRACK_SIDE:
case TR_PIT_NO_BUILDING:
pits->driversPitsNb = MIN(pits->nPitSeg, pits->nMaxPits);
pits->driversPits = (tTrackOwnPit *)calloc(pits->driversPitsNb, sizeof(tTrackOwnPit));
curPos.type = TR_TOMIDDLE;
// TR_LPOS_MAIN; //NB: TR_LPOS_MAIN not handled by RtTrackLocal2Global!
segName = GfParmGetStr(TrackHandle, path2, TRK_ATT_BUILDINGS_START, nullptr);
if (segName != 0)
{
pitBuildingsStart = theTrack->seg;
found = false;
for (i = 0; i <= theTrack->nseg; i++)
{
if (!strcmp(segName, pitBuildingsStart->name))
{
found = true;
}
else if (found)
{
pitBuildingsStart = pitBuildingsStart->next;
break;
}
pitBuildingsStart = pitBuildingsStart->prev;
}
if (!found)
{
pitBuildingsStart = nullptr;
}
}
if (pitBuildingsStart == nullptr)
{
if (pits->pitStart == nullptr)
{
GfLogError("Can't find pit start\n");
exit(1);
}
pitBuildingsStart = pits->pitStart;
}
curMainSeg = pitBuildingsStart->prev;
changeSeg = true;
offset = 0;
toStart = 0;
i = 0;
while (i < pits->driversPitsNb)
{
if (changeSeg)
{
changeSeg = false;
offset = 0;
curMainSeg = curMainSeg->next;
switch (pits->side)
{
case TR_RGT:
curPitSeg = curMainSeg->rside;
if (curPitSeg->rside)
{
offset = curPitSeg->width;
curPitSeg = curPitSeg->rside;
}
break;
case TR_LFT:
curPitSeg = curMainSeg->lside;
if (curPitSeg->lside)
{
offset = curPitSeg->width;
curPitSeg = curPitSeg->lside;
}
break;
}
curPos.seg = curMainSeg;
if (toStart >= curMainSeg->length)
{
toStart -= curMainSeg->length;
changeSeg = true;
continue;
}
} // if changeSeg
/* Not the real position but the start and border one
* instead of center */
// RtTrackLocal2Global expects toStart as a length in meters for straight,
// and as an angle in radian for curves
// TODO(kilo)
// Proper handling of this should enable non-linear pitlanes.
// Postponed after 2.0
#if 0
tdble pitCenter = toStart + pits->len / 2.0;
switch(curMainSeg->type) {
case TR_STR:
pits->driversPits[i].pos.toStart = pitCenter;
break;
case TR_LFT:
case TR_RGT:
pits->driversPits[i].pos.toStart = pitCenter / curMainSeg->radius;
break;
}
#endif
// TODO(kilo) get rid of following line when above feature is ready
curPos.toStart = toStart;
switch (pits->side)
{
case TR_RGT:
curPos.toRight = -offset - RtTrackGetWidth(curPitSeg, toStart);
curPos.toLeft = curMainSeg->width - curPos.toRight;
curPos.toMiddle = -curMainSeg->width / 2.0 + curPos.toRight;
break;
case TR_LFT:
curPos.toLeft = -offset - RtTrackGetWidth(curPitSeg, toStart);
curPos.toRight = curMainSeg->width - curPos.toLeft;
curPos.toMiddle = curMainSeg->width / 2.0 - curPos.toLeft;
break;
}
memcpy(&(pits->driversPits[i].pos), &curPos, sizeof(curPos));
toStart += pits->len;
if (toStart >= curMainSeg->length)
{
toStart -= curMainSeg->length;
changeSeg = true;
}
i++;
} // while i
break;
case TR_PIT_ON_SEPARATE_PATH:
break;
case TR_PIT_NONE:
break;
}
}
/** Bug fix:
If width of border decreased, additional vertices are needed to avoid missing surfaces
Implementation:
Compares old end vertices and new start vertices, set startNeeded if one is different
**/
int InitScene(tTrack *Track, void *TrackHandle, bool bump, bool raceline, bool bridge)
{
int i;
tTrackSeg *seg;
tTrackSeg *lastSeg = nullptr;
tTrackSeg *mseg;
int nbvert;
tdble width;
tdble anz, ts = 0;
tdble radiusr, radiusl;
tdble step;
tTrkLocPos trkpos;
tdble x, y, z;
tdble x2, y2, z2;
tdble x3, y3, z3;
bool startNeeded;
tdble xprev = 0;
tdble yprev = 0;
tDispElt *aDispElt = nullptr;
unsigned int prevTexId;
unsigned int curTexId = 0;
int curTexType = 0;
int curTexLink = 0;
tdble curTexOffset = 0;
tdble curTexSeg;
tdble curTexSize = 0;
tdble curHeight;
Ac3d::Surface::SURF prevSurfType = Ac3d::Surface::PolygonSingleSidedSmooth;
Ac3d::Surface::SURF curSurfType = Ac3d::Surface::PolygonSingleSidedSmooth; // shaded single sided polygon
tTexElt *texList = nullptr;
tTexElt *curTexElt = nullptr;
tTrackBarrier *curBarrier;
tdble texLen;
tdble texStep;
tdble texMaxT = 0;
tTrackPitInfo *pits;
static int GenTexId = 1;
tdble runninglentgh;
tdble tmWidth = Track->graphic.turnMarksInfo.width;
tdble tmHeight = Track->graphic.turnMarksInfo.height;
tdble tmVSpace = Track->graphic.turnMarksInfo.vSpace;
tdble tmHSpace = Track->graphic.turnMarksInfo.hSpace;
char buf[256];
bool hasBorder;
tDispElt *theCurDispElt = nullptr;
char sname[256];
// float dmax = 0;
#define LG_STEP_MAX 50.0
printf("++++++++++++ Track ++++++++++++\n");
printf("name = %s\n", Track->name);
printf("authors = %s\n", Track->authors);
printf("filename = %s\n", Track->filename);
printf("nseg = %d\n", Track->nseg);
printf("version = %d\n", Track->version);
printf("length = %f\n", Track->length);
printf("width = %f\n", Track->width);
printf("pits segs = %d\n", Track->pits.nPitSeg);
printf("pits = %d\n", Track->pits.nMaxPits);
printf("XSize = %f\n", Track->max.x);
printf("YSize = %f\n", Track->max.y);
printf("ZSize = %f\n", Track->max.z);
tdble delatx = Track->seg->next->vertex[TR_SL].x - Track->seg->vertex[TR_EL].x;
tdble delaty = Track->seg->next->vertex[TR_SL].y - Track->seg->vertex[TR_EL].y;
tdble delatz = Track->seg->next->vertex[TR_SL].z - Track->seg->vertex[TR_EL].z;
tdble delata = Track->seg->next->angle[TR_ZS] - Track->seg->angle[TR_ZE];
NORM_PI_PI(delata);
printf("Delta X = %f\n", delatx);
printf("Delta Y = %f\n", delaty);
printf("Delta Z = %f\n", delatz);
printf("Delta Ang = %f (%f)\n", delata, RAD2DEG(delata));
/* if ((fabs(delatx) > 1.0) || (fabs(delaty) > 1.0) || (fabs(delatz) > 1.0)) { */
/* exit(0); */
/* } */
Groups = (tGroup *)calloc(Track->nseg, sizeof(tGroup));
ActiveGroups = 0;
GroupNb = Track->nseg;
width = Track->width;
// wi2 = width / 2.0; // Never used.
double rlWidthScale = 1.0;
double rlOffset = 0.0;
if (raceline)
{
double SideDistExt = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, TRK_ATT_RLEXT, nullptr, 2.0);
double SideDistInt = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, TRK_ATT_RLINT, nullptr, 2.0);
rlWidthScale = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, TRK_ATT_RLWIDTHSCALE, nullptr, 1.0);
rlOffset = (1.0 - 1.0 / rlWidthScale) / 2.0;
generateRaceLine(Track, SideDistExt, SideDistInt);
}
trkpos.type = TR_LPOS_MAIN;
#define SETTEXTURE(texname, texnamebump, texnameraceline, _mipmap) \
do \
{ \
int found = 0; \
curTexElt = texList; \
if (curTexElt == nullptr) \
{ \
curTexElt = (tTexElt *)calloc(1, sizeof(tTexElt)); \
curTexElt->next = curTexElt; \
texList = curTexElt; \
curTexElt->name = strdup(texname); \
curTexElt->namebump = strdup(texnamebump); \
curTexElt->nameraceline = strdup(texnameraceline); \
curTexElt->mipmap = _mipmap; \
curTexElt->texid = GenTexId++; \
} \
else \
{ \
do \
{ \
curTexElt = curTexElt->next; \
if (strcmp(texname, curTexElt->name) == 0) \
{ \
found = 1; \
break; \
} \
} while (curTexElt != texList); \
if (!found) \
{ \
curTexElt = (tTexElt *)calloc(1, sizeof(tTexElt)); \
curTexElt->next = texList->next; \
texList->next = curTexElt; \
texList = curTexElt; \
curTexElt->name = strdup(texname); \
curTexElt->namebump = strdup(texnamebump); \
curTexElt->nameraceline = strdup(texnameraceline); \
curTexElt->mipmap = _mipmap; \
curTexElt->texid = GenTexId++; \
} \
} \
curTexId = curTexElt->texid; \
} while (0)
#define NBELTLIST 1
#define NEWDISPLIST(texchange, _name, _id) \
do \
{ \
if (!bump || (*(curTexElt->namebump) != 0)) \
{ \
if (theCurDispElt != nullptr) \
{ \
startNeeded = texchange; \
if (theCurDispElt->start != nbvert) \
{ \
theCurDispElt->nb = nbvert - theCurDispElt->start; \
theCurDispElt = aDispElt = (tDispElt *)malloc(sizeof(tDispElt)); \
aDispElt->start = nbvert; \
aDispElt->nb = 0; \
aDispElt->name = strdup(_name); \
aDispElt->id = _id; \
aDispElt->texture = curTexElt; \
aDispElt->surfType = curSurfType; \
if (Groups[_id].nb == 0) \
{ \
ActiveGroups++; \
aDispElt->next = aDispElt; \
Groups[_id].dispList = aDispElt; \
} \
else \
{ \
aDispElt->next = Groups[_id].dispList->next; \
Groups[_id].dispList->next = aDispElt; \
Groups[_id].dispList = aDispElt; \
} \
Groups[_id].nb++; \
} \
else \
{ \
aDispElt->texture = curTexElt; \
aDispElt->surfType = curSurfType; \
} \
} \
else \
{ \
theCurDispElt = aDispElt = (tDispElt *)malloc(sizeof(tDispElt)); \
aDispElt->start = nbvert; \
aDispElt->nb = 0; \
aDispElt->name = strdup(_name); \
aDispElt->id = _id; \
aDispElt->texture = curTexElt; \
aDispElt->surfType = curSurfType; \
aDispElt->next = aDispElt; \
Groups[_id].dispList = aDispElt; \
Groups[_id].nb++; \
ActiveGroups++; \
} \
/* fprintf(stderr, "%s %d (%s)\n", _name, _id, curTexElt->name); */ \
} \
} while (0)
#define CHECKDISPLIST(mat, name, id, off) \
do \
{ \
const char *texname; \
const char *texnamebump; \
const char *texnameraceline; \
int mipmap; \
static char path_[256]; \
if (Track->version < 4) \
{ \
sprintf(path_, "%s/%s/%s", TRK_SECT_SURFACES, TRK_LST_SURF, mat); \
} \
else \
{ \
sprintf(path_, "%s/%s", TRK_SECT_SURFACES, mat); \
} \
texnamebump = GfParmGetStr(TrackHandle, path_, TRK_ATT_BUMPNAME, ""); \
texnameraceline = GfParmGetStr(TrackHandle, path_, TRK_ATT_RACELINENAME, "raceline.png"); \
texname = GfParmGetStr(TrackHandle, path_, TRK_ATT_TEXTURE, "tr-asphalt.png"); \
mipmap = (int)GfParmGetNum(TrackHandle, path_, TRK_ATT_TEXMIPMAP, nullptr, 0); \
SETTEXTURE(texname, texnamebump, texnameraceline, mipmap); \
if ((curTexId != prevTexId) || (curSurfType != prevSurfType) || startNeeded) \
{ \
const char *textype; \
if (bump) \
{ \
curTexType = 1; \
curTexLink = 1; \
curTexOffset = -off; \
curTexSize = GfParmGetNum(TrackHandle, path_, TRK_ATT_BUMPSIZE, nullptr, 20.0); \
} \
else \
{ \
textype = GfParmGetStr(TrackHandle, path_, TRK_ATT_TEXTYPE, "continuous"); \
if (strcmp(textype, "continuous") == 0) \
curTexType = 1; \
else \
curTexType = 0; \
textype = GfParmGetStr(TrackHandle, path_, TRK_ATT_TEXLINK, TRK_VAL_YES); \
if (strcmp(textype, TRK_VAL_YES) == 0) \
curTexLink = 1; \
else \
curTexLink = 0; \
textype = GfParmGetStr(TrackHandle, path_, TRK_ATT_TEXSTARTBOUNDARY, TRK_VAL_NO); \
if (strcmp(textype, TRK_VAL_YES) == 0) \
curTexOffset = -off; \
else \
curTexOffset = 0; \
curTexSize = GfParmGetNum(TrackHandle, path_, TRK_ATT_TEXSIZE, nullptr, 20.0); \
} \
prevTexId = curTexId; \
prevSurfType = curSurfType; \
NEWDISPLIST(true, name, id); \
} \
} while (0)
#define CHECKDISPLIST2(texture, mipmap, name, id) \
do \
{ \
char texname[300]; \
sprintf(texname, "%s.png", texture); \
SETTEXTURE(texname, "", "", mipmap); \
if (curTexId != prevTexId) \
{ \
prevTexId = curTexId; \
NEWDISPLIST(true, name, id); \
} \
} while (0)
#define CHECKDISPLIST3(texture, mipmap, name, id) \
do \
{ \
SETTEXTURE(texture, "", "", mipmap); \
if (curTexId != prevTexId) \
{ \
prevTexId = curTexId; \
NEWDISPLIST(true, name, id); \
} \
} while (0)
#define CLOSEDISPLIST() \
do \
{ \
theCurDispElt->nb = nbvert - theCurDispElt->start; \
} while (0)
#define SETPOINT(t1, t2, x, y, z) \
do \
{ \
if (*(curTexElt->name) != 0) \
{ \
tracktexcoord[2 * nbvert] = t1; \
tracktexcoord[2 * nbvert + 1] = t2; \
trackvertices[3 * nbvert] = x; \
trackvertices[3 * nbvert + 1] = y; \
trackvertices[3 * nbvert + 2] = z; \
trackindices[nbvert] = nbvert; \
++nbvert; \
} \
} while (0)
#define SETPOINT2(t1, t2, x, y, z) \
do \
{ \
if (*(curTexElt->name) != 0) \
{ \
tracktexcoord[2 * nbvert] = t1; \
tracktexcoord[2 * nbvert + 1] = t2; \
trackvertices[3 * nbvert] = x; \
trackvertices[3 * nbvert + 1] = y; \
trackvertices[3 * nbvert + 2] = z; \
trackindices[nbvert] = nbvert; \
++nbvert; \
printf("x=%f y=%f z=%f u=%f v=%f\n", (tdble)(x), (tdble)(y), (tdble)(z), (tdble)(t1), (tdble)(t2)); \
} \
} while (0)
/* Count the number of vertice to allocate */
nbvert = 0;
for (i = 0, seg = Track->seg->next; i < Track->nseg; i++, seg = seg->next)
{
nbvert++;
switch (seg->type)
{
case TR_STR:
nbvert += (int)(seg->length / LMAX);
break;
case TR_LFT:
nbvert += (int)(seg->arc * (seg->radiusr) / LMAX);
break;
case TR_RGT:
nbvert += (int)(seg->arc * (seg->radiusl) / LMAX);
break;
}
}
nbvert++;
nbvert *= 30;
nbvert += 58; /* start bridge */
nbvert += 12 + 10 * Track->pits.driversPitsNb;
// TODO: Investigate if this is a feasible solution, nbvert was perviously += 1000.
nbvert += 10000; /* safety margin */
printf("=== Indices Array Size = %d\n", nbvert);
printf("=== Vertex Array Size = %d\n", nbvert * 3);
printf("=== Tex Coord Array Size = %d\n", nbvert * 2);
trackindices = (unsigned int *)malloc(sizeof(unsigned int) * nbvert);
trackvertices = (float *)malloc(sizeof(GLfloat) * (nbvert * 3));
tracktexcoord = (float *)malloc(sizeof(GLfloat) * (nbvert * 2));
nbvert = 0;
/* Main track */
prevTexId = 0;
texLen = 0;
startNeeded = true;
runninglentgh = 0;
for (i = 0, seg = Track->seg->next; i < Track->nseg; i++, seg = seg->next)
{
CHECKDISPLIST(seg->surface->material, "tkMn", i, seg->lgfromstart);
if (!curTexLink)
{
curTexSeg = 0;
}
else
{
curTexSeg = seg->lgfromstart;
}
curTexSeg += curTexOffset;
if (raceline)
{
// Required if some smaller than width tiled texture is used.
curTexSize = seg->width;
}
texLen = curTexSeg / curTexSize;
if (startNeeded || (runninglentgh > LG_STEP_MAX))
{
NEWDISPLIST(false, "tkMn", i);
runninglentgh = 0;
ts = 0;
if (raceline)
{
// Required if some smaller than width tiled texture is used.
texMaxT = 1.0;
}
else
{
// Normal case
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
}
double rlto = getTexureOffset(seg->lgfromstart) / rlWidthScale;
SETPOINT(texLen, texMaxT - rlOffset + rlto, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen, 0.0 + rlOffset + rlto, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
}
switch (seg->type)
{
case TR_STR:
ts = LMAX;
texStep = LMAX / curTexSize;
trkpos.seg = seg;
while (ts < seg->length)
{
texLen += texStep;
trkpos.toStart = ts;
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
double rlto = getTexureOffset(seg->lgfromstart + ts) / rlWidthScale;
SETPOINT(texLen, texMaxT - rlOffset + rlto, x, y, RtTrackHeightL(&trkpos));
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.0 + rlOffset + rlto, x, y, RtTrackHeightL(&trkpos));
ts += LMAX;
}
ts = seg->length;
break;
case TR_LFT:
step = LMAX / (seg->radiusr);
texStep = step * seg->radius / curTexSize;
anz = seg->angle[TR_ZS] + step;
ts = step;
radiusr = seg->radiusr;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz < seg->angle[TR_ZE])
{
texLen += texStep;
trkpos.toStart = ts;
double rlto = getTexureOffset(seg->lgfromstart + ts * seg->radius) / rlWidthScale;
/* left */
trkpos.toRight = width;
SETPOINT(texLen, texMaxT - rlOffset + rlto, seg->center.x + radiusl * sin(anz), seg->center.y - radiusl * cos(anz), RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
SETPOINT(texLen, 0.0 + rlOffset + rlto, seg->center.x + radiusr * sin(anz), seg->center.y - radiusr * cos(anz), RtTrackHeightL(&trkpos));
ts += step;
anz += step;
}
ts = seg->arc;
break;
case TR_RGT:
step = LMAX / (seg->radiusl);
texStep = step * seg->radius / curTexSize;
anz = seg->angle[TR_ZS] - step;
ts = step;
radiusr = seg->radiusr;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz > seg->angle[TR_ZE])
{
texLen += texStep;
trkpos.toStart = ts;
double rlto = getTexureOffset(seg->lgfromstart + ts * seg->radius) / rlWidthScale;
/* left */
trkpos.toRight = width;
SETPOINT(texLen, texMaxT - rlOffset + rlto, seg->center.x - radiusl * sin(anz), seg->center.y + radiusl * cos(anz), RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
SETPOINT(texLen, 0 + rlOffset + rlto, seg->center.x - radiusr * sin(anz), seg->center.y + radiusr * cos(anz), RtTrackHeightL(&trkpos));
ts += step;
anz -= step;
}
ts = seg->arc;
break;
}
texLen = (curTexSeg + seg->length) / curTexSize;
double rlto = getTexureOffset(seg->lgfromstart + seg->length) / rlWidthScale;
SETPOINT(texLen, texMaxT - rlOffset + rlto, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen, 0 + rlOffset + rlto, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
startNeeded = false;
runninglentgh += seg->length;
}
if (raceline)
{
CLOSEDISPLIST();
printf("=== Indices really used = %d\n", nbvert);
return 0;
}
/* Right Border */
lastSeg = nullptr;
for (int j = 0; j < 3; j++)
{
prevTexId = 0;
texLen = 0;
startNeeded = true;
runninglentgh = 0;
sprintf(sname, "t%dRB", j);
for (i = 0, mseg = Track->seg->next; i < Track->nseg; i++, mseg = mseg->next)
{
if ((mseg->rside != nullptr) && (mseg->rside->type2 == TR_RBORDER))
{
seg = mseg->rside;
if ((lastSeg && lastSeg->style != seg->style) || mseg->prev->rside->width != seg->width || mseg->prev->rside->height != seg->height)
startNeeded = true;
CHECKDISPLIST(seg->surface->material, sname, i, mseg->lgfromstart);
if (!curTexLink)
{
curTexSeg = 0;
}
else
{
curTexSeg = mseg->lgfromstart;
}
curTexSeg += curTexOffset;
texLen = curTexSeg / curTexSize;
if (startNeeded || (runninglentgh > LG_STEP_MAX))
{
NEWDISPLIST(false, sname, i);
runninglentgh = 0;
ts = 0;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
switch (seg->style)
{
case TR_PLAN:
if (j == 0)
{
SETPOINT(texLen, 0, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen, texMaxT, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
}
break;
case TR_CURB:
switch (j)
{
case 0:
if (!mseg->prev->rside || (mseg->prev->rside->type2 != TR_RBORDER) || (mseg->prev->rside->style != TR_CURB) ||
(mseg->prev->rside->style == TR_CURB && (mseg->prev->rside->width != seg->width || mseg->prev->rside->height != seg->height)))
{
SETPOINT(texLen, 0, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z - 0.1);
SETPOINT(texLen, texMaxT, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
}
SETPOINT(texLen, 0, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen, texMaxT, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + seg->height);
break;
case 1:
SETPOINT(texLen, texMaxT, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + seg->height);
SETPOINT(texLen, texMaxT, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
break;
case 2:
break;
}
break;
case TR_WALL:
switch (j)
{
case 0:
SETPOINT(texLen, 0, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen, .33, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + seg->height);
break;
case 1:
SETPOINT(texLen, 0.33, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + seg->height);
SETPOINT(texLen, 0.66, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + seg->height);
break;
case 2:
if (!mseg->prev->rside || (mseg->prev->rside->type2 != TR_RBORDER) || (mseg->prev->rside->style != TR_WALL) ||
(mseg->prev->rside->style == TR_WALL && (mseg->prev->rside->height < seg->height || mseg->prev->rside->width < seg->width)))
{
SETPOINT(texLen - seg->width / curTexSize, 0.66, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + seg->height);
SETPOINT(texLen - seg->width / curTexSize, 1.00, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
}
SETPOINT(texLen, 0.66, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + seg->height);
SETPOINT(texLen, 1.0, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
break;
}
break;
case TR_FENCE:
case TR_PITBUILDING:
case TR_NO_BARRIER:
// not supported
break;
}
}
switch (seg->type)
{
case TR_STR:
ts = LMAX;
texStep = LMAX / curTexSize;
texLen += texStep;
trkpos.seg = seg;
while (ts < seg->length)
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
switch (seg->style)
{
case TR_PLAN:
if (j == 0)
{
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
}
break;
case TR_CURB:
switch (j)
{
case 0:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
break;
case 2:
break;
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 2:
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
SETPOINT(texLen, 1.0, x, y, RtTrackHeightL(&trkpos));
break;
}
break;
case TR_FENCE:
case TR_PITBUILDING:
case TR_NO_BARRIER:
// not supported
break;
}
ts += LMAX;
texLen += texStep;
}
ts = seg->length;
break;
case TR_LFT:
step = LMAX / (mseg->radiusr);
texStep = step * mseg->radius / curTexSize;
anz = seg->angle[TR_ZS] + step;
ts = step;
texLen += texStep;
radiusr = seg->radiusr;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz < seg->angle[TR_ZE])
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
switch (seg->style)
{
case TR_PLAN:
if (j == 0)
{
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
}
break;
case TR_CURB:
switch (j)
{
case 0:
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
break;
case 2:
break;
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 2:
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
SETPOINT(texLen, 1.0, x, y, RtTrackHeightL(&trkpos));
break;
}
break;
case TR_FENCE:
case TR_PITBUILDING:
case TR_NO_BARRIER:
// not supported
break;
}
ts += step;
texLen += texStep;
anz += step;
}
ts = seg->arc;
break;
case TR_RGT:
step = LMAX / (mseg->radiusl);
texStep = step * mseg->radius / curTexSize;
anz = seg->angle[TR_ZS] - step;
ts = step;
texLen += texStep;
radiusr = seg->radiusr;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz > seg->angle[TR_ZE])
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
switch (seg->style)
{
case TR_PLAN:
if (j == 0)
{
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
}
break;
case TR_CURB:
switch (j)
{
case 0:
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
break;
case 2:
break;
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 2:
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
SETPOINT(texLen, 1.0, x, y, RtTrackHeightL(&trkpos));
break;
}
break;
case TR_FENCE:
case TR_PITBUILDING:
case TR_NO_BARRIER:
// not supported
break;
}
ts += step;
texLen += texStep;
anz -= step;
}
ts = seg->arc;
break;
}
texLen = (curTexSeg + mseg->length) / curTexSize;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
switch (seg->style)
{
case TR_PLAN:
if (j == 0)
{
SETPOINT(texLen, 0, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen, texMaxT, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
}
break;
case TR_CURB:
switch (j)
{
case 0:
SETPOINT(texLen, 0, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen, texMaxT, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + seg->height);
if (mseg->next->rside && ((mseg->next->rside->type2 != TR_RBORDER) || (mseg->next->rside->style != TR_CURB) ||
(mseg->next->rside->style == TR_CURB && (mseg->next->rside->width != seg->width || mseg->next->rside->height != seg->height))))
{
SETPOINT(texLen, 0, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z - 0.1);
SETPOINT(texLen, texMaxT, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
}
break;
case 1:
SETPOINT(texLen, texMaxT, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + seg->height);
SETPOINT(texLen, texMaxT, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
break;
case 2:
break;
}
break;
case TR_WALL:
switch (j)
{
case 0:
SETPOINT(texLen, 0, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen, 0.33, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + seg->height);
break;
case 1:
SETPOINT(texLen, 0.33, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + seg->height);
SETPOINT(texLen, 0.66, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + seg->height);
break;
case 2:
SETPOINT(texLen, 0.66, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + seg->height);
SETPOINT(texLen, 1.0, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
if (mseg->next->rside && ((mseg->next->rside->type2 != TR_RBORDER) || (mseg->next->rside->style != TR_WALL) ||
(mseg->next->rside->style == TR_WALL && (mseg->next->rside->height < seg->height || mseg->next->rside->width < seg->width))))
{
SETPOINT(texLen + seg->width / curTexSize, 0.66, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + seg->height);
SETPOINT(texLen + seg->width / curTexSize, 1.00, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
}
break;
}
break;
case TR_FENCE:
case TR_PITBUILDING:
case TR_NO_BARRIER:
// not supported
break;
}
startNeeded = false;
runninglentgh += seg->length;
lastSeg = seg;
}
else
{
startNeeded = true;
lastSeg = nullptr;
}
}
}
/* Right Side */
prevTexId = 0;
texLen = 0;
startNeeded = true;
runninglentgh = 0;
hasBorder = false;
lastSeg = nullptr;
for (i = 0, mseg = Track->seg->next; i < Track->nseg; i++, mseg = mseg->next)
{
if ((mseg->rside != nullptr) && ((mseg->rside->type2 == TR_RSIDE) || (mseg->rside->rside != nullptr)))
{
seg = mseg->rside;
if (seg->rside != nullptr)
{
seg = seg->rside;
if (!hasBorder)
{
startNeeded = true;
hasBorder = true;
}
}
else
{
if (hasBorder)
{
startNeeded = true;
hasBorder = false;
}
}
if (!startNeeded)
{
tdble d0 = Distance(lastSeg->vertex[TR_EL].x, lastSeg->vertex[TR_EL].y, lastSeg->vertex[TR_EL].z, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
tdble d1 = Distance(lastSeg->vertex[TR_ER].x, lastSeg->vertex[TR_ER].y, lastSeg->vertex[TR_ER].z, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
if ((d0 > 0.01) || (d1 > 0.01))
startNeeded = true;
}
CHECKDISPLIST(seg->surface->material, "tkRS", i, mseg->lgfromstart);
if (!curTexLink)
{
curTexSeg = 0;
}
else
{
curTexSeg = mseg->lgfromstart;
}
curTexSeg += curTexOffset;
texLen = curTexSeg / curTexSize;
if (startNeeded || (runninglentgh > LG_STEP_MAX))
{
NEWDISPLIST(false, "tkRS", i);
runninglentgh = 0;
ts = 0;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
SETPOINT(texLen, 0, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen, texMaxT, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
}
switch (seg->type)
{
case TR_STR:
ts = LMAX;
texStep = LMAX / curTexSize;
texLen += texStep;
trkpos.seg = seg;
while (ts < seg->length)
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
ts += LMAX;
texLen += texStep;
}
ts = seg->length;
break;
case TR_LFT:
step = LMAX / (mseg->radiusr);
texStep = step * mseg->radius / curTexSize;
anz = seg->angle[TR_ZS] + step;
ts = step;
texLen += texStep;
radiusr = seg->radiusr;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz < seg->angle[TR_ZE])
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
ts += step;
texLen += texStep;
anz += step;
}
ts = seg->arc;
break;
case TR_RGT:
step = LMAX / (mseg->radiusl);
texStep = step * mseg->radius / curTexSize;
anz = seg->angle[TR_ZS] - step;
ts = step;
texLen += texStep;
radiusr = seg->radiusr;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz > seg->angle[TR_ZE])
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
ts += step;
texLen += texStep;
anz -= step;
}
ts = seg->arc;
break;
}
texLen = (curTexSeg + mseg->length) / curTexSize;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
SETPOINT(texLen, 0, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen, texMaxT, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
startNeeded = false;
runninglentgh += seg->length;
lastSeg = seg;
}
else
{
startNeeded = true;
}
}
/* Left Border */
lastSeg = nullptr;
for (int j = 0; j < 3; j++)
{
prevTexId = 0;
texLen = 0;
startNeeded = true;
runninglentgh = 0;
sprintf(sname, "t%dLB", j);
for (i = 0, mseg = Track->seg->next; i < Track->nseg; i++, mseg = mseg->next)
{
if ((mseg->lside != nullptr) && (mseg->lside->type2 == TR_LBORDER))
{
seg = mseg->lside;
if ((lastSeg && lastSeg->style != seg->style) || mseg->prev->lside->width != seg->width || mseg->prev->lside->height != seg->height)
startNeeded = true;
CHECKDISPLIST(seg->surface->material, sname, i, mseg->lgfromstart);
if (!curTexLink)
{
curTexSeg = 0;
}
else
{
curTexSeg = mseg->lgfromstart;
}
curTexSeg += curTexOffset;
texLen = curTexSeg / curTexSize;
if (startNeeded || (runninglentgh > LG_STEP_MAX))
{
NEWDISPLIST(false, sname, i);
runninglentgh = 0;
ts = 0;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
switch (seg->style)
{
case TR_PLAN:
if (j == 0)
{
SETPOINT(texLen, texMaxT, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen, 0, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
}
break;
case TR_CURB:
switch (j)
{
case 0:
SETPOINT(texLen, texMaxT, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen, texMaxT, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + seg->height);
break;
case 1:
if (!mseg->prev->lside || (mseg->prev->lside->type2 != TR_LBORDER) || (mseg->prev->lside->style != TR_CURB) ||
(mseg->prev->lside->style == TR_CURB && (mseg->prev->lside->width != seg->width || mseg->prev->lside->height != seg->height)))
{
SETPOINT(texLen, texMaxT, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen, 0, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z - 0.1);
}
SETPOINT(texLen, texMaxT, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + seg->height);
SETPOINT(texLen, 0, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
break;
case 2:
break;
}
break;
case TR_WALL:
switch (j)
{
case 0:
if (!mseg->prev->lside || (mseg->prev->lside->type2 != TR_LBORDER) || (mseg->prev->lside->style != TR_WALL) ||
(mseg->prev->lside->style == TR_WALL && (mseg->prev->lside->height < seg->height || mseg->prev->lside->width < seg->width)))
{
SETPOINT(texLen - seg->width / curTexSize, 1.00, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
SETPOINT(texLen - seg->width / curTexSize, 0.66, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + seg->height);
}
SETPOINT(texLen, 1.0, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen, 0.66, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + seg->height);
break;
case 1:
SETPOINT(texLen, 0.66, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + seg->height);
SETPOINT(texLen, 0.33, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + seg->height);
break;
case 2:
SETPOINT(texLen, 0.33, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + seg->height);
SETPOINT(texLen, 0.0, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
break;
}
break;
case TR_FENCE:
case TR_PITBUILDING:
case TR_NO_BARRIER:
// not supported
break;
}
}
switch (seg->type)
{
case TR_STR:
ts = LMAX;
texStep = LMAX / curTexSize;
texLen += texStep;
trkpos.seg = seg;
while (ts < seg->length)
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
switch (seg->style)
{
case TR_PLAN:
if (j == 0)
{
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
}
break;
case TR_CURB:
switch (j)
{
case 0:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
break;
case 2:
break;
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 1.0, x, y, RtTrackHeightL(&trkpos));
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 2:
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
SETPOINT(texLen, 0.0, x, y, RtTrackHeightL(&trkpos));
break;
}
break;
case TR_FENCE:
case TR_PITBUILDING:
case TR_NO_BARRIER:
// not supported
break;
}
ts += LMAX;
texLen += texStep;
}
ts = seg->length;
break;
case TR_LFT:
step = LMAX / (mseg->radiusr);
texStep = step * mseg->radius / curTexSize;
anz = seg->angle[TR_ZS] + step;
ts = step;
texLen += texStep;
radiusr = seg->radiusr;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz < seg->angle[TR_ZE])
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
switch (seg->style)
{
case TR_PLAN:
if (j == 0)
{
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
}
break;
case TR_CURB:
switch (j)
{
case 0:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
break;
case 2:
break;
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 1.0, x, y, RtTrackHeightL(&trkpos));
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 2:
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
SETPOINT(texLen, 0.0, x, y, RtTrackHeightL(&trkpos));
break;
}
break;
case TR_FENCE:
case TR_PITBUILDING:
case TR_NO_BARRIER:
// not supported
break;
}
ts += step;
texLen += texStep;
anz += step;
}
ts = seg->arc;
break;
case TR_RGT:
step = LMAX / (mseg->radiusl);
texStep = step * mseg->radius / curTexSize;
anz = seg->angle[TR_ZS] - step;
ts = step;
texLen += texStep;
radiusr = seg->radiusr;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz > seg->angle[TR_ZE])
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
switch (seg->style)
{
case TR_PLAN:
if (j == 0)
{
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
}
break;
case TR_CURB:
switch (j)
{
case 0:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos) + seg->height);
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
break;
case 2:
break;
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 1.0, x, y, RtTrackHeightL(&trkpos));
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 1:
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, RtTrackHeightL(&trkpos) + seg->height);
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
break;
case 2:
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, RtTrackHeightL(&trkpos) + seg->height);
SETPOINT(texLen, 0.0, x, y, RtTrackHeightL(&trkpos));
break;
}
break;
case TR_FENCE:
case TR_PITBUILDING:
case TR_NO_BARRIER:
// not supported
break;
}
ts += step;
texLen += texStep;
anz -= step;
}
ts = seg->arc;
break;
}
texLen = (curTexSeg + mseg->length) / curTexSize;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
switch (seg->style)
{
case TR_PLAN:
if (j == 0)
{
SETPOINT(texLen, texMaxT, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen, 0, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
}
break;
case TR_CURB:
switch (j)
{
case 0:
SETPOINT(texLen, texMaxT, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen, texMaxT, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + seg->height);
break;
case 1:
SETPOINT(texLen, texMaxT, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + seg->height);
SETPOINT(texLen, 0, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
if (mseg->next->lside && ((mseg->next->lside->type2 != TR_LBORDER) || (mseg->next->lside->style != TR_CURB) ||
(mseg->next->lside->style == TR_CURB && (mseg->next->lside->height != seg->height || mseg->next->lside->width != seg->width))))
{
SETPOINT(texLen, texMaxT, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen, 0, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z - 0.1);
}
break;
case 2:
break;
}
break;
case TR_WALL:
switch (j)
{
case 0:
SETPOINT(texLen, 1.0, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen, 0.66, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + seg->height);
if (mseg->next->lside && ((mseg->next->lside->type2 != TR_LBORDER) || (mseg->next->lside->style != TR_WALL) ||
(mseg->next->lside->style == TR_WALL && (mseg->next->lside->height < seg->height || mseg->next->lside->width < seg->width))))
{
SETPOINT(texLen + seg->width / curTexSize, 1.00, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
SETPOINT(texLen + seg->width / curTexSize, 0.66, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + seg->height);
}
break;
case 1:
SETPOINT(texLen, 0.66, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + seg->height);
SETPOINT(texLen, 0.33, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + seg->height);
break;
case 2:
SETPOINT(texLen, 0.33, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + seg->height);
SETPOINT(texLen, 0.0, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
break;
}
break;
case TR_FENCE:
case TR_PITBUILDING:
case TR_NO_BARRIER:
// not supported
break;
}
startNeeded = false;
runninglentgh += seg->length;
lastSeg = seg;
}
else
{
startNeeded = true;
lastSeg = nullptr;
}
}
}
/* Left Side */
prevTexId = 0;
texLen = 0;
startNeeded = true;
runninglentgh = 0;
hasBorder = false;
lastSeg = nullptr;
for (i = 0, mseg = Track->seg->next; i < Track->nseg; i++, mseg = mseg->next)
{
if ((mseg->lside != nullptr) && ((mseg->lside->type2 == TR_LSIDE) || (mseg->lside->lside != nullptr)))
{
seg = mseg->lside;
if (seg->lside)
{
seg = seg->lside;
if (!hasBorder)
{
startNeeded = true;
hasBorder = true;
}
}
else
{
if (hasBorder)
{
startNeeded = true;
hasBorder = false;
}
}
if (!startNeeded)
{
tdble d0 = Distance(lastSeg->vertex[TR_EL].x, lastSeg->vertex[TR_EL].y, lastSeg->vertex[TR_EL].z, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
tdble d1 = Distance(lastSeg->vertex[TR_ER].x, lastSeg->vertex[TR_ER].y, lastSeg->vertex[TR_ER].z, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
if ((d0 > 0.01) || (d1 > 0.01))
startNeeded = true;
}
CHECKDISPLIST(seg->surface->material, "tkLS", i, mseg->lgfromstart);
if (!curTexLink)
{
curTexSeg = 0;
}
else
{
curTexSeg = mseg->lgfromstart;
}
curTexSeg += curTexOffset;
texLen = curTexSeg / curTexSize;
if (startNeeded || (runninglentgh > LG_STEP_MAX))
{
NEWDISPLIST(false, "tkLS", i);
runninglentgh = 0;
ts = 0;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
SETPOINT(texLen, texMaxT, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen, 0, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
}
switch (seg->type)
{
case TR_STR:
ts = LMAX;
texStep = LMAX / curTexSize;
texLen += texStep;
trkpos.seg = seg;
while (ts < seg->length)
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
ts += LMAX;
texLen += texStep;
}
ts = seg->length;
break;
case TR_LFT:
step = LMAX / (mseg->radiusr);
texStep = step * mseg->radius / curTexSize;
anz = seg->angle[TR_ZS] + step;
ts = step;
texLen += texStep;
radiusr = seg->radiusr;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz < seg->angle[TR_ZE])
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
ts += step;
texLen += texStep;
anz += step;
}
ts = seg->arc;
break;
case TR_RGT:
step = LMAX / (mseg->radiusl);
texStep = step * mseg->radius / curTexSize;
anz = seg->angle[TR_ZS] - step;
ts = step;
texLen += texStep;
radiusr = seg->radiusr;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz > seg->angle[TR_ZE])
{
trkpos.toStart = ts;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
/* left */
trkpos.toRight = width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, texMaxT, x, y, RtTrackHeightL(&trkpos));
/* right */
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0, x, y, RtTrackHeightL(&trkpos));
ts += step;
texLen += texStep;
anz -= step;
}
ts = seg->arc;
break;
}
texLen = (curTexSeg + mseg->length) / curTexSize;
width = RtTrackGetWidth(seg, ts);
texMaxT = (curTexType == 1 ? width / curTexSize : 1.0 + floor(width / curTexSize));
SETPOINT(texLen, texMaxT, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen, 0, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
startNeeded = false;
runninglentgh += seg->length;
lastSeg = seg;
}
else
{
startNeeded = true;
}
}
/* Right Barrier */
tTrackBarrier *lastBarrier = Track->seg->next->prev->barrier[0];
curSurfType = Ac3d::Surface::PolygonSingleSidedSmooth;
for (int j = 0; j < 3; j++)
{
prevTexId = 0;
texLen = 0;
startNeeded = true;
runninglentgh = 0;
sprintf(sname, "B%dRt", j);
for (i = 0, mseg = Track->seg->next; i < Track->nseg; i++, mseg = mseg->next)
{
// Find last side segment
seg = mseg;
while (seg->rside)
seg = seg->rside;
curBarrier = mseg->barrier[0];
if (seg->raceInfo & TR_PITBUILD || curBarrier->style == TR_NO_BARRIER)
{
startNeeded = true;
runninglentgh = 0;
lastBarrier = curBarrier;
xprev = 0;
yprev = 0;
continue;
}
bool startPolygonNeeded = false;
if (lastBarrier)
{
if (lastBarrier->style != curBarrier->style || lastBarrier->width != curBarrier->width || lastBarrier->height != curBarrier->height)
startNeeded = true;
else if (lastBarrier->style == curBarrier->style)
{
tTrackSeg *prevSide = mseg->prev;
while (prevSide->rside)
prevSide = prevSide->rside;
startPolygonNeeded = std::fabs(seg->vertex[TR_SR].x - prevSide->vertex[TR_ER].x) > 0.001 || std::fabs(seg->vertex[TR_SR].y - prevSide->vertex[TR_ER].y) > 0.001;
if (startPolygonNeeded)
startNeeded = true;
}
}
curSurfType = curBarrier->style == TR_FENCE ? Ac3d::Surface::PolygonDoubleSidedSmooth : Ac3d::Surface::PolygonSingleSidedSmooth;
CHECKDISPLIST(curBarrier->surface->material, sname, i, 0);
if (!curTexLink)
{
texLen = 0; // edited
}
// fence only has one side (j = 0)
if (curBarrier->style == TR_FENCE && j != 0)
{
xprev = seg->vertex[TR_SR].x; // edited
yprev = seg->vertex[TR_SR].y; // edited
lastBarrier = curBarrier;
continue;
}
trkpos.seg = seg;
if (startNeeded || (runninglentgh > LG_STEP_MAX))
{
NEWDISPLIST(false, sname, i);
if (curTexType == 0)
texLen = 0;
runninglentgh = 0;
xprev = seg->vertex[TR_SR].x; // edited
yprev = seg->vertex[TR_SR].y; // edited
switch (curBarrier->style)
{
case TR_FENCE:
if (j == 0)
{
SETPOINT(-texLen, 0.0, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
SETPOINT(-texLen, 1.0, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + curBarrier->height);
}
break;
case TR_WALL:
switch (j)
{
case 0:
SETPOINT(-texLen, 0, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
SETPOINT(-texLen, 0.33, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + curBarrier->height);
break;
case 1:
trkpos.toStart = 0;
trkpos.toRight = -curBarrier->width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(-texLen, 0.33, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + curBarrier->height);
SETPOINT(-texLen, 0.66, x, y, seg->vertex[TR_SR].z + curBarrier->height);
break;
case 2:
trkpos.toStart = 0;
trkpos.toRight = -curBarrier->width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
if ((mseg->prev->barrier[0]->style != TR_WALL) || (mseg->prev->barrier[0]->height != curBarrier->height) || (mseg->prev->barrier[0]->width != curBarrier->width) || startPolygonNeeded)
{
SETPOINT(-texLen - curBarrier->width / curTexSize, 0.66, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z + curBarrier->height);
SETPOINT(-texLen - curBarrier->width / curTexSize, 1.00, seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z);
}
SETPOINT(-texLen, 0.66, x, y, seg->vertex[TR_SR].z + curBarrier->height);
SETPOINT(-texLen, 1.0, x, y, seg->vertex[TR_SR].z);
break;
}
break;
case TR_CURB:
case TR_PLAN:
// not supported
break;
case TR_PITBUILDING:
case TR_NO_BARRIER:
// nothing to do
break;
}
}
switch (seg->type)
{
case TR_STR:
ts = LMAX;
trkpos.seg = seg;
while (ts < seg->length)
{
trkpos.toStart = ts;
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
curHeight = RtTrackHeightL(&trkpos);
texStep = sqrt(pow((y - yprev), 2.0f) + pow((x - xprev), 2.0f)) / curTexSize; // new
texLen += texStep; // new
xprev = x; // new
yprev = y; // new
switch (curBarrier->style)
{
case TR_FENCE:
if (j == 0)
{
SETPOINT(-texLen, 0, x, y, curHeight);
SETPOINT(-texLen, 1.0, x, y, curHeight + curBarrier->height);
}
break;
case TR_WALL:
switch (j)
{
case 0:
SETPOINT(-texLen, 0.0, x, y, curHeight);
SETPOINT(-texLen, 0.33, x, y, curHeight + curBarrier->height);
break;
case 1:
SETPOINT(-texLen, 0.33, x, y, curHeight + curBarrier->height);
trkpos.toRight = -curBarrier->width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(-texLen, 0.66, x, y, curHeight + curBarrier->height);
break;
case 2:
trkpos.toRight = -curBarrier->width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(-texLen, 0.66, x, y, curHeight + curBarrier->height);
SETPOINT(-texLen, 1.0, x, y, curHeight);
break;
}
break;
case TR_CURB:
case TR_PLAN:
// not supported
break;
case TR_PITBUILDING:
case TR_NO_BARRIER:
// nothing to do
break;
}
ts += LMAX;
}
ts = seg->length;
break;
case TR_LFT:
step = LMAX / (mseg->radiusr);
// texStep = step * mseg->radius / curTexSize; //edited
anz = seg->angle[TR_ZS] + step;
ts = step;
// texLen += texStep;
radiusr = seg->radiusr;
trkpos.seg = seg;
while (anz < seg->angle[TR_ZE])
{
trkpos.toStart = ts;
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
curHeight = RtTrackHeightL(&trkpos);
texStep = sqrt(pow((y - yprev), 2.0f) + pow((x - xprev), 2.0f)) / curTexSize; // new
texLen += texStep; // new
xprev = x; // new
yprev = y; // new
switch (curBarrier->style)
{
case TR_FENCE:
if (j == 0)
{
SETPOINT(-texLen, 0.0, x, y, curHeight);
SETPOINT(-texLen, 1.0, x, y, curHeight + curBarrier->height);
}
break;
case TR_WALL:
switch (j)
{
case 0:
SETPOINT(-texLen, 0.0, x, y, curHeight);
SETPOINT(-texLen, 0.33, x, y, curHeight + curBarrier->height);
break;
case 1:
SETPOINT(-texLen, 0.33, x, y, curHeight + curBarrier->height);
trkpos.toRight = -curBarrier->width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(-texLen, 0.66, x, y, curHeight + curBarrier->height);
break;
case 2:
trkpos.toRight = -curBarrier->width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(-texLen, 0.66, x, y, curHeight + curBarrier->height);
SETPOINT(-texLen, 1.0, x, y, curHeight);
break;
}
break;
case TR_CURB:
case TR_PLAN:
// not supported
break;
case TR_PITBUILDING:
case TR_NO_BARRIER:
// nothing to do
break;
}
ts += step;
// removed
anz += step;
}
ts = seg->arc;
break;
case TR_RGT:
step = LMAX / (mseg->radiusl);
// removed
anz = seg->angle[TR_ZS] - step;
ts = step;
// removed
radiusr = seg->radiusr;
trkpos.seg = seg;
while (anz > seg->angle[TR_ZE])
{
trkpos.toStart = ts;
trkpos.toRight = 0;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
curHeight = RtTrackHeightL(&trkpos);
texStep = sqrt(pow((y - yprev), 2.0f) + pow((x - xprev), 2.0f)) / curTexSize; // new
texLen += texStep; // new
xprev = x; // new
yprev = y; // new
switch (curBarrier->style)
{
case TR_FENCE:
if (j == 0)
{
SETPOINT(-texLen, 0.0, x, y, curHeight);
SETPOINT(-texLen, 1.0, x, y, curHeight + curBarrier->height);
}
break;
case TR_WALL:
switch (j)
{
case 0:
SETPOINT(-texLen, 0.0, x, y, curHeight);
SETPOINT(-texLen, 0.33, x, y, curHeight + curBarrier->height);
break;
case 1:
SETPOINT(-texLen, 0.33, x, y, curHeight + curBarrier->height);
trkpos.toRight = -curBarrier->width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(-texLen, 0.66, x, y, curHeight + curBarrier->height);
break;
case 2:
trkpos.toRight = -curBarrier->width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(-texLen, 0.66, x, y, curHeight + curBarrier->height);
SETPOINT(-texLen, 1.0, x, y, curHeight);
break;
}
break;
case TR_CURB:
case TR_PLAN:
// not supported
break;
case TR_PITBUILDING:
case TR_NO_BARRIER:
// nothing to do
break;
}
ts += step;
anz -= step;
}
ts = seg->arc;
break;
}
texStep = sqrt(pow((seg->vertex[TR_ER].y - yprev), 2.0f) + pow((seg->vertex[TR_ER].x - xprev), 2.0f)) / curTexSize; // new
texLen += texStep; // edited
xprev = seg->vertex[TR_ER].x; // new
yprev = seg->vertex[TR_ER].y; // new
switch (curBarrier->style)
{
case TR_FENCE:
if (j == 0)
{
SETPOINT(-texLen, 0.0, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
SETPOINT(-texLen, 1.0, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + curBarrier->height);
}
break;
case TR_WALL:
switch (j)
{
case 0:
SETPOINT(-texLen, 0.0, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
SETPOINT(-texLen, 0.33, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + curBarrier->height);
break;
case 1:
SETPOINT(-texLen, 0.33, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + curBarrier->height);
trkpos.toStart = ts;
trkpos.toRight = -curBarrier->width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(-texLen, 0.66, x, y, seg->vertex[TR_ER].z + curBarrier->height);
break;
case 2:
trkpos.toStart = ts;
trkpos.toRight = -curBarrier->width;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(-texLen, 0.66, x, y, seg->vertex[TR_ER].z + curBarrier->height);
SETPOINT(-texLen, 1.00, x, y, seg->vertex[TR_ER].z);
{
tTrackSeg *nextSide = mseg->next;
while (nextSide->rside)
nextSide = nextSide->rside;
const bool endPolygonNeeded = std::fabs(xprev - nextSide->vertex[TR_SR].x) > 0.001 || std::fabs(yprev - nextSide->vertex[TR_SR].y) > 0.001;
if ((mseg->next->barrier[0]->style != TR_WALL) || (mseg->next->barrier[0]->height != curBarrier->height) || (mseg->next->barrier[0]->width != curBarrier->width) || endPolygonNeeded)
{
SETPOINT(-texLen + curBarrier->width / curTexSize, 0.66, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z + curBarrier->height);
SETPOINT(-texLen + curBarrier->width / curTexSize, 1.00, seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z);
}
}
break;
}
break;
case TR_CURB:
case TR_PLAN:
// not supported
break;
case TR_PITBUILDING:
case TR_NO_BARRIER:
// nothing to do
break;
}
startNeeded = false;
runninglentgh += seg->length;
lastBarrier = curBarrier;
}
}
/* Left Barrier */
lastBarrier = Track->seg->next->prev->barrier[1];
curSurfType = Ac3d::Surface::PolygonSingleSidedSmooth;
for (int j = 0; j < 3; j++)
{
prevTexId = 0;
texLen = 0;
startNeeded = true;
runninglentgh = 0;
sprintf(sname, "B%dLt", j);
for (i = 0, mseg = Track->seg->next; i < Track->nseg; i++, mseg = mseg->next)
{
// Find last side segment
seg = mseg;
while (seg->lside)
seg = seg->lside;
curBarrier = mseg->barrier[1];
if (seg->raceInfo & TR_PITBUILD || curBarrier->style == TR_NO_BARRIER)
{
runninglentgh = 0;
startNeeded = true;
xprev = 0.0;
yprev = 0.0;
continue;
}
bool startPolygonNeeded = false;
if (lastBarrier)
{
if (lastBarrier->style != curBarrier->style || lastBarrier->width != curBarrier->width || lastBarrier->height != curBarrier->height)
startNeeded = true;
else if (lastBarrier->style == curBarrier->style)
{
tTrackSeg *prevSide = mseg->prev;
while (prevSide->lside)
prevSide = prevSide->lside;
startPolygonNeeded = std::fabs(seg->vertex[TR_SL].x - prevSide->vertex[TR_EL].x) > 0.001 || std::fabs(seg->vertex[TR_SL].y - prevSide->vertex[TR_EL].y) > 0.001;
if (startPolygonNeeded)
startNeeded = true;
}
}
curSurfType = curBarrier->style == TR_FENCE ? Ac3d::Surface::PolygonDoubleSidedSmooth : Ac3d::Surface::PolygonSingleSidedSmooth;
CHECKDISPLIST(curBarrier->surface->material, sname, i, 0);
if (!curTexLink)
{
texLen = 0;
}
// fence only has one side (j = 0)
if (curBarrier->style == TR_FENCE && j != 0)
{
xprev = seg->vertex[TR_SR].x; // edited
yprev = seg->vertex[TR_SR].y; // edited
continue;
}
trkpos.seg = seg;
if (startNeeded || (runninglentgh > LG_STEP_MAX))
{
NEWDISPLIST(false, sname, i);
runninglentgh = 0;
if (curTexType == 0)
texLen = 0;
xprev = seg->vertex[TR_SR].x; // edited
yprev = seg->vertex[TR_SR].y; // edited
switch (curBarrier->style)
{
case TR_FENCE:
if (j == 0)
{
SETPOINT(texLen, 1.0, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + curBarrier->height);
SETPOINT(texLen, 0.0, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toStart = 0;
trkpos.toRight = curBarrier->width + RtTrackGetWidth(seg, 0);
trkpos.seg = seg;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
if ((mseg->prev->barrier[1]->style != TR_WALL) || (mseg->prev->barrier[1]->height != curBarrier->height) || (mseg->prev->barrier[1]->width != curBarrier->width) || startPolygonNeeded)
{
SETPOINT(texLen - curBarrier->width / curTexSize, 1.00, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
SETPOINT(texLen - curBarrier->width / curTexSize, 0.66, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + curBarrier->height);
}
SETPOINT(texLen, 1.0, x, y, seg->vertex[TR_SL].z);
SETPOINT(texLen, 0.66, x, y, seg->vertex[TR_SL].z + curBarrier->height);
break;
case 1:
trkpos.toStart = 0;
trkpos.toRight = curBarrier->width + RtTrackGetWidth(seg, 0);
trkpos.seg = seg;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, seg->vertex[TR_SL].z + curBarrier->height);
SETPOINT(texLen, 0.33, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + curBarrier->height);
break;
case 2:
SETPOINT(texLen, 0.33, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z + curBarrier->height);
SETPOINT(texLen, 0.0, seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z);
break;
}
break;
case TR_CURB:
case TR_PLAN:
// not supported
break;
case TR_PITBUILDING:
case TR_NO_BARRIER:
// nothing to do
break;
}
}
switch (seg->type)
{
case TR_STR:
ts = LMAX;
trkpos.seg = seg;
while (ts < seg->length)
{
trkpos.toStart = ts;
trkpos.toRight = RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
curHeight = RtTrackHeightL(&trkpos);
texStep = sqrt(pow((y - yprev), 2.0f) + pow((x - xprev), 2.0f)) / curTexSize; // new
texLen += texStep; // new
xprev = x; // new
yprev = y; // new
switch (curBarrier->style)
{
case TR_FENCE:
if (j == 0)
{
SETPOINT(texLen, 1.0, x, y, curHeight + curBarrier->height);
SETPOINT(texLen, 0, x, y, curHeight);
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toRight = curBarrier->width + RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 1.0, x, y, curHeight);
SETPOINT(texLen, 0.66, x, y, curHeight + curBarrier->height);
break;
case 1:
trkpos.toRight = curBarrier->width + RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, curHeight + curBarrier->height);
trkpos.toRight = RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, curHeight + curBarrier->height);
break;
case 2:
SETPOINT(texLen, 0.33, x, y, curHeight + curBarrier->height);
SETPOINT(texLen, 0, x, y, curHeight);
break;
}
break;
case TR_CURB:
case TR_PLAN:
// not supported
break;
case TR_PITBUILDING:
case TR_NO_BARRIER:
// nothing to do
break;
}
ts += LMAX;
}
ts = seg->length;
break;
case TR_LFT:
step = LMAX / (mseg->radiusr);
anz = seg->angle[TR_ZS] + step;
ts = step;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz < seg->angle[TR_ZE])
{
trkpos.toStart = ts;
trkpos.toRight = RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
curHeight = RtTrackHeightL(&trkpos);
texStep = sqrt(pow((y - yprev), 2.0f) + pow((x - xprev), 2.0f)) / curTexSize; // new
texLen += texStep; // new
xprev = x; // new
yprev = y; // new
switch (curBarrier->style)
{
case TR_FENCE:
if (j == 0)
{
SETPOINT(texLen, 1.0, x, y, curHeight + curBarrier->height);
SETPOINT(texLen, 0, x, y, curHeight);
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toRight = curBarrier->width + RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 1.0, x, y, curHeight);
SETPOINT(texLen, 0.66, x, y, curHeight + curBarrier->height);
break;
case 1:
trkpos.toRight = curBarrier->width + RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, curHeight + curBarrier->height);
trkpos.toRight = RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, curHeight + curBarrier->height);
break;
case 2:
SETPOINT(texLen, 0.33, x, y, curHeight + curBarrier->height);
SETPOINT(texLen, 0, x, y, curHeight);
break;
}
break;
case TR_CURB:
case TR_PLAN:
// not supported
break;
case TR_PITBUILDING:
case TR_NO_BARRIER:
// nothing to do
break;
}
ts += step;
anz += step;
}
ts = seg->arc;
break;
case TR_RGT:
step = LMAX / (mseg->radiusl);
anz = seg->angle[TR_ZS] - step;
ts = step;
radiusl = seg->radiusl;
trkpos.seg = seg;
while (anz > seg->angle[TR_ZE])
{
trkpos.toStart = ts;
trkpos.toRight = RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
curHeight = RtTrackHeightL(&trkpos);
texStep = sqrt(pow((y - yprev), 2.0f) + pow((x - xprev), 2.0f)) / curTexSize; // new
texLen += texStep; // new
xprev = x; // new
yprev = y; // new
switch (curBarrier->style)
{
case TR_FENCE:
if (j == 0)
{
SETPOINT(texLen, 1.0, x, y, curHeight + curBarrier->height);
SETPOINT(texLen, 0, x, y, curHeight);
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toRight = curBarrier->width + RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 1.0, x, y, curHeight);
SETPOINT(texLen, 0.66, x, y, curHeight + curBarrier->height);
break;
case 1:
trkpos.toRight = curBarrier->width + RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, curHeight + curBarrier->height);
trkpos.toRight = RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.33, x, y, curHeight + curBarrier->height);
break;
case 2:
SETPOINT(texLen, 0.33, x, y, curHeight + curBarrier->height);
SETPOINT(texLen, 0, x, y, curHeight);
break;
}
break;
case TR_CURB:
case TR_PLAN:
// not supported
break;
case TR_PITBUILDING:
case TR_NO_BARRIER:
// nothing to do
break;
}
ts += step;
anz -= step;
}
ts = seg->arc;
break;
}
texStep = sqrt(pow((seg->vertex[TR_ER].y - yprev), 2.0f) + pow((seg->vertex[TR_ER].x - xprev), 2.0f)) / curTexSize; // new
texLen += texStep; // edited
xprev = seg->vertex[TR_ER].x; // new
yprev = seg->vertex[TR_ER].y;
switch (curBarrier->style)
{
case TR_FENCE:
if (j == 0)
{
SETPOINT(texLen, 1.0, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + curBarrier->height);
SETPOINT(texLen, 0, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
}
break;
case TR_WALL:
switch (j)
{
case 0:
trkpos.toStart = ts;
trkpos.toRight = curBarrier->width + RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 1.0, x, y, seg->vertex[TR_EL].z);
SETPOINT(texLen, 0.66, x, y, seg->vertex[TR_EL].z + curBarrier->height);
{
tTrackSeg *nextSide = mseg->next;
while (nextSide->lside)
nextSide = nextSide->lside;
const bool endPolygonNeeded = std::fabs(seg->vertex[TR_EL].x - nextSide->vertex[TR_SL].x) > 0.001 || std::fabs(seg->vertex[TR_EL].y - nextSide->vertex[TR_SL].y) > 0.001;
if ((mseg->next->barrier[1]->style != TR_WALL) || (mseg->next->barrier[1]->height != curBarrier->height) || (mseg->next->barrier[1]->width != curBarrier->width) || endPolygonNeeded)
{
SETPOINT(texLen + curBarrier->width / curTexSize, 1.00, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
SETPOINT(texLen + curBarrier->width / curTexSize, 0.66, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + curBarrier->height);
}
}
break;
case 1:
trkpos.toStart = ts;
trkpos.toRight = curBarrier->width + RtTrackGetWidth(seg, ts);
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
SETPOINT(texLen, 0.66, x, y, seg->vertex[TR_EL].z + curBarrier->height);
SETPOINT(texLen, 0.33, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + curBarrier->height);
break;
case 2:
SETPOINT(texLen, 0.33, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z + curBarrier->height);
SETPOINT(texLen, 0.0, seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z);
break;
}
break;
case TR_CURB:
case TR_PLAN:
// not supported
break;
case TR_PITBUILDING:
case TR_NO_BARRIER:
// nothing to do
break;
}
startNeeded = false;
runninglentgh += seg->length;
lastBarrier = curBarrier;
}
}
if (!bump)
{
curSurfType = Ac3d::Surface::PolygonSingleSidedSmooth;
/* Turn Marks */
for (i = 0, seg = Track->seg->next; i < Track->nseg; i++, seg = seg->next)
{
if (seg->ext)
{
t3Dd normvec;
int nbMarks = seg->ext->nbMarks;
int *marks = seg->ext->marks;
int j, k;
for (j = 0; j < nbMarks; j++)
{
/* find the segment */
tdble lgfs = seg->lgfromstart - (tdble)marks[j];
if (lgfs < 0)
{
lgfs += Track->length;
}
for (k = 0, mseg = Track->seg->next; k < Track->nseg; k++, mseg = mseg->next)
{
if ((lgfs >= mseg->lgfromstart) && (lgfs < (mseg->lgfromstart + mseg->length)))
{
break;
}
}
if (seg->type == TR_RGT)
{
sprintf(buf, "turn%dR", marks[j]);
trkpos.toRight = Track->width + tmHSpace + tmWidth;
}
else
{
sprintf(buf, "turn%dL", marks[j]);
trkpos.toRight = -tmHSpace;
}
trkpos.toStart = lgfs - mseg->lgfromstart;
if (mseg->type != TR_STR)
{
trkpos.toStart = trkpos.toStart / mseg->radius;
}
trkpos.seg = mseg;
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
z = tmVSpace + RtTrackHeightL(&trkpos);
if (seg->type == TR_LFT)
{
RtTrackSideNormalG(mseg, x, y, TR_RGT, &normvec);
normvec.x = -normvec.x;
normvec.y = -normvec.y;
}
else
{
RtTrackSideNormalG(mseg, x, y, TR_LFT, &normvec);
}
CHECKDISPLIST2(buf, 0, "TuMk", mseg->id);
SETPOINT(0.0, 0.0, x, y, z);
SETPOINT(1.0, 0.0, x + tmWidth * normvec.x, y + tmWidth * normvec.y, z);
SETPOINT(0.0, 1.0, x, y, z + tmHeight);
SETPOINT(1.0, 1.0, x + tmWidth * normvec.x, y + tmWidth * normvec.y, z + tmHeight);
CHECKDISPLIST2("back-sign", 0, "TuMk", mseg->id);
SETPOINT(0.0, 0.0, x + tmWidth * normvec.x, y + tmWidth * normvec.y, z);
SETPOINT(1.0, 0.0, x, y, z);
SETPOINT(0.0, 1.0, x + tmWidth * normvec.x, y + tmWidth * normvec.y, z + tmHeight);
SETPOINT(1.0, 1.0, x, y, z + tmHeight);
printf("(%f, %f, %f), (%f, %f, %f)\n", x, y, z, x + tmWidth * normvec.x, y + tmWidth * normvec.y, z + tmHeight);
}
}
}
/* Start Bridge */
if (bridge)
{
curSurfType = Ac3d::Surface::PolygonSingleSidedSmooth;
CHECKDISPLIST2("pylon1", 4, "S0Bg", 0);
#define BR_HEIGHT_1 8.0
#define BR_HEIGHT_2 6.0
#define BR_WIDTH_0 2.0
#define BR_WIDTH_1 2.0
mseg = Track->seg->next;
if (mseg->rside)
{
seg = mseg->rside;
if (seg->rside)
{
seg = seg->rside;
}
}
else
{
seg = mseg;
}
x = seg->vertex[TR_SR].x;
y = seg->vertex[TR_SR].y - 0.1;
z = seg->vertex[TR_SR].z;
SETPOINT(0, 0, x, y, z);
SETPOINT(0, 1, x, y, z + BR_HEIGHT_2);
x += BR_WIDTH_0;
SETPOINT(1, 0, x, y, z);
SETPOINT(1, 1, x, y, z + BR_HEIGHT_2);
y -= BR_WIDTH_1;
SETPOINT(2, 0, x, y, z);
SETPOINT(2, 1, x, y, z + BR_HEIGHT_2);
x -= BR_WIDTH_0;
SETPOINT(3, 0, x, y, z);
SETPOINT(3, 1, x, y, z + BR_HEIGHT_2);
y += BR_WIDTH_1;
SETPOINT(4, 0, x, y, z);
SETPOINT(4, 1, x, y, z + BR_HEIGHT_2);
NEWDISPLIST(false, "S1Bg", 0);
if (mseg->lside)
{
seg = mseg->lside;
if (seg->lside)
{
seg = seg->lside;
}
}
else
{
seg = mseg;
}
x2 = seg->vertex[TR_SL].x;
y2 = seg->vertex[TR_SL].y + 0.1;
z2 = seg->vertex[TR_SL].z;
SETPOINT(0, 1, x2, y2, z + BR_HEIGHT_2);
SETPOINT(0, 0, x2, y2, z2);
x2 += BR_WIDTH_0;
SETPOINT(1, 1, x2, y2, z + BR_HEIGHT_2);
SETPOINT(1, 0, x2, y2, z2);
y2 += BR_WIDTH_1;
SETPOINT(2, 1, x2, y2, z + BR_HEIGHT_2);
SETPOINT(2, 0, x2, y2, z2);
x2 -= BR_WIDTH_0;
SETPOINT(3, 1, x2, y2, z + BR_HEIGHT_2);
SETPOINT(3, 0, x2, y2, z2);
y2 -= BR_WIDTH_1;
SETPOINT(4, 1, x2, y2, z + BR_HEIGHT_2);
SETPOINT(4, 0, x2, y2, z2);
CHECKDISPLIST2("pylon2", 4, "S2Bg", 0);
SETPOINT(0, 1, x, y, z + BR_HEIGHT_1);
SETPOINT(0, 0, x, y, z + BR_HEIGHT_2);
y -= BR_WIDTH_1;
SETPOINT(1, 1, x, y, z + BR_HEIGHT_1);
SETPOINT(1, 0, x, y, z + BR_HEIGHT_2);
x += BR_WIDTH_0;
SETPOINT(2, 1, x, y, z + BR_HEIGHT_1);
SETPOINT(2, 0, x, y, z + BR_HEIGHT_2);
y += BR_WIDTH_1;
SETPOINT(3, 1, x, y, z + BR_HEIGHT_1);
SETPOINT(3, 0, x, y, z + BR_HEIGHT_2);
x -= BR_WIDTH_0;
SETPOINT(3, 1, x + BR_WIDTH_0, y, z + BR_HEIGHT_1);
SETPOINT(3, 0, x, y, z + BR_HEIGHT_1);
y -= BR_WIDTH_1;
SETPOINT(4, 1, x + BR_WIDTH_0, y, z + BR_HEIGHT_1);
SETPOINT(4, 0, x, y, z + BR_HEIGHT_1);
y += BR_WIDTH_1; /* back to origin */
NEWDISPLIST(false, "S3Bg", 0);
y2 += BR_WIDTH_1;
SETPOINT(0, 1, x2 + BR_WIDTH_0, y2, z + BR_HEIGHT_1);
SETPOINT(0, 0, x2, y2, z + BR_HEIGHT_1);
y2 -= BR_WIDTH_1;
SETPOINT(1, 1, x2 + BR_WIDTH_0, y2, z + BR_HEIGHT_1);
SETPOINT(1, 0, x2, y2, z + BR_HEIGHT_1);
x2 += BR_WIDTH_0;
SETPOINT(1, 1, x2, y2, z + BR_HEIGHT_1);
SETPOINT(1, 0, x2, y2, z + BR_HEIGHT_2);
y2 += BR_WIDTH_1;
SETPOINT(2, 1, x2, y2, z + BR_HEIGHT_1);
SETPOINT(2, 0, x2, y2, z + BR_HEIGHT_2);
x2 -= BR_WIDTH_0;
SETPOINT(3, 1, x2, y2, z + BR_HEIGHT_1);
SETPOINT(3, 0, x2, y2, z + BR_HEIGHT_2);
y2 -= BR_WIDTH_1;
SETPOINT(4, 1, x2, y2, z + BR_HEIGHT_1);
SETPOINT(4, 0, x2, y2, z + BR_HEIGHT_2);
/* Middle on the bridge */
CHECKDISPLIST2("pylon3", 4, "S4Bg", 2);
SETPOINT(0, 0, x2, y2, z + BR_HEIGHT_2);
SETPOINT(1, 0, x, y, z + BR_HEIGHT_2);
SETPOINT(0, 0.25, x2, y2, z + BR_HEIGHT_1);
SETPOINT(1, 0.25, x, y, z + BR_HEIGHT_1);
x += BR_WIDTH_0;
x2 += BR_WIDTH_0;
SETPOINT(0, 0.5, x2, y2, z + BR_HEIGHT_1);
SETPOINT(1, 0.5, x, y, z + BR_HEIGHT_1);
SETPOINT(0, 0.75, x2, y2, z + BR_HEIGHT_2);
SETPOINT(1, 0.75, x, y, z + BR_HEIGHT_2);
x -= BR_WIDTH_0;
x2 -= BR_WIDTH_0;
SETPOINT(0, 1, x2, y2, z + BR_HEIGHT_2);
SETPOINT(1, 1, x, y, z + BR_HEIGHT_2);
}
/* draw the pits */
#define PIT_HEIGHT 5.0
#define PIT_DEEP 10.0
#define PIT_TOP 0.2
pits = &(Track->pits);
initPits(Track, TrackHandle, pits);
curSurfType = Ac3d::Surface::PolygonDoubleSidedSmooth; // this must be 2 sided
switch (pits->type)
{
case TR_PIT_ON_TRACK_SIDE: {
static int uid = 1;
t3Dd normvec;
startNeeded = true;
sprintf(sname, "P%dts", uid++);
CHECKDISPLIST3("concrete2.png", 4, sname, pits->driversPits[0].pos.seg->id);
RtTrackLocal2Global(&(pits->driversPits[0].pos), &x, &y, pits->driversPits[0].pos.type);
RtTrackSideNormalG(pits->driversPits[0].pos.seg, x, y, pits->side, &normvec);
z2 = RtTrackHeightG(pits->driversPits[0].pos.seg, x, y);
x2 = x + PIT_TOP * normvec.x;
y2 = y + PIT_TOP * normvec.y;
SETPOINT(1.0 - PIT_TOP, PIT_HEIGHT - PIT_TOP, x2, y2, z2 + PIT_HEIGHT - PIT_TOP);
SETPOINT(1.0 - PIT_TOP, PIT_HEIGHT, x2, y2, z2 + PIT_HEIGHT);
x2 = x;
y2 = y;
SETPOINT(1.0, PIT_HEIGHT - PIT_TOP, x2, y2, z2 + PIT_HEIGHT - PIT_TOP);
x2 = x - PIT_DEEP * normvec.x;
y2 = y - PIT_DEEP * normvec.y;
SETPOINT(1.0 + PIT_DEEP, PIT_HEIGHT, x2, y2, z2 + PIT_HEIGHT);
x2 = x;
y2 = y;
SETPOINT(1.0, 0, x2, y2, z2);
x2 = x - PIT_DEEP * normvec.x;
y2 = y - PIT_DEEP * normvec.y;
SETPOINT(1.0 + PIT_DEEP, 0, x2, y2, z2);
for (i = 0; i < pits->driversPitsNb; i++)
{
startNeeded = true;
sprintf(sname, "P%dts", uid++);
CHECKDISPLIST3("concrete.png", 4, sname, pits->driversPits[i].pos.seg->id);
RtTrackLocal2Global(&(pits->driversPits[i].pos), &x, &y, pits->driversPits[i].pos.type);
RtTrackSideNormalG(pits->driversPits[i].pos.seg, x, y, pits->side, &normvec);
x2 = x;
y2 = y;
z2 = RtTrackHeightG(pits->driversPits[i].pos.seg, x2, y2);
if (pits->side == TR_RGT)
{
x3 = x + pits->len * normvec.y;
y3 = y - pits->len * normvec.x;
}
else
{
x3 = x - pits->len * normvec.y;
y3 = y + pits->len * normvec.x;
}
z3 = RtTrackHeightG(pits->driversPits[i].pos.seg, x3, y3);
SETPOINT(pits->len, 0, x2, y2, z2 + PIT_HEIGHT - PIT_TOP);
SETPOINT(0, 0, x3, y3, z3 + PIT_HEIGHT - PIT_TOP);
tdble dx = PIT_TOP * normvec.x;
tdble dy = PIT_TOP * normvec.y;
SETPOINT(pits->len, PIT_TOP, x2 + dx, y2 + dy, z2 + PIT_HEIGHT - PIT_TOP);
SETPOINT(0, PIT_TOP, x3 + dx, y3 + dy, z3 + PIT_HEIGHT - PIT_TOP);
SETPOINT(pits->len, 2 * PIT_TOP, x2 + dx, y2 + dy, z2 + PIT_HEIGHT);
SETPOINT(0, 2 * PIT_TOP, x3 + dx, y3 + dy, z3 + PIT_HEIGHT);
dx = -PIT_DEEP * normvec.x;
dy = -PIT_DEEP * normvec.y;
SETPOINT(pits->len, 2 * PIT_TOP + PIT_DEEP, x2 + dx, y2 + dy, z2 + PIT_HEIGHT);
SETPOINT(0, 2 * PIT_TOP + PIT_DEEP, x3 + dx, y3 + dy, z3 + PIT_HEIGHT);
SETPOINT(pits->len, 2 * PIT_TOP + PIT_DEEP + PIT_HEIGHT, x2 + dx, y2 + dy, z2);
SETPOINT(0, 2 * PIT_TOP + PIT_DEEP + PIT_HEIGHT, x3 + dx, y3 + dy, z3);
} // for i
startNeeded = true;
i--;
sprintf(sname, "P%dts", uid++);
CHECKDISPLIST3("concrete2.png", 4, sname, pits->driversPits[i].pos.seg->id);
RtTrackLocal2Global(&(pits->driversPits[i].pos), &x, &y, pits->driversPits[i].pos.type);
RtTrackSideNormalG(pits->driversPits[i].pos.seg, x, y, pits->side, &normvec);
if (pits->side == TR_RGT)
{
x += pits->len * normvec.y;
y -= pits->len * normvec.x;
}
else
{
x -= pits->len * normvec.y;
y += pits->len * normvec.x;
}
z2 = RtTrackHeightG(pits->driversPits[i].pos.seg, x, y);
x2 = x + PIT_TOP * normvec.x;
y2 = y + PIT_TOP * normvec.y;
SETPOINT(1.0 - PIT_TOP, PIT_HEIGHT, x2, y2, z2 + PIT_HEIGHT);
SETPOINT(1.0 - PIT_TOP, PIT_HEIGHT - PIT_TOP, x2, y2, z2 + PIT_HEIGHT - PIT_TOP);
x2 = x - PIT_DEEP * normvec.x;
y2 = y - PIT_DEEP * normvec.y;
SETPOINT(1.0 + PIT_DEEP, PIT_HEIGHT, x2, y2, z2 + PIT_HEIGHT);
x2 = x;
y2 = y;
SETPOINT(1.0, PIT_HEIGHT - PIT_TOP, x2, y2, z2 + PIT_HEIGHT - PIT_TOP);
x2 = x - PIT_DEEP * normvec.x;
y2 = y - PIT_DEEP * normvec.y;
SETPOINT(1.0 + PIT_DEEP, 0, x2, y2, z2);
x2 = x;
y2 = y;
SETPOINT(1.0, 0, x2, y2, z2);
break; // TR_PIT_ON_TRACK_SIDE
}
case TR_PIT_NO_BUILDING:
break;
case TR_PIT_ON_SEPARATE_PATH:
break;
case TR_PIT_NONE:
break;
} // switch pits->type
}
CLOSEDISPLIST();
printf("=== Indices really used = %d\n", nbvert);
return 0;
} // InitScene
static void saveObject(Ac3d &ac3d, int nb, int start, char *texture, char *name, Ac3d::Surface::SURF surfType)
{
Ac3d::Object object;
object.type = "poly";
object.name = name;
object.textures.emplace_back(texture);
for (int i = 0; i < nb; i++)
{
int index = 3 * (start + i);
object.vertices.emplace_back(trackvertices[index], trackvertices[index + 2], -trackvertices[index + 1]);
}
Ac3d::Surface surface;
surface.surf = surfType;
surface.mat = 0;
surface.refs.emplace_back(0, tracktexcoord[2 * start], tracktexcoord[2 * start + 1]);
surface.refs.emplace_back(1, tracktexcoord[2 * (start + 1)], tracktexcoord[2 * (start + 1) + 1]);
surface.refs.emplace_back(2, tracktexcoord[2 * (start + 2)], tracktexcoord[2 * (start + 2) + 1]);
object.surfaces.push_back(surface);
/* triangle strip conversion to triangles */
for (int i = 2; i < nb - 1; i++)
{
surface.surf = surfType;
surface.mat = 0;
surface.refs.clear();
if ((i % 2) == 0)
{
int index = i;
surface.refs.emplace_back(index, tracktexcoord[2 * (start + index)], tracktexcoord[2 * (start + index) + 1]);
index = i - 1;
surface.refs.emplace_back(index, tracktexcoord[2 * (start + index)], tracktexcoord[2 * (start + index) + 1]);
index = i + 1;
surface.refs.emplace_back(index, tracktexcoord[2 * (start + index)], tracktexcoord[2 * (start + index) + 1]);
}
else
{
int index = i - 1;
surface.refs.emplace_back(index, tracktexcoord[2 * (start + index)], tracktexcoord[2 * (start + index) + 1]);
index = i;
surface.refs.emplace_back(index, tracktexcoord[2 * (start + index)], tracktexcoord[2 * (start + index) + 1]);
index = i + 1;
surface.refs.emplace_back(index, tracktexcoord[2 * (start + index)], tracktexcoord[2 * (start + index) + 1]);
}
object.surfaces.push_back(surface);
}
ac3d.addObject(object);
ac3d.stack.pop();
}
static void SaveMainTrack(Ac3d &ac3d, bool bump, bool raceline)
{
tDispElt *aDispElt;
char buf[256];
int i;
for (i = 0; i < GroupNb; i++)
{
if (Groups[i].nb != 0)
{
aDispElt = Groups[i].dispList;
sprintf(buf, "TKMN%d", i);
Ac3d::Object object;
object.type = "group";
object.name = buf;
ac3d.addObject(object);
do
{
aDispElt = aDispElt->next;
if (aDispElt->nb != 0)
{
sprintf(buf, "%s%d", aDispElt->name, aDispElt->id);
// skip bad display lists
if (aDispElt->nb > 0 && aDispElt->nb < 3)
{
GfLogWarning("Bug: Display list %s has %d vertices!\n", buf, aDispElt->nb);
continue;
}
if (bump)
{
saveObject(ac3d, aDispElt->nb, aDispElt->start, aDispElt->texture->namebump, buf, aDispElt->surfType);
}
else if (raceline)
{
saveObject(ac3d, aDispElt->nb, aDispElt->start, aDispElt->texture->nameraceline, buf, aDispElt->surfType);
}
else
{
saveObject(ac3d, aDispElt->nb, aDispElt->start, aDispElt->texture->name, buf, aDispElt->surfType);
}
}
} while (aDispElt != Groups[i].dispList);
ac3d.stack.pop();
}
}
}
/** Calculate track parameters and exit without any file creation
It is for information only, mainly for use from TrackEditor.
@param Track track structure
@param TrackHandle handle on the track description
@return none
*/
void CalculateTrack(tTrack *Track, void *TrackHandle, bool bump, bool raceline, bool bridge)
{
TrackStep = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_TSTEP, nullptr, TrackStep);
printf("Track step: %.2f ", TrackStep);
InitScene(Track, TrackHandle, bump, raceline, bridge);
printf("Calculation finished\n");
}
/** Generate the track AC3D file(s).
@param Track track structure
@param TrackHandle handle on the track description
@param outFile output file name for track only
@param AllFd fd of the merged file
@return none
*/
void GenerateTrack(tTrack *Track, void *TrackHandle, const std::string &outFile, Ac3d &allAc3d, bool all, bool bump, bool raceline, bool bridge)
{
TrackStep = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_TSTEP, nullptr, TrackStep);
printf("Track step: %.2f ", TrackStep);
InitScene(Track, TrackHandle, bump, raceline, bridge);
if (!outFile.empty())
{
Ac3d ac3d;
ac3d.addDefaultMaterial();
Ac3d::Object object;
object.type = "group";
object.name = "track";
ac3d.addObject(object);
SaveMainTrack(ac3d, bump, raceline);
ac3d.writeFile(outFile, false);
}
if (all)
{
Ac3d::Object object;
object.type = "group";
object.name = "track";
allAc3d.addObject(object);
SaveMainTrack(allAc3d, bump, raceline);
allAc3d.stack.pop();
}
}