void save_database(void) { int i; tFace *curFace; sgMat4 m; ssgBranch *b = new ssgBranch(); sgMakeIdentMat4(m); for (i = 0; i < NbRows; i++) { curFace = GF_TAILQ_FIRST(&(Row[i].faces)); while (curFace) { if (curFace->isPresent) { curFace->branch->setTransform(m); ssgFlatten(curFace->branch); ssgStripify(curFace->branch); } curFace = GF_TAILQ_NEXT(curFace, link); } } b->addKid(Root); ssgFlatten(Root); ssgStripify(Root); myssgSaveAC(OutputFileName, b, SkinFileName); }
void CountRelief(int interior, int *nb_vert, int *nb_seg) { tLine *curLine; tRingListHead *curHead; *nb_vert = *nb_seg = 0; if (Root == NULL) { return; } if (interior) { curHead = &InteriorList; } else { curHead = &ExteriorList; } curLine = GF_TAILQ_FIRST(curHead); while (curLine != NULL) { ssgBranch *br = curLine->branch->getParent(0); ssgBranch *br2 = new ssgBranch(); br2->addKid(br); ssgFlatten(br); curLine->branch = br2; countRec((ssgEntity *)curLine->branch, nb_vert, nb_seg); curLine = GF_TAILQ_NEXT(curLine, link); } }
/* * Recalculate the bounding box of the faces */ void calc_bbox(void) { int i, j; tFace *curFace; ssgEntity *e; sgVec3 min, max; int nbcol; fprintf(stderr, "Bounding boxes:\n"); NbMaxCols = 0; for (i = 0; i < NbRows; i++) { curFace = GF_TAILQ_FIRST(&(Row[i].faces)); nbcol = 0; while (curFace) { nbcol++; if (curFace->isPresent) { e = curFace->branch; min[0] = min[1] = min[2] = INT_MAX; max[0] = max[1] = max[2] = -INT_MAX; updt_bbox(e, min, max); for (j = 0; j < 3; j++) { curFace->lbbmin[j] = min[j]; curFace->lbbmax[j] = max[j]; } fprintf(stderr, " Face %s : %f %f %f --- %f %f %f\n", curFace->faceName, min[0], min[1], min[2], max[0], max[1], max[2]); } curFace = GF_TAILQ_NEXT(curFace, link); } NbMaxCols = MAX(NbMaxCols, nbcol); } }
void draw(void) { int i; tFace *curFace; sgVec3 cam; cam[0] = cam[2] = 0; cam[1] = -10000; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ssgSetOrtho(ImgSize, ImgSize); for (i = 0; i < NbRows; i++) { curFace = GF_TAILQ_FIRST(&(Row[i].faces)); while (curFace) { if (curFace->isPresent) { printf("Drawing face %s\n", curFace->faceName); ssgSetNearFar(MIN(curFace->sbbmin[1], curFace->sbbmax[1]) - 1, MAX(curFace->sbbmin[1], curFace->sbbmax[1]) + 1); ssgCullAndDraw((ssgRoot*)curFace->branch); } curFace = GF_TAILQ_NEXT(curFace, link); } } //saveSkin(); }
static void rmFreeDrvList(void) { tDrvElt *cur; while ((cur = GF_TAILQ_FIRST(&DrvList)) != NULL) { GF_TAILQ_REMOVE(&DrvList, cur, link); free(cur->name); free(cur->dname); GfParmReleaseHandle(cur->car); free(cur); } }
void set_texture_coord(void) { int i; tFace *curFace; for (i = 0; i < NbRows; i++) { curFace = GF_TAILQ_FIRST(&(Row[i].faces)); while (curFace) { if (curFace->isPresent) { /* now apply the matrix to the vertices */ set_texcoord(curFace->branch, curFace->mat); } curFace = GF_TAILQ_NEXT(curFace, link); } } }
void ReSituationUpdater::freezSituation(tRmInfo*& pSituation) { if (pSituation) { // carList if (pSituation->carList) { for (int nCarInd = 0; nCarInd < _nInitDrivers; nCarInd++) { tCarElt* pTgtCar = &pSituation->carList[nCarInd]; tCarPenalty *penalty; while ((penalty = GF_TAILQ_FIRST(&(pTgtCar->_penaltyList))) != GF_TAILQ_END(&(pTgtCar->_penaltyList))) { GF_TAILQ_REMOVE (&(pTgtCar->_penaltyList), penalty, link); free(penalty); } free(pTgtCar->_curSplitTime); free(pTgtCar->_bestSplitTime); } free(pSituation->carList); } // s if (pSituation->s) free(pSituation->s); // rules if (pSituation->rules) free(pSituation->rules); // raceEngineInfo if (pSituation->_reMessage) free(pSituation->_reMessage); if (pSituation->_reBigMessage) free(pSituation->_reBigMessage); if (pSituation->_reCarInfo) free(pSituation->_reCarInfo); free(pSituation); pSituation = 0; } }
/* Compute Pit stop time */ void ReCarsUpdateCarPitTime(tCarElt *car) { tSituation *s = ReInfo->s; tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]); tCarPenalty *penalty; int i; // GfLogDebug("ReCarsUpdateCarPitTime(%s) : typ=%d, fuel=%f, rep=%d\n", // car->_name, car->_pitStopType, car->_pitFuel, car->_pitRepair); switch (car->_pitStopType) { case RM_PIT_REPAIR: info->totalPitTime = 2.0f + fabs((double)(car->_pitFuel)) / 8.0f + (tdble)(fabs((double)(car->_pitRepair))) * 0.007f; car->_scheduledEventTime = s->currentTime + info->totalPitTime; RePhysicsEngine().reconfigureCar(car); for (i=0; i<4; i++) { car->_tyreCondition(i) = 1.01f; car->_tyreT_in(i) = 50.0f; car->_tyreT_mid(i) = 50.0f; car->_tyreT_out(i) = 50.0f; } GfLogInfo("%s in repair pit stop for %.1f s (refueling by %.1f l, repairing by %d).\n", car->_name, info->totalPitTime, car->_pitFuel, car->_pitRepair); break; case RM_PIT_STOPANDGO: penalty = GF_TAILQ_FIRST(&(car->_penaltyList)); if (penalty && penalty->penalty == RM_PENALTY_10SEC_STOPANDGO) info->totalPitTime = 10.0; else info->totalPitTime = 0.0; car->_scheduledEventTime = s->currentTime + info->totalPitTime; // Prevent car->_state & RM_CAR_STATE_PIT from being true for a too short delay, // in order for the penalty management to detect it. if (car->_scheduledEventTime < s->currentTime + RCM_MAX_DT_SIMU) car->_scheduledEventTime += RCM_MAX_DT_SIMU; GfLogInfo("%s in Stop-and-Go pit stop for %.1f s.\n", car->_name, info->totalPitTime); break; } }
/* * Read the faces from AC3D file */ static ssgBranch * hookNode(char *s) { int i; tFace *curFace; for (i = 0; i < NbRows; i++) { curFace = GF_TAILQ_FIRST(&(Row[i].faces)); while (curFace) { if (!strcmp(s, curFace->faceName)) { printf("Face %s found\n", s); curFace->branch = new ssgTransform(); curFace->branch->setName(s); BrNb++; return (ssgBranch*)curFace->branch; } curFace = GF_TAILQ_NEXT(curFace, link); } } return (ssgBranch*)NULL; }
void GenRelief(int interior) { tLine *curLine; tRingListHead *curHead; if (Root == NULL) { return; } if (interior) { curHead = &InteriorList; } else { curHead = &ExteriorList; } curLine = GF_TAILQ_FIRST(curHead); while (curLine != NULL) { genRec((ssgEntity *)curLine->branch); curLine = GF_TAILQ_NEXT(curLine, link); } }
/* Compute the race rules and penalties */ static void reCarsApplyRaceRules(tCarElt *car) { char msg[64]; tCarPenalty *penalty; tTrack *track = ReInfo->track; tRmCarRules *rules = &(ReInfo->rules[car->index]); tTrackSeg *seg = RtTrackGetSeg(&(car->_trkPos)); tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]); tTrackSeg *prevSeg = RtTrackGetSeg(&(info->prevTrkPos)); static const float ctrlMsgColor[] = {0.0, 0.0, 1.0, 1.0}; // DNF cars which need too much time for the current lap, this is mainly to avoid // that a "hanging" driver can stop the quali from finishing. // Allowed time is longest pitstop possible + time for tracklength with speed??? // (currently fixed 10 [m/s]). // For simplicity. Human driver is an exception to this rule, to allow explorers // to enjoy the landscape. // Also - don't remove cars that are currently being repaired in pits // TODO: Make it configurable. if ((car->_curLapTime > 84.5 + ReInfo->track->length/10.0) && !(car->_state & RM_CAR_STATE_PIT) && (car->_driverType != RM_DRV_HUMAN)) { if (!(car->_state & RM_CAR_STATE_ELIMINATED)) GfLogInfo("%s eliminated (too long to finish the lap).\n", car->_name); car->_state |= RM_CAR_STATE_ELIMINATED; return; } // Stop here (no more rules) if not in "Pro" skill level. if (car->_skillLevel < 3) return; // Stop here (no more rules) if "penalties" feature not enables for this race. if (! (ReInfo->s->_features & RM_FEATURE_PENALTIES) ) return; // Otherwise, update control board and do the referee job. // 1) Update control board message about the current penalty if any. // TODO: Optimization : Add penalty->timeStamp and car->ctrl.timeStamp fields // to avoid doing this again and again as long as the penalty is not cleared // whereas it's only needed when the penalty reaches the _penaltyList head. penalty = GF_TAILQ_FIRST(&(car->_penaltyList)); if (penalty) { switch (penalty->penalty) { case RM_PENALTY_DRIVETHROUGH: snprintf(car->ctrl.msg[3], RM_CMD_MAX_MSG_SIZE, "Drive-Through Penalty"); break; case RM_PENALTY_STOPANDGO: snprintf(car->ctrl.msg[3], RM_CMD_MAX_MSG_SIZE, "Stop-and-Go Penalty"); break; case RM_PENALTY_10SEC_STOPANDGO: snprintf(car->ctrl.msg[3], RM_CMD_MAX_MSG_SIZE, "10s Stop-and-Go Penalty"); break; default: *(car->ctrl.msg[3]) = 0; break; } car->ctrl.msg[3][RM_CMD_MAX_MSG_SIZE - 1] = 0; // Some snprintf implementations fail to do so. memcpy(car->ctrl.msgColor, ctrlMsgColor, sizeof(car->ctrl.msgColor)); } else { // No penalty => no message. *(car->ctrl.msg[3]) = 0; } // 2) Check if not too late for the 1st penalty if any. if (penalty) { if (car->_laps > penalty->lapToClear) { // The penalty was not "executed" : too late to clear => disqualified (out of race) reCarsAddPenalty(car, RM_PENALTY_DISQUALIFIED); GfLogInfo("%s disqualified (penalty not executed after 5 laps).\n", car->_name); return; } } // 3) Check if we can hopefuly clear the penalty because just entered the pit lane. // (means that we enter the clearing process, but that it may fail ; nothing sure) if (prevSeg->raceInfo & TR_PITSTART) { //if (seg->raceInfo & TR_PIT) // GfLogDebug("%s crossed pit lane entry.\n", car->_name); if (penalty) { // just entered the pit lane if (seg->raceInfo & TR_PIT) { switch (penalty->penalty) { case RM_PENALTY_DRIVETHROUGH: snprintf(msg, sizeof(msg), "%s Drive-Through penalty clearing", car->_name); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 5); rules->ruleState |= RM_PNST_DRIVETHROUGH; GfLogInfo("%s might get its Drive-Through penalty cleared.\n", car->_name); break; case RM_PENALTY_STOPANDGO: case RM_PENALTY_10SEC_STOPANDGO: snprintf(msg, sizeof(msg), "%s Stop-and-Go penalty clearing", car->_name); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 5); rules->ruleState |= RM_PNST_STOPANDGO; GfLogInfo("%s might get his Stop-and-Go Penalty cleared.\n", car->_name); break; } } } // 4) If in pit lane for more than 1 segment : } else if (prevSeg->raceInfo & TR_PIT) { if (seg->raceInfo & TR_PIT) { // 4a) Check if we can go on with clearing the penalty because stopped in pit. if (car->_state & RM_CAR_STATE_PIT) { //GfLogDebug("%s is pitting.\n", car->_name); if (rules->ruleState & RM_PNST_STOPANDGO && car->_pitStopType == RM_PIT_STOPANDGO) { GfLogInfo("%s Stop-and-Go accepted.\n", car->_name); rules->ruleState |= RM_PNST_STOPANDGO_OK; // Stop-and-Go really done. } } } else if (seg->raceInfo & TR_PITEND) { //GfLogDebug("%s crossing pit lane exit.\n", car->_name); // 4b) Check if the penalty can really and finally be removed because exiting pit lane // and everything went well in the clearing process til then. if (rules->ruleState & (RM_PNST_DRIVETHROUGH | RM_PNST_STOPANDGO_OK)) { snprintf(msg, sizeof(msg), "%s penalty cleared", car->_name); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 5); penalty = GF_TAILQ_FIRST(&(car->_penaltyList)); reCarsRemovePenalty(car, penalty); GfLogInfo("%s %s penalty cleared.\n", car->_name, (rules->ruleState & RM_PNST_DRIVETHROUGH) ? "Drive-Through" : "Stop-and-Go"); } rules->ruleState = 0; } else { // 4c) Exiting pit lane the wrong way : add new stop and go penalty if possible. //GfLogDebug("%s exiting pit lane by a side (bad).\n", car->_name); if (!(rules->ruleState & RM_PNST_STOPANDGO)) { reCarsAddPenalty(car, RM_PENALTY_STOPANDGO); rules->ruleState = RM_PNST_STOPANDGO; GfLogInfo("%s got a Stop-and-Go penalty (went out the pits at a wrong place).\n", car->_name); } } // 5) Still crossing pit lane exit (probably a long PITEND segment) : Nothing bad. } else if (seg->raceInfo & TR_PITEND) { rules->ruleState = 0; // 6) Entering the pits at a wrong place, add new stop and go penalty if possible. } else if (seg->raceInfo & TR_PIT) { //GfLogDebug("%s entering pit lane by a side (bad).\n", car->_name); if (!(rules->ruleState & RM_PNST_STOPANDGO)) { reCarsAddPenalty(car, RM_PENALTY_STOPANDGO); rules->ruleState = RM_PNST_STOPANDGO; GfLogInfo("%s got a Stop-and-Go penalty (went in the pits at a wrong place).\n", car->_name); } } // 7) If too fast in a speed limited section, add new drive-through penalty if possible. if (seg->raceInfo & TR_SPEEDLIMIT) { if (!(rules->ruleState & (RM_PNST_OVERSPEED | RM_PNST_STOPANDGO)) && car->_speed_x > track->pits.speedLimit) { rules->ruleState |= RM_PNST_OVERSPEED; reCarsAddPenalty(car, RM_PENALTY_DRIVETHROUGH); GfLogInfo("%s got a Drive-Through penalty (too fast in the pits).\n", car->_name); } } // Check for jumping starting lights if (ReInfo->s->_raceState & RM_RACE_PRESTART && car->_speed_x > 1) { if (!(rules->ruleState & (RM_PNST_STOPANDGO))) { reCarsAddPenalty(car, RM_PENALTY_STOPANDGO); rules->ruleState = RM_PNST_STOPANDGO; GfLogInfo("%s got a Stop-and-Go penalty (jumped starting lights).\n", car->_name); } } }
/** Interactive Drivers list selection @param vs Pointer on tRmDrvSelect structure (cast to void) @warning The race manager params are modified but not saved. */ void RmDriversSelect(void *vs) { tModList *list; tModList *curmod; char dname[256]; char *sp; char *cardllname; int i, index; tDrvElt *curDrv; int nCars, robotIdx; void *robhdle; struct stat st; char *carName; void *carhdle; int human; #define B_BASE 380 #define B_HT 30 ds = (tRmDrvSelect*)vs; GF_TAILQ_INIT(&DrvList); scrHandle = GfuiScreenCreateEx((float*)NULL, NULL, rmdsActivate, NULL, (tfuiCallback)NULL, 1); GfuiScreenAddBgImg(scrHandle, "data/img/splash-qrdrv.png"); GfuiTitleCreate(scrHandle, "Select Drivers", sizeof("Select Drivers")); GfuiLabelCreate(scrHandle, "Selected", GFUI_FONT_LARGE, 120, 400, GFUI_ALIGN_HC_VB, 0); GfuiLabelCreate(scrHandle, "Not Selected", GFUI_FONT_LARGE, 496, 400, GFUI_ALIGN_HC_VB, 0); selectedScrollList = GfuiScrollListCreate(scrHandle, GFUI_FONT_MEDIUM_C, 20, 80, GFUI_ALIGN_HL_VB, 200, 310, GFUI_SB_RIGHT, NULL, rmdsClickOnDriver); unselectedScrollList = GfuiScrollListCreate(scrHandle, GFUI_FONT_MEDIUM_C, 396, 80, GFUI_ALIGN_HL_VB, 200, 310, GFUI_SB_RIGHT, NULL, rmdsClickOnDriver); GfuiButtonCreate(scrHandle, "Accept", GFUI_FONT_LARGE, 210, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, NULL, rmdsSelect, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiButtonCreate(scrHandle, "Cancel", GFUI_FONT_LARGE, 430, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, ds->prevScreen, rmdsDeactivate, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiButtonCreate(scrHandle, "Move Up", GFUI_FONT_MEDIUM, 320, B_BASE, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, (void*)-1, rmMove, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiButtonCreate(scrHandle, "Move Down", GFUI_FONT_MEDIUM, 320, B_BASE - B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, (void*)1, rmMove, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiButtonCreate(scrHandle, "(De)Select", GFUI_FONT_MEDIUM, 320, B_BASE - 2 * B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, (void*)0, rmSelectDeselect, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); GfuiButtonCreate(scrHandle, "Set Focus", GFUI_FONT_MEDIUM, 320, B_BASE - 3 * B_HT, 100, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP, NULL, rmdsSetFocus, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL); list = (tModList *)NULL; sprintf(buf, "%sdrivers", GetLibDir ()); GfModInfoDir(CAR_IDENT, buf, 1, &list); curmod = list; if (curmod != NULL) { do { curmod = curmod->next; for (i = 0; i < MAX_MOD_ITF; i++) { if (curmod->modInfo[i].name) { sp = strrchr(curmod->sopath, '/'); if (sp == NULL) { sp = curmod->sopath; } else { sp++; } strcpy(dname, sp); dname[strlen(dname) - strlen(DLLEXT) - 1] = 0; /* cut .so or .dll */ sprintf(buf, "%sdrivers/%s/%s.xml", GetLocalDir(), dname, dname); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); if (!robhdle) { sprintf(buf, "drivers/%s/%s.xml", dname, dname); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); } sprintf(path, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, curmod->modInfo[i].index); carName = GfParmGetStr(robhdle, path, ROB_ATTR_CAR, ""); if (strcmp(GfParmGetStr(robhdle, path, ROB_ATTR_TYPE, ROB_VAL_ROBOT), ROB_VAL_ROBOT)) { human = 1; } else { human = 0; } sprintf(path, "cars/%s/%s.xml", carName, carName); if (!stat(path, &st)) { carhdle = GfParmReadFile(path, GFPARM_RMODE_STD); if (carhdle) { curDrv = (tDrvElt*)calloc(1, sizeof(tDrvElt)); curDrv->index = curmod->modInfo[i].index; curDrv->dname = strdup(dname); curDrv->name = strdup(curmod->modInfo[i].name); curDrv->car = carhdle; if (human) { curDrv->human = 1; GF_TAILQ_INSERT_HEAD(&DrvList, curDrv, link); } else { curDrv->human = 0; GF_TAILQ_INSERT_TAIL(&DrvList, curDrv, link); } } else { GfOut("Driver %s not selected because car %s is not readable\n", curmod->modInfo[i].name, carName); } } else { GfOut("Driver %s not selected because car %s is not present\n", curmod->modInfo[i].name, carName); } GfParmReleaseHandle(robhdle); } } } while (curmod != list); } nbSelectedDrivers = 0; nbMaxSelectedDrivers = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_MAXNUM, NULL, 0); nCars = GfParmGetEltNb(ds->param, RM_SECT_DRIVERS); index = 1; for (i = 1; i < nCars+1; i++) { sprintf(dname, "%s/%d", RM_SECT_DRIVERS, i); cardllname = GfParmGetStr(ds->param, dname, RM_ATTR_MODULE, ""); robotIdx = (int)GfParmGetNum(ds->param, dname, RM_ATTR_IDX, (char*)NULL, 0); curDrv = GF_TAILQ_FIRST(&DrvList); if (curDrv != NULL) { do { if ((curDrv->index == robotIdx) && (strcmp(curDrv->dname, cardllname) == 0)) { if (nbSelectedDrivers < nbMaxSelectedDrivers) { GfuiScrollListInsertElement(scrHandle, selectedScrollList, curDrv->name, index, (void*)curDrv); curDrv->sel = index++; nbSelectedDrivers++; } break; } } while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL); } } curDrv = GF_TAILQ_FIRST(&DrvList); if (curDrv != NULL) { do { if (curDrv->sel == 0) { GfuiScrollListInsertElement(scrHandle, unselectedScrollList, curDrv->name, 1000, (void*)curDrv); } } while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL); } GfuiLabelCreate(scrHandle, "Focused:", GFUI_FONT_MEDIUM, 320, B_BASE - 5 * B_HT, GFUI_ALIGN_HC_VB, 0); cardllname = GfParmGetStr(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, ""); robotIdx = (int)GfParmGetNum(ds->param, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, (char*)NULL, 0); curDrv = GF_TAILQ_FIRST(&DrvList); if (curDrv != NULL) { do { if ((curDrv->index == robotIdx) && (strcmp(curDrv->dname, cardllname) == 0)) { break; } } while ((curDrv = GF_TAILQ_NEXT(curDrv, link)) != NULL); } if (curDrv == NULL) { curDrv = GF_TAILQ_FIRST(&DrvList); } if (curDrv == NULL) { FocDrvLabelId = GfuiLabelCreate(scrHandle, "", GFUI_FONT_MEDIUM_C, 320, B_BASE - 5 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256); } else { FocDrvLabelId = GfuiLabelCreate(scrHandle, curDrv->name, GFUI_FONT_MEDIUM_C, 320, B_BASE - 5 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256); } /* Picked Driver Info */ GfuiLabelCreate(scrHandle, "Driver:", GFUI_FONT_MEDIUM, 320, B_BASE - 7 * B_HT, GFUI_ALIGN_HC_VB, 0); PickDrvNameLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C, 320, B_BASE - 7 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256); GfuiLabelCreate(scrHandle, "Car:", GFUI_FONT_MEDIUM, 320, B_BASE - 8 * B_HT, GFUI_ALIGN_HC_VB, 0); PickDrvCarLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C, 320, B_BASE - 8 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256); GfuiLabelCreate(scrHandle, "Category:", GFUI_FONT_MEDIUM, 320, B_BASE - 9 * B_HT, GFUI_ALIGN_HC_VB, 0); PickDrvCategoryLabelId = GfuiLabelCreateEx(scrHandle, "", aColor, GFUI_FONT_MEDIUM_C, 320, B_BASE - 9 * B_HT - GfuiFontHeight(GFUI_FONT_MEDIUM), GFUI_ALIGN_HC_VB, 256); GfuiMenuDefaultKeysAdd(scrHandle); rmdsAddKeys(); GfuiScreenActivate(scrHandle); }
/* Compute the race rules and penalties */ static void ReRaceRules(tCarElt *car) { tCarPenalty *penalty; tTrack *track = ReInfo->track; tRmCarRules *rules = &(ReInfo->rules[car->index]); tTrackSeg *seg = RtTrackGetSeg(&(car->_trkPos)); tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]); tTrackSeg *prevSeg = RtTrackGetSeg(&(info->prevTrkPos)); static float color[] = {0.0, 0.0, 1.0, 1.0}; // DNF cars which need too much time for the current lap, this is mainly to avoid // that a "hanging" driver can stop the quali from finishing. // Allowed time is longest pitstop possible + time for tracklength with speed??? (currently fixed 10 [m/s]). // for simplicity. Human driver is an exception to this rule, to allow explorers // to enjoy the landscape. // TODO: Make it configurable. if ((car->_curLapTime > 84.5 + ReInfo->track->length/10.0) && (car->_driverType != RM_DRV_HUMAN)) { car->_state |= RM_CAR_STATE_ELIMINATED; return; } if (car->_skillLevel < 3) { /* only for the pros */ return; } penalty = GF_TAILQ_FIRST(&(car->_penaltyList)); if (penalty) { if (car->_laps > penalty->lapToClear) { /* too late to clear the penalty, out of race */ car->_state |= RM_CAR_STATE_ELIMINATED; return; } switch (penalty->penalty) { case RM_PENALTY_DRIVETHROUGH: sprintf(car->ctrl.msg[3], "Drive Through Penalty"); break; case RM_PENALTY_STOPANDGO: sprintf(car->ctrl.msg[3], "Stop And Go Penalty"); break; default: *(car->ctrl.msg[3]) = 0; break; } memcpy(car->ctrl.msgColor, color, sizeof(car->ctrl.msgColor)); } if (prevSeg->raceInfo & TR_PITSTART) { /* just entered the pit lane */ if (seg->raceInfo & TR_PIT) { /* may be a penalty can be cleaned up */ if (penalty) { switch (penalty->penalty) { case RM_PENALTY_DRIVETHROUGH: sprintf(buf, "%s DRIVE THROUGH PENALTY CLEANING", car->_name); ReRaceMsgSet(buf, 5); rules->ruleState |= RM_PNST_DRIVETHROUGH; break; case RM_PENALTY_STOPANDGO: sprintf(buf, "%s STOP&GO PENALTY CLEANING", car->_name); ReRaceMsgSet(buf, 5); rules->ruleState |= RM_PNST_STOPANDGO; break; } } } } else if (prevSeg->raceInfo & TR_PIT) { if (seg->raceInfo & TR_PIT) { /* the car stopped in pits */ if (car->_state & RM_CAR_STATE_PIT) { if (rules->ruleState & RM_PNST_DRIVETHROUGH) { /* it's not more a drive through */ rules->ruleState &= ~RM_PNST_DRIVETHROUGH; } else if (rules->ruleState & RM_PNST_STOPANDGO) { rules->ruleState |= RM_PNST_STOPANDGO_OK; } } else { if(rules->ruleState & RM_PNST_STOPANDGO_OK && car->_pitStopType != RM_PIT_STOPANDGO) { rules->ruleState &= ~ ( RM_PNST_STOPANDGO | RM_PNST_STOPANDGO_OK ); } } } else if (seg->raceInfo & TR_PITEND) { /* went out of the pit lane, check if the current penalty is cleared */ if (rules->ruleState & (RM_PNST_DRIVETHROUGH | RM_PNST_STOPANDGO_OK)) { /* clear the penalty */ sprintf(buf, "%s penalty cleared", car->_name); ReRaceMsgSet(buf, 5); penalty = GF_TAILQ_FIRST(&(car->_penaltyList)); GF_TAILQ_REMOVE(&(car->_penaltyList), penalty, link); FREEZ(penalty); } rules->ruleState = 0; } else { /* went out of the pit lane illegally... */ /* it's a new stop and go... */ if (!(rules->ruleState & RM_PNST_STNGO)) { sprintf(buf, "%s STOP&GO PENALTY", car->_name); ReRaceMsgSet(buf, 5); penalty = (tCarPenalty*)calloc(1, sizeof(tCarPenalty)); penalty->penalty = RM_PENALTY_STOPANDGO; penalty->lapToClear = car->_laps + 5; GF_TAILQ_INSERT_TAIL(&(car->_penaltyList), penalty, link); rules->ruleState = RM_PNST_STNGO; } } } else if (seg->raceInfo & TR_PITEND) { rules->ruleState = 0; } else if (seg->raceInfo & TR_PIT) { /* entrered the pits not from the pit entry... */ /* it's a new stop and go... */ if (!(rules->ruleState & RM_PNST_STNGO)) { sprintf(buf, "%s STOP&GO PENALTY", car->_name); ReRaceMsgSet(buf, 5); penalty = (tCarPenalty*)calloc(1, sizeof(tCarPenalty)); penalty->penalty = RM_PENALTY_STOPANDGO; penalty->lapToClear = car->_laps + 5; GF_TAILQ_INSERT_TAIL(&(car->_penaltyList), penalty, link); rules->ruleState = RM_PNST_STNGO; } } if (seg->raceInfo & TR_SPEEDLIMIT) { if (!(rules->ruleState & (RM_PNST_SPD | RM_PNST_STNGO)) && (car->_speed_x > track->pits.speedLimit)) { sprintf(buf, "%s DRIVE THROUGH PENALTY", car->_name); ReRaceMsgSet(buf, 5); rules->ruleState |= RM_PNST_SPD; penalty = (tCarPenalty*)calloc(1, sizeof(tCarPenalty)); penalty->penalty = RM_PENALTY_DRIVETHROUGH; penalty->lapToClear = car->_laps + 5; GF_TAILQ_INSERT_TAIL(&(car->_penaltyList), penalty, link); } } }
void calc_coord(void) { sgMat4 m, m2; int i, j; tFace *curFace; float width, height; float scale, offX, offY; int largerRow; float maxWidth; int col; ssgBranch *branch; ColWidth = (float*)calloc(NbMaxCols, sizeof(float)); fprintf(stderr, "After Rotation:\n"); largerRow = 0; maxWidth = 0; for (i = 0; i < NbRows; i++) { curFace = GF_TAILQ_FIRST(&(Row[i].faces)); while (curFace) { if (curFace->isPresent) { branch = curFace->branch->getParent(0); if (branch->isAKindOf(_SSG_TYPE_BASETRANSFORM)) { ((ssgBaseTransform*)branch)->getTransform(m2); curFace->align[0] *= m2[3][0]; curFace->align[1] *= m2[3][1]; curFace->align[2] *= m2[3][2]; fprintf(stderr, "Align face %s : %f %f %f\n", curFace->faceName, curFace->align[0], curFace->align[1], curFace->align[2]); } sgMakeTransMat4(m, curFace->align); sgMakeIdentMat4(m2); for (j = 0; j < 3; j++) { m2[j][j] = curFace->lscale[j]; } sgPostMultMat4(m, m2); sgMakeRotMat4(m2, curFace->xform.hpr); sgPostMultMat4(m, m2); sgCopyMat4(curFace->mat, m); sgXformPnt3(curFace->sbbmin, curFace->lbbmin, m); sgXformPnt3(curFace->sbbmax, curFace->lbbmax, m); fprintf(stderr, " Face %s : %f %f %f --- %f %f %f\n", curFace->faceName, curFace->sbbmin[0], curFace->sbbmin[1], curFace->sbbmin[2], curFace->sbbmax[0], curFace->sbbmax[1], curFace->sbbmax[2]); curFace->lwidth = 2.0 * MAX(fabs(curFace->sbbmin[0]), fabs(curFace->sbbmax[0])); curFace->lheight = 2.0 * MAX(fabs(curFace->sbbmin[2]), fabs(curFace->sbbmax[2])); //curFace->lwidth = fabs(curFace->sbbmin[0] - curFace->sbbmax[0]); //curFace->lheight = fabs(curFace->sbbmin[2] - curFace->sbbmax[2]); Row[i].lwidth += curFace->lwidth; Row[i].lheight = MAX(Row[i].lheight, curFace->lheight); } curFace = GF_TAILQ_NEXT(curFace, link); } if (Row[i].lwidth > maxWidth) { maxWidth = Row[i].lwidth; largerRow = i; } } height = 0; fprintf(stderr, "After Scaling:\n"); for (i = 0; i < NbRows; i++) { height += Row[i].lheight; } width = maxWidth; scale = (float)ImgSize / MAX(width, height); curFace = GF_TAILQ_FIRST(&(Row[largerRow].faces)); i = 0; fprintf(stderr, "Columns : "); while (curFace) { ColWidth[i] = curFace->lwidth * scale; fprintf(stderr, "%.2f ", ColWidth[i]); curFace = GF_TAILQ_NEXT(curFace, link); i++; } fprintf(stderr, "\n"); fprintf(stderr, "Total Width = %.2f Height = %.2f\n", width, height); fprintf(stderr, "Image Width = %.2f Height = %.2f\n", width*scale, height*scale); offY = - (float)ImgSize / 2.0; for (i = 0; i < NbRows; i++) { curFace = GF_TAILQ_FIRST(&(Row[i].faces)); offY += Row[i].lheight*scale / 2.0; col = 0; offX = - (float)ImgSize / 2.0; while (curFace) { if (curFace->isPresent) { sgCopyMat4(m, curFace->mat); curFace->texScale = scale; sgMakeIdentMat4(m2); for (j = 0; j < 3; j++) { m2[j][j] = scale; } sgPostMultMat4(m, m2); sgXformPnt3(curFace->sbbmin, curFace->lbbmin, m); sgXformPnt3(curFace->sbbmax, curFace->lbbmax, m); offX += ColWidth[col] / 2.0; curFace->offset[0] = offX; curFace->offset[2] = offY; offX += ColWidth[col] / 2.0; sgMakeTransMat4(m2, curFace->offset); sgPostMultMat4(m, m2); sgCopyMat4(curFace->mat, m); curFace->branch->setTransform(m); } else { offX += ColWidth[col]; } col++; curFace = GF_TAILQ_NEXT(curFace, link); } offY += Row[i].lheight*scale / 2.0; } }