Bug #692 - Initial attempt at replay capability
git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@5803 30fe4595-0a0c-4342-8851-515496e4dcbd
This commit is contained in:
parent
560a5b9068
commit
79acb89c9b
|
@ -1,4 +1,4 @@
|
|||
INCLUDE(../cmake/macros.cmake)
|
||||
|
||||
SD_INSTALL_FILES(DATA cmake FILES splitargn.cmake robot.def.in.cmake FindENET.cmake FindPLIB.cmake FindSOLID.cmake
|
||||
FindOGG.cmake FindVORBISFILE.cmake FindVORBIS.cmake)
|
||||
FindOGG.cmake FindVORBISFILE.cmake FindVORBIS.cmake FindSQLITE3.cmake)
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# Find Sqlite3
|
||||
# ~~~~~~~~~~~~
|
||||
# Copyright (c) 2007, Martin Dobias <wonder.sk at gmail.com>
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
# CMake module to search for Sqlite3 library
|
||||
#
|
||||
# If it's found it sets SQLITE3_FOUND to TRUE
|
||||
# and following variables are set:
|
||||
# SQLITE3_INCLUDE_DIR
|
||||
# SQLITE3_LIBRARY
|
||||
|
||||
|
||||
# FIND_PATH and FIND_LIBRARY normally search standard locations
|
||||
# before the specified paths. To search non-standard paths first,
|
||||
# FIND_* is invoked first with specified paths and NO_DEFAULT_PATH
|
||||
# and then again with no specified paths to search the default
|
||||
# locations. When an earlier FIND_* succeeds, subsequent FIND_*s
|
||||
# searching for the same item do nothing.
|
||||
|
||||
# try to use framework on mac
|
||||
# want clean framework path, not unix compatibility path
|
||||
IF (APPLE)
|
||||
IF (CMAKE_FIND_FRAMEWORK MATCHES "FIRST"
|
||||
OR CMAKE_FRAMEWORK_PATH MATCHES "ONLY"
|
||||
OR NOT CMAKE_FIND_FRAMEWORK)
|
||||
SET (CMAKE_FIND_FRAMEWORK_save ${CMAKE_FIND_FRAMEWORK} CACHE STRING "" FORCE)
|
||||
SET (CMAKE_FIND_FRAMEWORK "ONLY" CACHE STRING "" FORCE)
|
||||
#FIND_PATH(SQLITE3_INCLUDE_DIR SQLite3/sqlite3.h)
|
||||
FIND_LIBRARY(SQLITE3_LIBRARY SQLite3)
|
||||
IF (SQLITE3_LIBRARY)
|
||||
# FIND_PATH doesn't add "Headers" for a framework
|
||||
SET (SQLITE3_INCLUDE_DIR ${SQLITE3_LIBRARY}/Headers CACHE PATH "Path to a file.")
|
||||
ENDIF (SQLITE3_LIBRARY)
|
||||
SET (CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK_save} CACHE STRING "" FORCE)
|
||||
ENDIF ()
|
||||
ENDIF (APPLE)
|
||||
|
||||
FIND_PATH(SQLITE3_INCLUDE_DIR sqlite3.h
|
||||
"$ENV{LIB_DIR}/include"
|
||||
"$ENV{LIB_DIR}/include/sqlite"
|
||||
#mingw
|
||||
c:/msys/local/include
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
FIND_PATH(SQLITE3_INCLUDE_DIR sqlite3.h)
|
||||
|
||||
FIND_LIBRARY(SQLITE3_LIBRARY NAMES sqlite3 sqlite3_i PATHS
|
||||
"$ENV{LIB_DIR}/lib"
|
||||
#mingw
|
||||
c:/msys/local/lib
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
FIND_LIBRARY(SQLITE3_LIBRARY NAMES sqlite3)
|
||||
|
||||
IF (SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY)
|
||||
SET(SQLITE3_FOUND TRUE)
|
||||
ENDIF (SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY)
|
||||
|
||||
|
||||
IF (SQLITE3_FOUND)
|
||||
|
||||
IF (NOT SQLITE3_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found Sqlite3: ${SQLITE3_LIBRARY}")
|
||||
ENDIF (NOT SQLITE3_FIND_QUIETLY)
|
||||
|
||||
ELSE (SQLITE3_FOUND)
|
||||
|
||||
IF (SQLITE3_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find Sqlite3")
|
||||
ENDIF (SQLITE3_FIND_REQUIRED)
|
||||
|
||||
ENDIF (SQLITE3_FOUND)
|
|
@ -289,5 +289,31 @@ MACRO(CHECK_LIBRARIES)
|
|||
|
||||
ENDIF(OPTION_3RDPARTY_SOLID)
|
||||
|
||||
# SQLITE3
|
||||
IF(OPTION_3RDPARTY_SQLITE3)
|
||||
|
||||
Find_Package(SQLITE3)
|
||||
IF(SQLITE3_FOUND)
|
||||
SET(HAVE_LIBSQLITE3 1)
|
||||
MESSAGE(STATUS "Looking for library SQLITE3 - found")
|
||||
ELSE(SQLITE3_FOUND)
|
||||
MESSAGE(STATUS "Looking for library SQLITE3 - NOT found")
|
||||
ENDIF(SQLITE3_FOUND)
|
||||
|
||||
ENDIF(OPTION_3RDPARTY_SQLITE3)
|
||||
|
||||
# SQLITE3
|
||||
IF(OPTION_3RDPARTY_SQLITE3)
|
||||
|
||||
Find_Package(SQLITE3)
|
||||
IF(SQLITE3_FOUND)
|
||||
SET(HAVE_LIBSQLITE3 1)
|
||||
MESSAGE(STATUS "Looking for library SQLITE3 - found")
|
||||
ELSE(SQLITE3_FOUND)
|
||||
MESSAGE(STATUS "Looking for library SQLITE3 - NOT found")
|
||||
ENDIF(SQLITE3_FOUND)
|
||||
|
||||
ENDIF(OPTION_3RDPARTY_SQLITE3)
|
||||
|
||||
ENDMACRO(CHECK_LIBRARIES)
|
||||
|
||||
|
|
|
@ -125,6 +125,11 @@ MACRO(_FIND_3RDPARTY_DEPENDENCIES ROOT_DIR)
|
|||
|
||||
# ENet.
|
||||
_FIND_3RDPARTY_DEPENDENCY(ENET enet/enet.h "" enet ${ROOT_DIR} "")
|
||||
|
||||
# SQlite.
|
||||
IF(OPTION_3RDPARTY_SQLITE3)
|
||||
_FIND_3RDPARTY_DEPENDENCY(SQLITE3 sqlite3.h "" sqlite3 ${ROOT_DIR} "")
|
||||
ENDIF(OPTION_3RDPARTY_SQLITE3)
|
||||
|
||||
# OpenSceneGraph
|
||||
IF(OPTION_OSGGRAPH)
|
||||
|
|
|
@ -153,16 +153,16 @@ MACRO(ADD_SDLIB_INCLUDEDIR)
|
|||
FIND_PATH(SDLIB_NETWORKING_INCLUDE_DIR network.h PATHS ${INCLUDE_CANDIDATE} /usr/include /usr/local/include)
|
||||
MARK_AS_ADVANCED(SDLIB_NETWORKING_INCLUDE_DIR)
|
||||
SET(SDLIB_EXTRA_INCLUDEDIR SDLIB_NETWORKING_INCLUDE_DIR)
|
||||
ELSEIF(SDLIB_LIB STREQUAL "raceengine")
|
||||
ELSEIF(SDLIB_LIB STREQUAL "standardgame")
|
||||
IF(IN_SOURCETREE)
|
||||
SET(INCLUDE_CANDIDATE ${SOURCE_DIR}/src/libs/raceengine)
|
||||
SET(INCLUDE_CANDIDATE ${SOURCE_DIR}/src/modules/racing/standardgame)
|
||||
ELSE(IN_SOURCETREE)
|
||||
SET(INCLUDE_CANDIDATE ${SD_INCLUDEDIR_ABS})
|
||||
ENDIF(IN_SOURCETREE)
|
||||
FIND_PATH(SDLIB_RACEENGINE_INCLUDE_DIR raceengine.h PATHS ${INCLUDE_CANDIDATE} /usr/include /usr/local/include NO_DEFAULT_PATH)
|
||||
FIND_PATH(SDLIB_RACEENGINE_INCLUDE_DIR raceengine.h PATHS ${INCLUDE_CANDIDATE} /usr/include /usr/local/include)
|
||||
MARK_AS_ADVANCED(SDLIB_RACEENGINE_INCLUDE_DIR)
|
||||
SET(SDLIB_EXTRA_INCLUDEDIR SDLIB_RACEENGINE_INCLUDE_DIR)
|
||||
FIND_PATH(SDLIB_STANDARDGAME_INCLUDE_DIR standardgame.h PATHS ${INCLUDE_CANDIDATE} /usr/include /usr/local/include NO_DEFAULT_PATH)
|
||||
FIND_PATH(SDLIB_STANDARDGAME_INCLUDE_DIR standardgame.h PATHS ${INCLUDE_CANDIDATE} /usr/include /usr/local/include)
|
||||
MARK_AS_ADVANCED(SDLIB_STANDARDGAME_INCLUDE_DIR)
|
||||
SET(SDLIB_EXTRA_INCLUDEDIR SDLIB_STANDARDGAME_INCLUDE_DIR)
|
||||
ELSE(SDLIB_LIB STREQUAL "portability")
|
||||
SET(SDLIB_FOUND_LIB FALSE)
|
||||
IF(NOT SDLIB_LIB STREQUAL "OPTIONAL")
|
||||
|
@ -300,14 +300,14 @@ MACRO(ADD_SDLIB_LIBRARY TARGET)
|
|||
ENDIF(IN_SOURCETREE)
|
||||
FIND_LIBRARY(SDLIB_NETWORKING_LIBRARY networking PATHS ${LIBRARY_CANDIDATE} /usr/lib /usr/local/lib PATH_SUFFIXES "" lib)
|
||||
SET(SDLIB_EXTRA_LIBRARY SDLIB_NETWORKING_LIBRARY)
|
||||
ELSEIF(SDLIB_LIB STREQUAL "raceengine")
|
||||
ELSEIF(SDLIB_LIB STREQUAL "standardgame")
|
||||
IF(IN_SOURCETREE)
|
||||
SET(LIBRARY_CANDIDATE ${SOURCE_DIR}/src/libs/raceengine)
|
||||
SET(LIBRARY_CANDIDATE ${SOURCE_DIR}/src/modules/racing/standardgame)
|
||||
ELSE(IN_SOURCETREE)
|
||||
SET(LIBRARY_CANDIDATE ${SD_LIBDIR_ABS})
|
||||
ENDIF(IN_SOURCETREE)
|
||||
FIND_LIBRARY(SDLIB_RACEENGINE_LIBRARY raceengine PATHS ${LIBRARY_CANDIDATE} /usr/lib /usr/local/lib PATH_SUFFIXES "" lib)
|
||||
SET(SDLIB_EXTRA_LIBRARY SDLIB_RACEENGINE_LIBRARY)
|
||||
FIND_LIBRARY(SDLIB_STANDARDGAME_LIBRARY standardgame PATHS ${LIBRARY_CANDIDATE} /usr/lib /usr/local/lib PATH_SUFFIXES "" lib)
|
||||
SET(SDLIB_EXTRA_LIBRARY SDLIB_STANDARDGAME_LIBRARY)
|
||||
ELSEIF(SDLIB_LIB STREQUAL "legacymenu")
|
||||
IF(IN_SOURCETREE)
|
||||
SET(LIBRARY_CANDIDATE ${SOURCE_DIR}/src/modules/userinterface/legacymenu)
|
||||
|
|
|
@ -74,6 +74,10 @@ MACRO(ADD_SD_COMPILE_OPTIONS)
|
|||
|
||||
SET(OPTION_3RDPARTY_EXPAT true CACHE BOOL "Use 3rd party Expat library rather than bundled TXML")
|
||||
|
||||
SET(OPTION_3RDPARTY_SQLITE3 false CACHE BOOL "Use SQLite3 as database for record/replay")
|
||||
|
||||
SET(OPTION_3RDPARTY_SQLITE3 false CACHE BOOL "Use SQLite3 as database for record/replay")
|
||||
|
||||
# Enable building with 3rd party SOLID library under Windows, as we ship the binary package,
|
||||
# but not under Linux, where FreeSolid seems not to be available by default on most distros.
|
||||
IF(WIN32)
|
||||
|
@ -150,6 +154,14 @@ MACRO(ADD_SD_COMPILE_OPTIONS)
|
|||
ADD_DEFINITIONS(-DTHIRD_PARTY_EXPAT)
|
||||
ENDIF(OPTION_3RDPARTY_EXPAT)
|
||||
|
||||
IF(OPTION_3RDPARTY_SQLITE3)
|
||||
ADD_DEFINITIONS(-DTHIRD_PARTY_SQLITE3)
|
||||
ENDIF(OPTION_3RDPARTY_SQLITE3)
|
||||
|
||||
IF(OPTION_3RDPARTY_SQLITE3)
|
||||
ADD_DEFINITIONS(-DTHIRD_PARTY_SQLITE3)
|
||||
ENDIF(OPTION_3RDPARTY_SQLITE3)
|
||||
|
||||
IF(OPTION_3RDPARTY_SOLID)
|
||||
ADD_DEFINITIONS(-DTHIRD_PARTY_SOLID)
|
||||
ENDIF(OPTION_3RDPARTY_SOLID)
|
||||
|
|
|
@ -20,6 +20,54 @@
|
|||
# @author Mart Kelder, J.-P. Meuret
|
||||
# @version $Id$
|
||||
|
||||
MACRO(ADD_SQLITE3_INCLUDEDIR)
|
||||
|
||||
FIND_PACKAGE(SQLITE3)
|
||||
|
||||
IF(SQLITE3_FOUND)
|
||||
INCLUDE_DIRECTORIES(${SQLITE3_INCLUDE_DIR})
|
||||
ELSE(SQLITE3_FOUND)
|
||||
MESSAGE(FATAL_ERROR "Cannot find SQLITE3 header files")
|
||||
ENDIF(SQLITE3_FOUND)
|
||||
|
||||
ENDMACRO(ADD_SQLITE3_INCLUDEDIR)
|
||||
|
||||
MACRO(ADD_SQLITE3_LIBRARY TARGET)
|
||||
|
||||
FIND_PACKAGE(SQLITE3)
|
||||
|
||||
IF(SQLITE3_FOUND)
|
||||
TARGET_LINK_LIBRARIES(${TARGET} ${SQLITE3_LIBRARY})
|
||||
ELSE(SQLITE3_FOUND)
|
||||
MESSAGE(FATAL_ERROR "Cannot find SQLITE3 libraries")
|
||||
ENDIF(SQLITE3_FOUND)
|
||||
|
||||
ENDMACRO(ADD_SQLITE3_LIBRARY TARGET)
|
||||
|
||||
MACRO(ADD_SQLITE3_INCLUDEDIR)
|
||||
|
||||
FIND_PACKAGE(SQLITE3)
|
||||
|
||||
IF(SQLITE3_FOUND)
|
||||
INCLUDE_DIRECTORIES(${SQLITE3_INCLUDE_DIR})
|
||||
ELSE(SQLITE3_FOUND)
|
||||
MESSAGE(FATAL_ERROR "Cannot find SQLITE3 header files")
|
||||
ENDIF(SQLITE3_FOUND)
|
||||
|
||||
ENDMACRO(ADD_SQLITE3_INCLUDEDIR)
|
||||
|
||||
MACRO(ADD_SQLITE3_LIBRARY TARGET)
|
||||
|
||||
FIND_PACKAGE(SQLITE3)
|
||||
|
||||
IF(SQLITE3_FOUND)
|
||||
TARGET_LINK_LIBRARIES(${TARGET} ${SQLITE3_LIBRARY})
|
||||
ELSE(SQLITE3_FOUND)
|
||||
MESSAGE(FATAL_ERROR "Cannot find SQLITE3 libraries")
|
||||
ENDIF(SQLITE3_FOUND)
|
||||
|
||||
ENDMACRO(ADD_SQLITE3_LIBRARY TARGET)
|
||||
|
||||
MACRO(ADD_PLIB_INCLUDEDIR)
|
||||
|
||||
FIND_PACKAGE(PLIB)
|
||||
|
|
|
@ -166,6 +166,27 @@
|
|||
<attstr name="pushed image" val="data/img/button-left-pushed.png"/>
|
||||
</section>
|
||||
|
||||
<section name="ReplayButton">
|
||||
<attstr name="type" val="text button"/>
|
||||
<attstr name="show box" val="no"/>
|
||||
<attstr name="text" val="Replay"/>
|
||||
<attstr name="tip" val="View a replay of the race"/>
|
||||
<attstr name="h align" val="left"/>
|
||||
<attnum name="x" val="160"/>
|
||||
<attnum name="y" val="44"/>
|
||||
<attnum name="width" val="150"/>
|
||||
<attstr name="font" val="medium"/>
|
||||
<attstr name="color" val="0xFFFFFF"/>
|
||||
<attstr name="focused color" val="0xFFFFFF"/>
|
||||
<attstr name="pushed color" val="0xFFFFFF"/>
|
||||
<attnum name="image x" val="-10"/>
|
||||
<attnum name="image y" val="4"/>
|
||||
<attnum name="image width" val="60"/>
|
||||
<attnum name="image height" val="16"/>
|
||||
<attstr name="focused image" val="data/img/button-left-focused.png"/>
|
||||
<attstr name="enabled image" val="data/img/button-left.png"/>
|
||||
<attstr name="pushed image" val="data/img/button-left-pushed.png"/>
|
||||
</section>
|
||||
<!--
|
||||
<section name="SaveButton">
|
||||
<attstr name="type" val="text button"/>
|
||||
|
|
|
@ -205,6 +205,28 @@
|
|||
<attstr name="pushed image" val="data/img/button-left-pushed.png"/>
|
||||
</section>
|
||||
|
||||
<section name="ReplayButton">
|
||||
<attstr name="type" val="text button"/>
|
||||
<attstr name="show box" val="no"/>
|
||||
<attstr name="text" val="Replay"/>
|
||||
<attstr name="tip" val="View a replay of the race"/>
|
||||
<attstr name="h align" val="left"/>
|
||||
<attnum name="x" val="160"/>
|
||||
<attnum name="y" val="44"/>
|
||||
<attnum name="width" val="150"/>
|
||||
<attstr name="font" val="medium"/>
|
||||
<attstr name="color" val="0xFFFFFF"/>
|
||||
<attstr name="focused color" val="0xFFFFFF"/>
|
||||
<attstr name="pushed color" val="0xFFFFFF"/>
|
||||
<attnum name="image x" val="-10"/>
|
||||
<attnum name="image y" val="4"/>
|
||||
<attnum name="image width" val="60"/>
|
||||
<attnum name="image height" val="16"/>
|
||||
<attstr name="focused image" val="data/img/button-left-focused.png"/>
|
||||
<attstr name="enabled image" val="data/img/button-left.png"/>
|
||||
<attstr name="pushed image" val="data/img/button-left-pushed.png"/>
|
||||
</section>
|
||||
|
||||
<!--
|
||||
<section name="SaveButton">
|
||||
<attstr name="type" val="text button"/>
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
|
||||
<section name="simulabel">
|
||||
<attstr name="type" val="label"/>
|
||||
<attnum name="max len" val="5"/>
|
||||
<attnum name="max len" val="6"/>
|
||||
<attstr name="tip" val="Choose your simulation engine (Warning: Physics setups designed only for V2.1 and V4.0)"/>
|
||||
<attnum name="x" val="295"/>
|
||||
<attnum name="y" val="322"/>
|
||||
|
@ -139,6 +139,44 @@
|
|||
<attstr name="font" val="medium"/>
|
||||
</section>
|
||||
|
||||
<section name="replayrateleftarrow">
|
||||
<attstr name="type" val="image button"/>
|
||||
<attnum name="width" val="24"/>
|
||||
<attnum name="height" val="24"/>
|
||||
<attstr name="tip" val=""/>
|
||||
<attnum name="x" val="265"/>
|
||||
<attnum name="y" val="228"/>
|
||||
<attstr name="disabled image" val="data/img/arrow-left-top-disabled.png"/>
|
||||
<attstr name="enabled image" val="data/img/arrow-left-top.png"/>
|
||||
<attstr name="focused image" val="data/img/arrow-left-top-focused.png"/>
|
||||
<attstr name="pushed image" val="data/img/arrow-left-top-pushed.png"/>
|
||||
</section>
|
||||
|
||||
<section name="replayraterightarrow">
|
||||
<attstr name="type" val="image button"/>
|
||||
<attnum name="width" val="24"/>
|
||||
<attnum name="height" val="24"/>
|
||||
<attstr name="tip" val=""/>
|
||||
<attnum name="x" val="465"/>
|
||||
<attnum name="y" val="228"/>
|
||||
<attstr name="disabled image" val="data/img/arrow-right-top-disabled.png"/>
|
||||
<attstr name="enabled image" val="data/img/arrow-right-top.png"/>
|
||||
<attstr name="focused image" val="data/img/arrow-right-top-focused.png"/>
|
||||
<attstr name="pushed image" val="data/img/arrow-right-top-pushed.png"/>
|
||||
</section>
|
||||
|
||||
<section name="replayratelabel">
|
||||
<attstr name="type" val="label"/>
|
||||
<attnum name="max len" val="8"/>
|
||||
<attstr name="tip" val="Determines the quality (and size) of the replay file"/>
|
||||
<attnum name="x" val="295"/>
|
||||
<attnum name="y" val="232"/>
|
||||
<attnum name="width" val="160"/>
|
||||
<attstr name="h align" val="center"/>
|
||||
<attstr name="color" val="0xFFFFFF"/>
|
||||
<attstr name="font" val="medium"/>
|
||||
</section>
|
||||
|
||||
<section name="CancelButton">
|
||||
<attstr name="type" val="text button"/>
|
||||
<attstr name="show box" val="no"/>
|
||||
|
@ -240,6 +278,16 @@
|
|||
<attstr name="font" val="small_t"/>
|
||||
</section>
|
||||
|
||||
<section name="7">
|
||||
<attstr name="type" val="label"/>
|
||||
<attnum name="x" val="20"/>
|
||||
<attnum name="y" val="232"/>
|
||||
<attstr name="text" val="Replay Quality:"/>
|
||||
<attstr name="h align" val="right"/>
|
||||
<attnum name="width" val="220"/>
|
||||
<attstr name="font" val="small_t"/>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
</params>
|
||||
|
|
|
@ -6,6 +6,7 @@ SD_ADD_SUBDIRECTORY(kilo2008)
|
|||
SD_ADD_SUBDIRECTORY(networkhuman)
|
||||
SD_ADD_SUBDIRECTORY(simplix)
|
||||
SD_ADD_SUBDIRECTORY(usr)
|
||||
SD_ADD_SUBDIRECTORY(replay)
|
||||
|
||||
# Work-in-progress / unofficial robots.
|
||||
IF(NOT OPTION_OFFICIAL_ONLY)
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
INCLUDE(../../../cmake/macros.cmake)
|
||||
|
||||
SET(ROBOT_NAME "replay")
|
||||
|
||||
SET(ROBOT_SOURCES ${ROBOT_NAME}.cpp)
|
||||
|
||||
ROBOT_MODULE(NAME ${ROBOT_NAME} VERSION 1.0.0 SOVERSION 1.0.0
|
||||
INTERFACE LEGACY_MIN
|
||||
SOURCES ${ROBOT_SOURCES})
|
||||
|
||||
# For data associated to the robot module, see data/drivers/hymie/CMakeLists.txt
|
|
@ -0,0 +1,137 @@
|
|||
/***************************************************************************
|
||||
|
||||
file : replay.cpp
|
||||
created : Wed Jan 8 18:31:16 CET 2003
|
||||
copyright : (C) 2007 Andrew Sumner, 2002-2004 Bernhard Wymann
|
||||
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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <tgf.h>
|
||||
#include <track.h>
|
||||
#include <car.h>
|
||||
#include <raceman.h>
|
||||
#include <robottools.h>
|
||||
#include <robot.h>
|
||||
|
||||
#define BUFSIZE 20
|
||||
#define NBBOTS 10
|
||||
|
||||
static char const* botname[] = {
|
||||
"RP: Replay 1",
|
||||
"RP: Replay 2",
|
||||
"RP: Replay 3",
|
||||
"RP: Replay 4",
|
||||
"RP: Replay 5",
|
||||
"RP: Replay 6",
|
||||
"RP: Replay 7",
|
||||
"RP: Replay 8",
|
||||
"RP: Replay 9",
|
||||
"RP: Replay 10"
|
||||
};
|
||||
|
||||
static void initTrack(int index, tTrack* track, void *carHandle, void **carParmHandle, tSituation *s);
|
||||
static void newRace(int index, tCarElt* car, tSituation *s);
|
||||
static void drive(int index, tCarElt* car, tSituation *s);
|
||||
static int pitcmd(int index, tCarElt* car, tSituation *s);
|
||||
static void shutdown(int index);
|
||||
static int InitFuncPt(int index, void *pt);
|
||||
static void endRace(int index, tCarElt *car, tSituation *s);
|
||||
|
||||
|
||||
// Module entry point.
|
||||
extern "C" int replay(tModInfo *modInfo)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Clear all structures.
|
||||
memset(modInfo, 0, NBBOTS*sizeof(tModInfo));
|
||||
|
||||
for (i = 0; i < NBBOTS; i++) {
|
||||
modInfo[i].name = botname[i]; // name of the module (short).
|
||||
modInfo[i].desc = botname[i]; // Description of the module (can be long).
|
||||
modInfo[i].fctInit = InitFuncPt; // Init function.
|
||||
modInfo[i].gfId = ROB_IDENT; // Supported framework version.
|
||||
modInfo[i].index = i+1; // Indices from 0 to 9.
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Module interface initialization.
|
||||
static int InitFuncPt(int index, void *pt)
|
||||
{
|
||||
tRobotItf *itf = (tRobotItf *)pt;
|
||||
|
||||
// Create robot instance for index.
|
||||
itf->rbNewTrack = initTrack; // Give the robot the track view called.
|
||||
itf->rbNewRace = newRace; // Start a new race.
|
||||
itf->rbDrive = drive; // Drive during race.
|
||||
itf->rbPitCmd = pitcmd; // Pit commands.
|
||||
itf->rbEndRace = endRace; // End of the current race.
|
||||
itf->rbShutdown = shutdown; // Called before the module is unloaded.
|
||||
itf->index = index; // Index used if multiple interfaces.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Called for every track change or new race.
|
||||
static void initTrack(int index, tTrack* track, void *carHandle, void **carParmHandle, tSituation *s)
|
||||
{
|
||||
//driver[index-1]->initTrack(track, carHandle, carParmHandle, s);
|
||||
}
|
||||
|
||||
|
||||
// Start a new race.
|
||||
static void newRace(int index, tCarElt* car, tSituation *s)
|
||||
{
|
||||
//driver[index-1]->newRace(car, s);
|
||||
}
|
||||
|
||||
|
||||
// Drive during race.
|
||||
static void drive(int index, tCarElt* car, tSituation *s)
|
||||
{
|
||||
//driver[index-1]->drive(s);
|
||||
}
|
||||
|
||||
|
||||
// Pitstop callback.
|
||||
static int pitcmd(int index, tCarElt* car, tSituation *s)
|
||||
{
|
||||
//return driver[index-1]->pitCommand(s);
|
||||
}
|
||||
|
||||
|
||||
// End of the current race.
|
||||
static void endRace(int index, tCarElt *car, tSituation *s)
|
||||
{
|
||||
//driver[index-1]->endRace(s);
|
||||
}
|
||||
|
||||
|
||||
// Called before the module is unloaded.
|
||||
static void shutdown(int index)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -177,6 +177,7 @@ typedef struct {
|
|||
double curTime;
|
||||
tdble topSpeed;
|
||||
int laps;
|
||||
int bestLap;
|
||||
int nbPitStops;
|
||||
int remainingLaps;
|
||||
int pos;
|
||||
|
@ -204,6 +205,7 @@ typedef struct {
|
|||
#define _curTime race.curTime
|
||||
#define _topSpeed race.topSpeed
|
||||
#define _laps race.laps
|
||||
#define _bestLap race.bestLap
|
||||
#define _nbPitStops race.nbPitStops
|
||||
#define _remainingLaps race.remainingLaps
|
||||
#define _pos race.pos
|
||||
|
|
|
@ -416,15 +416,25 @@ typedef struct RmInfo
|
|||
#define RM_VAL_MOD_SIMU_V2_1 "simuv2.1"
|
||||
#define RM_VAL_MOD_SIMU_V3 "simuv3"
|
||||
#define RM_VAL_MOD_SIMU_V4 "simuv4"
|
||||
#define RM_VAL_MOD_SIMU_REPLAY "simureplay"
|
||||
#define RM_VAL_MOD_TRACK "track"
|
||||
#define RM_VAL_MOD_SSGRAPH "ssggraph"
|
||||
|
||||
/* Replay Settings */
|
||||
|
||||
#define RM_VAL_REPLAY_OFF "0"
|
||||
#define RM_VAL_REPLAY_LOW "2"
|
||||
#define RM_VAL_REPLAY_NORMAL "10"
|
||||
#define RM_VAL_REPLAY_HIGH "30"
|
||||
#define RM_VAL_REPLAY_PERFECT "100"
|
||||
|
||||
/* Race Engine itself */
|
||||
|
||||
#define RM_SECT_RACE_ENGINE "Race Engine"
|
||||
|
||||
#define RM_ATTR_MULTI_THREADING "multi-threading"
|
||||
#define RM_ATTR_THREAD_AFFINITY "thread affinity"
|
||||
#define RM_ATTR_REPLAY_RATE "replay rate"
|
||||
|
||||
#define RM_VAL_AUTO "auto"
|
||||
#define RM_VAL_ON "on"
|
||||
|
|
|
@ -23,7 +23,37 @@
|
|||
|
||||
#define RPL_IDENT 0
|
||||
|
||||
#include <car.h>
|
||||
|
||||
#define REPLAY_TIMESTEP 2 // 2Hz Data logging
|
||||
#define REPLAY_CHUNK 100
|
||||
|
||||
typedef struct ReplayElt
|
||||
{
|
||||
double currentTime;
|
||||
tInitCar info; /**< public */
|
||||
tPublicCar pub; /**< public */
|
||||
tCarRaceInfo race; /**< public */
|
||||
tPrivCar priv; /**< private */
|
||||
tCarCtrl ctrl; /**< private */
|
||||
tCarPitCmd pitcmd; /**< private */
|
||||
} tReplayElt;
|
||||
|
||||
extern int replayRecord;
|
||||
extern int replayReplay;
|
||||
extern double replayTimestamp;
|
||||
|
||||
extern int ghostcarActive;
|
||||
extern double ghostcarTimeOffset;
|
||||
extern tReplayElt curGhostcarData, nextGhostcarData;
|
||||
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
#include <sqlite3.h>
|
||||
|
||||
extern sqlite3 *replayDB;
|
||||
extern sqlite3_stmt *replayBlobs[50]; // Hard coded 50 car limit to race
|
||||
extern sqlite3_stmt *ghostcarBlob;
|
||||
#endif
|
||||
|
||||
#endif /* __REPLAYV1_H__ */
|
||||
|
||||
|
|
|
@ -238,12 +238,23 @@ void ReSituationUpdater::runOneStep(double deltaTimeIncrement)
|
|||
}
|
||||
|
||||
// Update times.
|
||||
pCurrReInfo->_reCurTime += deltaTimeIncrement * pCurrReInfo->_reTimeMult; /* "Real" time */
|
||||
pCurrReInfo->_reCurTime += deltaTimeIncrement * fabs(pCurrReInfo->_reTimeMult); /* "Real" time */
|
||||
#if 0
|
||||
s->currentTime += deltaTimeIncrement; /* Simulated time */
|
||||
#else
|
||||
if (pCurrReInfo->_reTimeMult > 0)
|
||||
s->currentTime += deltaTimeIncrement;
|
||||
else
|
||||
s->currentTime -= deltaTimeIncrement;
|
||||
#endif
|
||||
|
||||
if (s->currentTime < 0) {
|
||||
/* no simu yet */
|
||||
pCurrReInfo->s->_raceState = RM_RACE_PRESTART;
|
||||
if (pCurrReInfo->_reTimeMult < 0)
|
||||
/* Revert to forward time x1 */
|
||||
pCurrReInfo->_reTimeMult = 1;
|
||||
else
|
||||
/* no simu yet */
|
||||
pCurrReInfo->s->_raceState = RM_RACE_PRESTART;
|
||||
} else if (pCurrReInfo->s->_raceState == RM_RACE_PRESTART) {
|
||||
pCurrReInfo->s->_raceState = RM_RACE_RUNNING;
|
||||
s->currentTime = 0.0; /* resynchronize */
|
||||
|
|
|
@ -23,6 +23,10 @@ ADD_SDLIB_INCLUDEDIR(math portability robottools tgf tgfdata networking)
|
|||
ADD_PLIB_INCLUDEDIR()
|
||||
ADD_SDL_INCLUDEDIR()
|
||||
|
||||
IF(OPTION_3RDPARTY_SQLITE3)
|
||||
ADD_SQLITE3_INCLUDEDIR()
|
||||
ENDIF(OPTION_3RDPARTY_SQLITE3)
|
||||
|
||||
# Disable developer warning
|
||||
IF (COMMAND CMAKE_POLICY)
|
||||
CMAKE_POLICY(SET CMP0003 NEW)
|
||||
|
@ -46,4 +50,8 @@ SD_ADD_LIBRARY(standardgame MODULE ${_SOURCES} ${_HEADERS} ${_OTHER_SOURCES})
|
|||
|
||||
ADD_SDLIB_LIBRARY(standardgame portability tgf tgfdata robottools networking)
|
||||
|
||||
IF(OPTION_3RDPARTY_SQLITE3)
|
||||
ADD_SQLITE3_LIBRARY(standardgame)
|
||||
ENDIF(OPTION_3RDPARTY_SQLITE3)
|
||||
|
||||
SD_INSTALL_FILES(LIB modules/racing TARGETS standardgame)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <robot.h>
|
||||
#include <robottools.h>
|
||||
#include <teammanager.h>
|
||||
#include <replay.h>
|
||||
|
||||
#include "standardgame.h"
|
||||
|
||||
|
@ -39,6 +40,12 @@
|
|||
#include "raceresults.h"
|
||||
#include "racecars.h"
|
||||
|
||||
int ghostcarActive;
|
||||
double ghostcarTimeOffset;
|
||||
tReplayElt curGhostcarData, nextGhostcarData;
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
sqlite3_stmt *ghostcarBlob;
|
||||
#endif
|
||||
|
||||
/* Compute Pit stop time */
|
||||
void
|
||||
|
@ -166,6 +173,7 @@ reCarsApplyRaceRules(tCarElt *car)
|
|||
// 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))
|
||||
|
@ -560,7 +568,9 @@ ReCarsManageCar(tCarElt *car, bool& bestLapChanged)
|
|||
}
|
||||
if ((car->_lastLapTime < car->_bestLapTime) || (car->_bestLapTime == 0)) {
|
||||
car->_bestLapTime = car->_lastLapTime;
|
||||
car->_bestLap = car->_laps - 1;
|
||||
memcpy(car->_bestSplitTime, car->_curSplitTime, sizeof(double)*(ReInfo->track->numberOfSectors - 1) );
|
||||
|
||||
if (s->_raceType != RM_TYPE_RACE && s->_ncars > 1)
|
||||
{
|
||||
/* Best lap time is made better : update times behind leader */
|
||||
|
@ -677,6 +687,34 @@ ReCarsManageCar(tCarElt *car, bool& bestLapChanged)
|
|||
return;
|
||||
}
|
||||
|
||||
#if 0 //def THIRD_PARTY_SQLITE3
|
||||
// Re-read the best lap for ghostcar
|
||||
if (replayDB != NULL && car->_bestLap) {
|
||||
char command[200];
|
||||
int result;
|
||||
|
||||
GfLogInfo("Re-reading best lap\n");
|
||||
sprintf(command, "SELECT datablob FROM car0 where lap=%d", car->_bestLap);
|
||||
result = sqlite3_prepare_v2(replayDB, command, -1, &ghostcarBlob, 0);
|
||||
|
||||
if (result) {
|
||||
GfLogInfo("Unable to read ghostlap %d: %s\n", car->_bestLap, sqlite3_errmsg(replayDB));
|
||||
} else {
|
||||
// read the first 2 records
|
||||
result = sqlite3_step(ghostcarBlob);
|
||||
if (result == SQLITE_ROW) {
|
||||
memcpy(&curGhostcarData, sqlite3_column_blob(ghostcarBlob, 0), sizeof(tReplayElt));
|
||||
}
|
||||
result = sqlite3_step(ghostcarBlob);
|
||||
if (result == SQLITE_ROW) {
|
||||
memcpy(&nextGhostcarData, sqlite3_column_blob(ghostcarBlob, 0), sizeof(tReplayElt));
|
||||
}
|
||||
|
||||
ghostcarTimeOffset = s->currentTime - curGhostcarData.currentTime;
|
||||
ghostcarActive = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
info->lapFlag--;
|
||||
}
|
||||
|
|
|
@ -28,10 +28,15 @@
|
|||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
#include <sqlite3.h>
|
||||
#endif
|
||||
|
||||
#include <raceman.h>
|
||||
#include <robot.h>
|
||||
#include <teammanager.h>
|
||||
#include <robottools.h>
|
||||
#include <replay.h>
|
||||
|
||||
#include <portability.h>
|
||||
#include <tgf.hpp>
|
||||
|
@ -61,6 +66,13 @@ tModList *ReRacingRobotsModList = 0;
|
|||
// The race situation
|
||||
tRmInfo *ReInfo = 0;
|
||||
|
||||
int replayRecord;
|
||||
double replayTimestamp;
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
sqlite3 *replayDB;
|
||||
sqlite3_stmt *replayBlobs[50];
|
||||
#endif
|
||||
|
||||
// Race Engine reset
|
||||
void
|
||||
ReReset(void)
|
||||
|
@ -463,7 +475,13 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
|
|||
|
||||
/* good robot found */
|
||||
curModInfo = &((*(ReInfo->robModList))->modInfo[modindex]);
|
||||
GfLogInfo("Driver's name: %s\n", curModInfo->name);
|
||||
|
||||
#if 0 //SDW
|
||||
if (replayReplay)
|
||||
GfLogInfo("Driver in car %d being driven by replay\n", carindex);
|
||||
else
|
||||
#endif
|
||||
GfLogInfo("Driver's name: %s\n", curModInfo->name);
|
||||
|
||||
isHuman = strcmp( cardllname, "human" ) == 0 || strcmp( cardllname, "networkhuman" ) == 0;
|
||||
|
||||
|
@ -475,7 +493,14 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
|
|||
curRobot = (tRobotItf*)calloc(1, sizeof(tRobotItf));
|
||||
|
||||
/* ... and initialize the driver */
|
||||
#if 0 // SDW
|
||||
if (replayReplay) {
|
||||
// Register against the Replay driver (which does nothing)
|
||||
curModInfo->fctInit(carindex, (void*)(curRobot));
|
||||
} else if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) {
|
||||
#else
|
||||
if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) {
|
||||
#endif
|
||||
curModInfo->fctInit(robotIdx, (void*)(curRobot));
|
||||
} else {
|
||||
curRobot->rbNewTrack = NULL;
|
||||
|
@ -650,7 +675,7 @@ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int
|
|||
}
|
||||
else
|
||||
handle = NULL;
|
||||
if (handle) {
|
||||
if (handle && !replayReplay) {
|
||||
GfLogTrace("Checking/Merging %s specific setup into %s setup.\n",
|
||||
curModInfo->name, elt->_carName);
|
||||
if (GfParmCheckHandle(carhdle, handle)) {
|
||||
|
@ -728,7 +753,14 @@ ReInitCars(void)
|
|||
snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS_RACING, i);
|
||||
robotModuleName = GfParmGetStr(ReInfo->params, path, RM_ATTR_MODULE, "");
|
||||
robotIdx = (int)GfParmGetNum(ReInfo->params, path, RM_ATTR_IDX, NULL, 0);
|
||||
snprintf(path, sizeof(path), "%sdrivers/%s/%s.%s", GfLibDir(), robotModuleName, robotModuleName, DLLEXT);
|
||||
|
||||
#if 0 // SDW
|
||||
if (replayReplay)
|
||||
// Register against the Replay driver
|
||||
snprintf(path, sizeof(path), "%sdrivers/replay/replay.%s", GfLibDir(), DLLEXT);
|
||||
else
|
||||
#endif
|
||||
snprintf(path, sizeof(path), "%sdrivers/%s/%s.%s", GfLibDir(), robotModuleName, robotModuleName, DLLEXT);
|
||||
|
||||
/* Load the robot shared library */
|
||||
if (GfModLoad(CAR_IDENT, path, ReInfo->robModList))
|
||||
|
@ -805,13 +837,91 @@ ReInitCars(void)
|
|||
GfLogInfo("%d driver(s) ready to race\n", nCars);
|
||||
}
|
||||
|
||||
if (replayReplay)
|
||||
replayRecord = 0;
|
||||
else {
|
||||
char buf[1024];
|
||||
const char *replayRateSchemeName;
|
||||
snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG);
|
||||
|
||||
void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
|
||||
replayRateSchemeName = GfParmGetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_REPLAY_RATE, "0");
|
||||
GfParmReleaseHandle(paramHandle);
|
||||
|
||||
replayRecord = atoi(replayRateSchemeName);
|
||||
}
|
||||
|
||||
if (replayRecord || replayReplay) {
|
||||
int result;
|
||||
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
result = sqlite3_open("/tmp/race.sqlite", &replayDB);
|
||||
if (result) {
|
||||
GfLogError("Replay: Unable to open Database: %s\n", sqlite3_errmsg(replayDB));
|
||||
sqlite3_close(replayDB);
|
||||
replayDB = NULL;
|
||||
} else {
|
||||
GfLogInfo("Replay: Database Opened 0x8%8.8X\n", replayDB);
|
||||
|
||||
if (replayRecord)
|
||||
GfLogInfo("Replay: Record Timestep = %f\n", 1/(float)replayRecord);
|
||||
|
||||
if (replayReplay)
|
||||
GfLogInfo("Replay: Playback from file\n");
|
||||
|
||||
/* speed up database by turning of synchronous behaviour/etc */
|
||||
sqlite3_exec(replayDB, "PRAGMA synchronous = OFF", NULL, NULL, NULL);
|
||||
sqlite3_exec(replayDB, "PRAGMA journal_mode = OFF", NULL, NULL, NULL);
|
||||
sqlite3_exec(replayDB, "PRAGMA count_changes = OFF", NULL, NULL, NULL);
|
||||
#if 0 // This pragma seems to prevent re-opening the sqlite3 database
|
||||
sqlite3_exec(replayDB, "PRAGMA locking_mode = EXCLUSIVE", NULL, NULL, NULL);
|
||||
#endif
|
||||
sqlite3_exec(replayDB, "PRAGMA default_temp_store = MEMORY", NULL, NULL, NULL);
|
||||
|
||||
//replayBlobs = (sqlite3_stmt *) calloc(nCars, sizeof(void *)); //sqlite3_stmt));
|
||||
|
||||
replayTimestamp = -5;
|
||||
ghostcarActive = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ReInfo->s->_ncars = nCars;
|
||||
FREEZ(ReInfo->s->cars);
|
||||
ReInfo->s->cars = (tCarElt **)calloc(nCars, sizeof(tCarElt *));
|
||||
for (i = 0; i < nCars; i++)
|
||||
{
|
||||
ReInfo->s->cars[i] = &(ReInfo->carList[i]);
|
||||
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
//open a table for each car
|
||||
if (replayDB) {
|
||||
char command[200];
|
||||
int result;
|
||||
|
||||
if (replayRecord) {
|
||||
sprintf(command, "DROP TABLE IF EXISTS car%d", i);
|
||||
result = sqlite3_exec(replayDB, command, 0, 0, 0);
|
||||
if (result) GfLogInfo("Replay: Unable to drop table car%d: %s\n", i, sqlite3_errmsg(replayDB));
|
||||
}
|
||||
|
||||
sprintf(command, "CREATE TABLE IF NOT EXISTS car%d (timestamp, lap, datablob BLOB)", i);
|
||||
result = sqlite3_exec(replayDB, command, 0, 0, 0);
|
||||
if (result) {
|
||||
GfLogInfo("Replay: Unable to create table car%d: %s\n", i, sqlite3_errmsg(replayDB));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (replayReplay) {
|
||||
// Build index to allow faster read access
|
||||
sprintf(command, "CREATE UNIQUE INDEX IF NOT EXISTS index%d ON car%d (timestamp)", i, i);
|
||||
result = sqlite3_exec(replayDB, command, 0, 0, 0);
|
||||
if (result) GfLogInfo("Replay: Unable to create index car%d: %s\n", i, sqlite3_errmsg(replayDB));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ReInfo->_rePitRequester = 0;
|
||||
|
||||
// TODO: reconsider splitting the call into one for cars, track and maybe other objects.
|
||||
|
@ -836,6 +946,15 @@ ReRaceCleanup(void)
|
|||
ReStoreRaceResults(ReInfo->_reRaceName);
|
||||
|
||||
ReRaceCleanDrivers();
|
||||
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
GfLogInfo("Replay: Database closed\n");
|
||||
if (replayDB)
|
||||
sqlite3_close(replayDB);
|
||||
|
||||
replayDB = NULL;
|
||||
#endif
|
||||
replayRecord = 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -124,6 +124,7 @@ static void ReSStCarInit( tCarElt *car )
|
|||
car->_curTime = 0.3f * car->_pos;
|
||||
car->_bestLapTime = 0.0f;
|
||||
car->_laps = 0;
|
||||
car->_bestLap = 0;
|
||||
}
|
||||
|
||||
static tSimuSimuData* ReSSInit()
|
||||
|
@ -196,8 +197,10 @@ static void ReSSStep( SimuSimuData *data )
|
|||
|
||||
//Change structure
|
||||
car->_curTime += laptime;
|
||||
if( car->_bestLapTime > laptime || car->_bestLapTime == 0.0f )
|
||||
if( car->_bestLapTime > laptime || car->_bestLapTime == 0.0f ) {
|
||||
car->_bestLapTime = laptime;
|
||||
car->_bestLap = car->_laps;
|
||||
}
|
||||
++car->_laps;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,15 @@
|
|||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
#include <sqlite3.h>
|
||||
#endif
|
||||
|
||||
#include <portability.h>
|
||||
#include <network.h>
|
||||
#include <robot.h>
|
||||
#include <raceman.h>
|
||||
#include <replay.h>
|
||||
|
||||
#include "standardgame.h"
|
||||
|
||||
|
@ -43,7 +48,6 @@
|
|||
#include "racemessage.h"
|
||||
#include "racenetwork.h"
|
||||
|
||||
|
||||
// The singleton.
|
||||
ReSituation* ReSituation::_pSelf = 0;
|
||||
|
||||
|
@ -157,10 +161,26 @@ void ReSituation::accelerateTime(double fMultFactor)
|
|||
{
|
||||
lock("accelerateTime");
|
||||
|
||||
_pReInfo->_reTimeMult *= fMultFactor;
|
||||
if (_pReInfo->_reTimeMult > 0.0)
|
||||
_pReInfo->_reTimeMult *= fMultFactor;
|
||||
else
|
||||
_pReInfo->_reTimeMult /= fMultFactor;
|
||||
|
||||
if (fMultFactor == 0.0)
|
||||
_pReInfo->_reTimeMult = 1.0;
|
||||
else if (_pReInfo->_reTimeMult > 64.0)
|
||||
else if (replayReplay) {
|
||||
// allow for the reversal of time on replays (note this is divider not multipler)
|
||||
if (_pReInfo->_reTimeMult > 4.0) {
|
||||
GfLogInfo("Reversing Time %f\n", _pReInfo->_reCurTime);
|
||||
_pReInfo->_reTimeMult = -4.0;
|
||||
} else if (_pReInfo->_reTimeMult < -4.0) {
|
||||
GfLogInfo("Correcting Time at %f\n", _pReInfo->_reCurTime);
|
||||
_pReInfo->_reTimeMult = 4.0;
|
||||
} else if (_pReInfo->_reTimeMult > -0.0625 && _pReInfo->_reTimeMult < 0.0)
|
||||
_pReInfo->_reTimeMult = -0.0625;
|
||||
else if (_pReInfo->_reTimeMult < 0.0625 && _pReInfo->_reTimeMult > 0.0)
|
||||
_pReInfo->_reTimeMult = 0.0625;
|
||||
} else if (_pReInfo->_reTimeMult > 64.0)
|
||||
_pReInfo->_reTimeMult = 64.0;
|
||||
else if (_pReInfo->_reTimeMult < 0.0625)
|
||||
_pReInfo->_reTimeMult = 0.0625;
|
||||
|
@ -256,12 +276,20 @@ void ReSituationUpdater::runOneStep(double deltaTimeIncrement)
|
|||
}
|
||||
|
||||
// Update times.
|
||||
pCurrReInfo->_reCurTime += deltaTimeIncrement * pCurrReInfo->_reTimeMult; /* "Real" time */
|
||||
s->currentTime += deltaTimeIncrement; /* Simulated time */
|
||||
pCurrReInfo->_reCurTime += deltaTimeIncrement * fabs(pCurrReInfo->_reTimeMult); /* "Real" time */
|
||||
|
||||
if (pCurrReInfo->_reTimeMult > 0)
|
||||
s->currentTime += deltaTimeIncrement;
|
||||
else
|
||||
s->currentTime -= deltaTimeIncrement;
|
||||
|
||||
if (s->currentTime < 0) {
|
||||
/* no simu yet */
|
||||
pCurrReInfo->s->_raceState = RM_RACE_PRESTART;
|
||||
if (pCurrReInfo->_reTimeMult < 0)
|
||||
/* Revert to forward time x1 */
|
||||
pCurrReInfo->_reTimeMult = 1;
|
||||
else
|
||||
/* no simu yet */
|
||||
pCurrReInfo->s->_raceState = RM_RACE_PRESTART;
|
||||
} else if (pCurrReInfo->s->_raceState == RM_RACE_PRESTART) {
|
||||
pCurrReInfo->s->_raceState = RM_RACE_RUNNING;
|
||||
s->currentTime = 0.0; /* resynchronize */
|
||||
|
@ -297,7 +325,8 @@ void ReSituationUpdater::runOneStep(double deltaTimeIncrement)
|
|||
for (int i = 0; i < s->_ncars; i++) {
|
||||
if ((s->cars[i]->_state & RM_CAR_STATE_NO_SIMU) == 0) {
|
||||
robot = s->cars[i]->robot;
|
||||
robot->rbDrive(robot->index, s->cars[i], s);
|
||||
if (replayReplay == 0)
|
||||
robot->rbDrive(robot->index, s->cars[i], s);
|
||||
}
|
||||
else if (! (s->cars[i]->_state & RM_CAR_STATE_ENDRACE_CALLED ) && ( s->cars[i]->_state & RM_CAR_STATE_OUT ) == RM_CAR_STATE_OUT )
|
||||
{ // No simu, look if it is out
|
||||
|
@ -336,6 +365,10 @@ void ReSituationUpdater::runOneStep(double deltaTimeIncrement)
|
|||
else if (pCurrReInfo->s->_raceType == RM_TYPE_QUALIF)
|
||||
ReUpdateQualifCurRes(pCurrReInfo->s->cars[0]);
|
||||
}
|
||||
|
||||
if (replayRecord && pCurrReInfo->s->currentTime >= replayTimestamp) {
|
||||
replaySituation(pCurrReInfo);
|
||||
}
|
||||
}
|
||||
|
||||
int ReSituationUpdater::threadLoop(void* pUpdater)
|
||||
|
@ -560,11 +593,18 @@ int ReSituationUpdater::terminate()
|
|||
|
||||
GfLogInfo("Terminating situation updater.\n");
|
||||
|
||||
/* need to ensure the last record gets writeen */
|
||||
tRmInfo* pCurrReInfo = ReSituation::self().data();
|
||||
if (replayRecord) {
|
||||
replaySituation(pCurrReInfo);
|
||||
GfLogInfo("Last replay entry done.\n");
|
||||
}
|
||||
|
||||
// Lock the race engine data.
|
||||
ReSituation::self().lock("ReSituationUpdater::terminate");
|
||||
|
||||
// Set the death flag.
|
||||
_bTerminate = true;
|
||||
_bTerminate = true;
|
||||
|
||||
// Unlock the race engine data.
|
||||
ReSituation::self().unlock("ReSituationUpdater::terminate");
|
||||
|
@ -661,6 +701,7 @@ tRmInfo* ReSituationUpdater::copySituation(tRmInfo*& pTarget, const tRmInfo* pSo
|
|||
pTgtCar->_curTime = pSrcCar->_curTime;
|
||||
pTgtCar->_topSpeed = pSrcCar->_topSpeed;
|
||||
pTgtCar->_laps = pSrcCar->_laps;
|
||||
pTgtCar->_bestLap = pSrcCar->_bestLap;
|
||||
pTgtCar->_nbPitStops = pSrcCar->_nbPitStops;
|
||||
pTgtCar->_remainingLaps = pSrcCar->_remainingLaps;
|
||||
pTgtCar->_pos = pSrcCar->_pos;
|
||||
|
@ -693,9 +734,9 @@ tRmInfo* ReSituationUpdater::copySituation(tRmInfo*& pTarget, const tRmInfo* pSo
|
|||
//{
|
||||
// tCarPenalty *newPenalty = (tCarPenalty*)malloc(sizeof(tCarPenalty));
|
||||
// newPenalty->penalty = penalty->penalty;
|
||||
// newPenalty->lapToClear = penalty->lapToClear;
|
||||
// GfLogDebug("ReSituationCopy(car #%d) : Copying penalty %p to %p\n",
|
||||
// pSrcCar->index, penalty, newPenalty);
|
||||
// newPenalty->lapToClear = penalty->lapToClear;
|
||||
// GfLogDebug("ReSituationCopy(car #%d) : Copying penalty %p to %p\n",
|
||||
// pSrcCar->index, penalty, newPenalty);
|
||||
// GF_TAILQ_INSERT_TAIL(&(pTgtCar->_penaltyList), newPenalty, link);
|
||||
// penalty = GF_TAILQ_NEXT(penalty, link);
|
||||
//}
|
||||
|
@ -787,6 +828,152 @@ tRmInfo* ReSituationUpdater::copySituation(tRmInfo*& pTarget, const tRmInfo* pSo
|
|||
return pTarget;
|
||||
}
|
||||
|
||||
void ReSituationUpdater::replaySituation(tRmInfo*& pSource)
|
||||
{
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
char command[200];
|
||||
int result;
|
||||
|
||||
tReplayElt dummyTarget;
|
||||
tReplayElt* pTgtCar;
|
||||
tCarElt* pSrcCar;
|
||||
|
||||
if (!replayDB) return;
|
||||
|
||||
// Do everything in 1 transaction for speed
|
||||
sqlite3_exec(replayDB, "BEGIN TRANSACTION", NULL, NULL, NULL);
|
||||
|
||||
for (int nCarInd = 0; nCarInd < _nInitDrivers; nCarInd++)
|
||||
{
|
||||
pTgtCar = &dummyTarget;
|
||||
pSrcCar = &pSource->carList[nCarInd];
|
||||
|
||||
// Assemble the data we record
|
||||
pTgtCar->currentTime = pSource->s->currentTime;
|
||||
|
||||
memcpy(&pTgtCar->info, &pSrcCar->info, sizeof(tInitCar));
|
||||
memcpy(&pTgtCar->pub, &pSrcCar->pub, sizeof(tPublicCar));
|
||||
memcpy(&pTgtCar->race, &pSrcCar->race, sizeof(tCarRaceInfo));
|
||||
memcpy(&pTgtCar->priv, &pSrcCar->priv, sizeof(tPrivCar));
|
||||
memcpy(&pTgtCar->ctrl, &pSrcCar->ctrl, sizeof(tCarCtrl));
|
||||
memcpy(&pTgtCar->pitcmd, &pSrcCar->pitcmd, sizeof(tCarPitCmd));
|
||||
|
||||
// and write to database
|
||||
sprintf(command, "INSERT INTO car%d (timestamp, lap, datablob) VALUES (%f, %d, ?)", nCarInd,
|
||||
pSource->s->currentTime, pSrcCar->_laps);
|
||||
|
||||
result = sqlite3_prepare_v2(replayDB, command, -1, &replayBlobs[nCarInd], 0);
|
||||
if (result) {
|
||||
GfLogInfo("Replay: Unable to instert into table car%d: %s\n", nCarInd, sqlite3_errmsg(replayDB));
|
||||
} else {
|
||||
/* push binary blob into database */
|
||||
result = sqlite3_bind_blob(replayBlobs[nCarInd], 1, (void *) &dummyTarget, sizeof(dummyTarget), SQLITE_STATIC);
|
||||
result = sqlite3_step(replayBlobs[nCarInd]);
|
||||
}
|
||||
//GfLogInfo("Replay wrote car%d = time %f, lap %d\n", nCarInd, pSource->s->currentTime, pSrcCar->_laps);
|
||||
}
|
||||
|
||||
sqlite3_exec(replayDB, "END TRANSACTION", NULL, NULL, NULL);
|
||||
replayTimestamp = pSource->s->currentTime + (1/(float)replayRecord);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ReSituationUpdater::ghostcarSituation(tRmInfo*& pTarget)
|
||||
{
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
tCarElt *pTgtCar;
|
||||
tReplayElt *pSrcCar, *pSrc2Car;
|
||||
int result;
|
||||
|
||||
if (!replayDB) return;
|
||||
|
||||
if (ghostcarActive) {
|
||||
if (pTarget->s->currentTime - ghostcarTimeOffset >= nextGhostcarData.currentTime) {
|
||||
result = sqlite3_step(ghostcarBlob);
|
||||
if (result == SQLITE_ROW) {
|
||||
curGhostcarData = nextGhostcarData;
|
||||
memcpy(&nextGhostcarData, sqlite3_column_blob(ghostcarBlob, 0), sizeof(tReplayElt));
|
||||
} else {
|
||||
// don't do anything untill next lap is started
|
||||
// GfLogInfo("Ghostcar completed lap\n");
|
||||
ghostcarActive = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ghostcar uses the last carElt
|
||||
pTgtCar = &pTarget->carList[_nInitDrivers];
|
||||
pSrcCar = &curGhostcarData;
|
||||
|
||||
// GfLogInfo("Read ghostcar data: time %f %f, lap %d\n", pTarget->s->currentTime, pSrcCar->currentTime, pSrcCar->_laps);
|
||||
|
||||
// Really this should only be read once at start of race
|
||||
memcpy(&pTgtCar->race, &pSrcCar->race, sizeof(tCarRaceInfo));
|
||||
pTgtCar->race.pit = NULL;
|
||||
|
||||
// hack to fix trkpos
|
||||
pSrcCar->pub.trkPos = pTgtCar->pub.trkPos;
|
||||
|
||||
memcpy(&pTgtCar->pub, &pSrcCar->pub, sizeof(tPublicCar));
|
||||
memcpy(&pTgtCar->info, &pSrcCar->info, sizeof(tInitCar));
|
||||
|
||||
for(int i=0; i < 4; i++) {
|
||||
pTgtCar->priv.wheel[i] = pSrcCar->priv.wheel[i];
|
||||
pTgtCar->priv.wheel[i].seg = NULL;
|
||||
}
|
||||
pTgtCar->priv.gear = pSrcCar->priv.gear;
|
||||
pTgtCar->priv.fuel = pSrcCar->priv.fuel;
|
||||
pTgtCar->priv.enginerpm = pSrcCar->priv.enginerpm;
|
||||
pTgtCar->priv.dammage = pSrcCar->priv.dammage;
|
||||
}
|
||||
|
||||
if (pTarget->s->currentTime - ghostcarTimeOffset < nextGhostcarData.currentTime) {
|
||||
// Interpolate position in between records
|
||||
double timeFrac;
|
||||
double yaw, roll, pitch;
|
||||
|
||||
pTgtCar = &pTarget->carList[_nInitDrivers];
|
||||
pSrcCar = &curGhostcarData;
|
||||
pSrc2Car = &nextGhostcarData;
|
||||
|
||||
timeFrac = (pTarget->s->currentTime - ghostcarTimeOffset - curGhostcarData.currentTime) /
|
||||
(nextGhostcarData.currentTime - curGhostcarData.currentTime);
|
||||
|
||||
pTgtCar->_pos_X = pSrcCar->_pos_X + (pSrc2Car->_pos_X - pSrcCar->_pos_X) * timeFrac;
|
||||
pTgtCar->_pos_Y = pSrcCar->_pos_Y + (pSrc2Car->_pos_Y - pSrcCar->_pos_Y) * timeFrac;
|
||||
pTgtCar->_pos_Z = pSrcCar->_pos_Z + (pSrc2Car->_pos_Z - pSrcCar->_pos_Z) * timeFrac - pTgtCar->_statGC_z;
|
||||
|
||||
yaw = pSrc2Car->_yaw;
|
||||
roll = pSrc2Car->_roll;
|
||||
pitch = pSrc2Car->_pitch;
|
||||
|
||||
// assumes that these can't change at high rate
|
||||
if (yaw < pSrcCar->_yaw - PI)
|
||||
yaw += 2 * PI;
|
||||
else if (yaw > pSrcCar->_yaw + PI)
|
||||
yaw -= 2 * PI;
|
||||
|
||||
if (roll < pSrcCar->_roll - PI)
|
||||
roll += 2 * PI;
|
||||
else if (roll > pSrcCar->_roll + PI)
|
||||
roll -= 2 * PI;
|
||||
|
||||
if (pitch < pSrcCar->_pitch - PI)
|
||||
pitch += 2 * PI;
|
||||
else if (pitch > pSrcCar->_pitch + PI)
|
||||
pitch -= 2 * PI;
|
||||
|
||||
pTgtCar->_yaw = pSrcCar->_yaw + (yaw - pSrcCar->_yaw) * timeFrac;
|
||||
pTgtCar->_roll = pSrcCar->_roll + (roll - pSrcCar->_roll) * timeFrac;
|
||||
pTgtCar->_pitch = pSrcCar->_pitch + (pitch - pSrcCar->_pitch) * timeFrac;
|
||||
|
||||
sgMakeCoordMat4(pTgtCar->pub.posMat, pTgtCar->_pos_X, pTgtCar->_pos_Y, pTgtCar->_pos_Z,
|
||||
(tdble) RAD2DEG(pTgtCar->_yaw), (tdble) RAD2DEG(pTgtCar->_roll),
|
||||
(tdble) RAD2DEG(pTgtCar->_pitch));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ReSituationUpdater::freezSituation(tRmInfo*& pSituation)
|
||||
{
|
||||
if (pSituation)
|
||||
|
@ -891,6 +1078,13 @@ tRmInfo* ReSituationUpdater::getPreviousStep()
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (replayRecord && _pPrevReInfo->s->currentTime >= replayTimestamp) {
|
||||
replaySituation(_pPrevReInfo);
|
||||
}
|
||||
|
||||
if (replayRecord)
|
||||
ghostcarSituation(_pPrevReInfo);
|
||||
|
||||
return _pPrevReInfo;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,12 @@ private:
|
|||
//! (Deep) Copy the given situation.
|
||||
struct RmInfo* copySituation(struct RmInfo*& pTarget, const struct RmInfo* pSource);
|
||||
|
||||
// Record the situation to a replay database
|
||||
void replaySituation(struct RmInfo*& pTarget);
|
||||
|
||||
// Record the situation to a replay database
|
||||
void ghostcarSituation(struct RmInfo*& pTarget);
|
||||
|
||||
//! Free the given situation
|
||||
void freezSituation(struct RmInfo*& pSituation);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <tgfdata.h>
|
||||
#include <race.h>
|
||||
#include <tracks.h>
|
||||
#include <replay.h>
|
||||
|
||||
#include "racesituation.h"
|
||||
#include "racemain.h"
|
||||
|
@ -40,6 +41,7 @@
|
|||
|
||||
#include "standardgame.h"
|
||||
|
||||
int replayReplay;
|
||||
|
||||
// The singleton.
|
||||
StandardGame* StandardGame::_pSelf = 0;
|
||||
|
@ -316,6 +318,13 @@ bool StandardGame::loadPhysicsEngine()
|
|||
if (pmodPhysEngine && !_piPhysEngine)
|
||||
GfModule::unload(pmodPhysEngine);
|
||||
|
||||
// don't record if we're 'replaying'
|
||||
printf("Checking type of SIMU\n");
|
||||
if (strcmp(RM_VAL_MOD_SIMU_REPLAY, strModName.c_str()) == 0)
|
||||
replayReplay = 1;
|
||||
else
|
||||
replayReplay = 0;
|
||||
|
||||
return _piPhysEngine ? true : false;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,3 +11,6 @@ IF(NOT OPTION_OFFICIAL_ONLY)
|
|||
|
||||
ENDIF()
|
||||
|
||||
IF(OPTION_3RDPARTY_SQLITE3)
|
||||
SD_ADD_SUBDIRECTORY(simureplay)
|
||||
ENDIF(OPTION_3RDPARTY_SQLITE3)
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
IF(NOT OPTION_3RDPARTY_SOLID)
|
||||
|
||||
INCLUDE_DIRECTORIES(BEFORE ../simuv2.1/SOLID-2.0/include)
|
||||
ELSE(NOT OPTION_3RDPARTY_SOLID)
|
||||
ADD_SOLID_INCLUDEDIR()
|
||||
|
||||
ENDIF(NOT OPTION_3RDPARTY_SOLID)
|
||||
|
||||
INCLUDE(../../../../cmake/macros.cmake)
|
||||
|
||||
ADD_SDLIB_INCLUDEDIR(portability)
|
||||
|
||||
IF(WIN32)
|
||||
# DLL export stuff under Windows (to avoid .def file)
|
||||
ADD_DEFINITIONS(-DSIMUVREPLAY_DLL)
|
||||
ENDIF(WIN32)
|
||||
|
||||
IF(MSVC)
|
||||
# Ignore some run-time libs to avoid link time warnings and sometimes even crashes.
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:msvcrt.lib")
|
||||
ENDIF(MSVC)
|
||||
|
||||
SET(SIMU_SOURCES simu.cpp simureplay.cpp)
|
||||
SET(SIMU_HEADERS sim.h simureplay.h)
|
||||
|
||||
IF(NOT OPTION_3RDPARTY_SOLID)
|
||||
# BEFORE in order to prevent Windows 3rdParty/include/SOLID from taking the flag.
|
||||
INCLUDE_DIRECTORIES(BEFORE SOLID-2.0/include)
|
||||
ELSE(NOT OPTION_3RDPARTY_SOLID)
|
||||
ADD_SOLID_INCLUDEDIR()
|
||||
ENDIF(NOT OPTION_3RDPARTY_SOLID)
|
||||
ADD_PLIB_INCLUDEDIR()
|
||||
|
||||
ADD_INTERFACE_INCLUDEDIR()
|
||||
ADD_SDLIB_INCLUDEDIR(math tgf robottools)
|
||||
|
||||
# Note: Headers needed for having them available in IDEs.
|
||||
SD_ADD_LIBRARY(simureplay MODULE ${SIMU_SOURCES} ${SIMU_HEADERS})
|
||||
|
||||
# Might not work with GCC 4.5 or + (non-robot modules crash at 1st reload = after 1 dlclose)
|
||||
#SET_TARGET_PROPERTIES(simuv2.1 PROPERTIES VERSION ${VERSION} SOVERSION 0.0.0)
|
||||
|
||||
ADD_SOLID_LIBRARY(simureplay) # Ignored if not OPTION_3RDPARTY_SOLID
|
||||
|
||||
ADD_SDLIB_LIBRARY(simureplay portability tgf robottools solid) # solid ignored if not OPTION_3RDPARTY_SOLID
|
||||
|
||||
SD_INSTALL_FILES(LIB modules/simu TARGETS simureplay)
|
|
@ -0,0 +1,156 @@
|
|||
/***************************************************************************
|
||||
|
||||
file : carstruct.h
|
||||
created : Sun Mar 19 00:06:07 CET 2000
|
||||
copyright : (C) 2000 by Eric Espie
|
||||
email : torcs@free.fr
|
||||
version : $Id: carstruct.h 2917 2010-10-17 19:03:40Z pouillot $
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _CAR__H_
|
||||
#define _CAR__H_
|
||||
|
||||
#include <plib/sg.h>
|
||||
#include <SOLID/solid.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
tCarCtrl *ctrl;
|
||||
void *params;
|
||||
tCarElt *carElt;
|
||||
tDynPt DynGC; /* GC local data except position */
|
||||
tDynPt DynGCg; /* GC global data */
|
||||
tTrkLocPos trkPos; /* current track position */
|
||||
#if 0
|
||||
/* driver's interface */
|
||||
tCarCtrl *ctrl;
|
||||
void *params;
|
||||
tCarElt *carElt;
|
||||
|
||||
tCarCtrl preCtrl;
|
||||
|
||||
/* components */
|
||||
tAxle axle[2];
|
||||
tWheel wheel[4];
|
||||
tSteer steer;
|
||||
tBrakeSyst brkSyst;
|
||||
tAero aero;
|
||||
tWing wing[2];
|
||||
tTransmission transmission; /* includes clutch, gearbox and driveshaft */
|
||||
tEngine engine;
|
||||
|
||||
/* static */
|
||||
t3Dd dimension; /* car's mesures */
|
||||
tdble mass; /* mass with pilot (without fuel) */
|
||||
tdble Minv; /* 1 / mass with pilot (without fuel) */
|
||||
tdble tank; /* fuel tank capa */
|
||||
t3Dd statGC; /* static pos of GC */
|
||||
t3Dd Iinv; /* inverse of inertial moment along the car's 3 axis */
|
||||
|
||||
/* dynamic */
|
||||
tdble fuel; /* current fuel load */
|
||||
tDynPt DynGC; /* GC local data except position */
|
||||
tDynPt DynGCg; /* GC global data */
|
||||
tPosd VelColl; /* resulting velocity after collision */
|
||||
tDynPt preDynGC; /* previous one */
|
||||
tTrkLocPos trkPos; /* current track position */
|
||||
tdble airSpeed2; /* current air speed (squared) for aerodynamic forces */
|
||||
|
||||
/* internals */
|
||||
tdble Cosz;
|
||||
tdble Sinz;
|
||||
tDynPt corner[4]; /* x,y,z for static relative pos, ax,ay,az for dyn. world coord */
|
||||
int collision;
|
||||
t3Dd normal;
|
||||
t3Dd collpos;
|
||||
tdble wheelbase;
|
||||
tdble wheeltrack;
|
||||
sgMat4 posMat;
|
||||
DtShapeRef shape; /* for collision */
|
||||
int blocked; // Flag to show if the car has had already a collision in the same timestep.
|
||||
int dammage;
|
||||
|
||||
/* enabling features */
|
||||
int features;
|
||||
|
||||
tDynPt restPos; /* target rest position after the car is broken */
|
||||
|
||||
int collisionAware;
|
||||
#endif
|
||||
} tCar;
|
||||
|
||||
#if 0
|
||||
|
||||
#define CHECK_VAR(_var_, _msg_) do { \
|
||||
if (isnan(_var_) || isinf(_var_)) { \
|
||||
printf("%s = %f in %s line %d\n", _msg_, _var_, __FILE__, __LINE__); \
|
||||
assert (0); \
|
||||
exit(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DUMP_CAR(_car_) do { \
|
||||
printf("DynGC.acc.x = %f\n", (_car_)->DynGC.acc.x); \
|
||||
printf("DynGC.acc.y = %f\n", (_car_)->DynGC.acc.y); \
|
||||
printf("DynGC.acc.y = %f\n", (_car_)->DynGC.acc.y); \
|
||||
printf("DynGC.vel.x = %f\n", (_car_)->DynGC.vel.x); \
|
||||
printf("DynGC.vel.y = %f\n", (_car_)->DynGC.vel.y); \
|
||||
printf("DynGCg.pos.x = %f\n", (_car_)->DynGCg.pos.x); \
|
||||
printf("DynGCg.pos.y = %f\n", (_car_)->DynGCg.pos.y); \
|
||||
printf("DynGCg.acc.x = %f\n", (_car_)->DynGCg.acc.x); \
|
||||
printf("DynGCg.acc.y = %f\n", (_car_)->DynGCg.acc.y); \
|
||||
printf("DynGCg.vel.x = %f\n", (_car_)->DynGCg.vel.x); \
|
||||
printf("DynGCg.vel.y = %f\n", (_car_)->DynGCg.vel.y); \
|
||||
printf("DynGCg.pos.x = %f\n", (_car_)->DynGCg.pos.x); \
|
||||
printf("DynGCg.pos.y = %f\n", (_car_)->DynGCg.pos.y); \
|
||||
printf("aero.drag = %f\n", (_car_)->aero.drag); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define CHECK(_car_) do { \
|
||||
if (isnan((_car_)->DynGC.acc.x) || isinf((_car_)->DynGC.acc.x) || \
|
||||
isnan((_car_)->DynGC.acc.y) || isinf((_car_)->DynGC.acc.y) || \
|
||||
isnan((_car_)->DynGC.vel.x) || isinf((_car_)->DynGC.vel.x) || \
|
||||
isnan((_car_)->DynGC.vel.y) || isinf((_car_)->DynGC.vel.y) || \
|
||||
isnan((_car_)->DynGC.acc.x) || isinf((_car_)->DynGC.acc.x) || \
|
||||
isnan((_car_)->DynGCg.acc.y) || isinf((_car_)->DynGCg.acc.y) || \
|
||||
isnan((_car_)->DynGCg.vel.x) || isinf((_car_)->DynGCg.vel.x) || \
|
||||
isnan((_car_)->DynGCg.vel.y) || isinf((_car_)->DynGCg.vel.y) || \
|
||||
isnan((_car_)->DynGCg.pos.x) || isinf((_car_)->DynGCg.pos.x) || \
|
||||
isnan((_car_)->DynGCg.pos.y) || isinf((_car_)->DynGCg.pos.y) || \
|
||||
isnan((_car_)->aero.drag) || isinf((_car_)->aero.drag)) { \
|
||||
printf("Problem for %s in %s line %d\n", (_car_)->carElt->_name, __FILE__, __LINE__); \
|
||||
DUMP_CAR(_car_); \
|
||||
assert (0); \
|
||||
/* GfScrShutdown(); */ \
|
||||
exit(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define CHECK_VAR(_var_, _msg_)
|
||||
#define CHECK(_car_)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _CAR__H_ */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/***************************************************************************
|
||||
|
||||
file : sim.h
|
||||
created : Sun Mar 19 00:07:42 CET 2000
|
||||
copyright : (C) 2000 by Eric Espie
|
||||
email : torcs@free.fr
|
||||
version : $Id: sim.h 3568 2011-05-15 15:55:24Z pouillot $
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _SIMFCT_H_
|
||||
#define _SIMFCT_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include <portability.h>
|
||||
#include <tgf.h>
|
||||
#include <track.h>
|
||||
#include <car.h>
|
||||
#include <raceman.h>
|
||||
#include <robottools.h>
|
||||
|
||||
#include "carstruct.h"
|
||||
|
||||
|
||||
extern void SimConfig(tCarElt *carElt);
|
||||
extern void SimReConfig(tCarElt *carElt);
|
||||
extern void SimUpdate(tSituation*, double deltaTime);
|
||||
extern void SimInit(int nbcars, tTrack* track);
|
||||
extern void SimShutdown(void);
|
||||
|
||||
extern void SimCarTelemetry(int nCarIndex, bool bOn = true);
|
||||
extern void UpdateSimCarTable(tDynPt DynGCG,int index);
|
||||
extern void SimUpdateSingleCar(int index, double deltaTime,tSituation *s);
|
||||
extern tDynPt* GetSimCarTable(int index);
|
||||
|
||||
#if 0
|
||||
extern void SimAxleConfig(tCar *car, int index);
|
||||
extern void SimAxleUpdate(tCar *car, int index);
|
||||
|
||||
extern void SimCarConfig(tCar *car);
|
||||
extern void SimCarUpdate(tCar *car, tSituation*);
|
||||
extern void SimCarUpdate2(tCar *car, tSituation*);
|
||||
|
||||
extern void SimSuspCheckIn(tSuspension *susp);
|
||||
extern void SimSuspUpdate(tSuspension *susp);
|
||||
extern void SimSuspConfig(void *hdle, const char *section, tSuspension *susp, tdble F0, tdble X0);
|
||||
|
||||
extern void SimWheelConfig(tCar *car, int index);
|
||||
extern void SimWheelUpdateRide(tCar *car, int index);
|
||||
extern void SimWheelUpdateForce(tCar *car, int index);
|
||||
extern void SimWheelUpdateRotation(tCar *car);
|
||||
extern void SimUpdateFreeWheels(tCar *car, int axlenb);
|
||||
|
||||
|
||||
extern void SimSteerConfig(tCar *car);
|
||||
extern void SimSteerUpdate(tCar *car);
|
||||
|
||||
extern void SimBrakeConfig(void *hdle, const char *section, tBrake *brake);
|
||||
extern void SimBrakeUpdate(tCar *car, tWheel *wheel, tBrake *brake);
|
||||
extern void SimBrakeSystemConfig(tCar *car);
|
||||
extern void SimBrakeSystemUpdate(tCar *car);
|
||||
|
||||
extern void SimAeroConfig(tCar *car);
|
||||
extern void SimAeroUpdate(tCar *car, tSituation *s);
|
||||
extern void SimWingConfig(tCar *car, int index);
|
||||
extern void SimWingUpdate(tCar *car, int index, tSituation *s);
|
||||
|
||||
extern void SimCarUpdateWheelPos(tCar *car);
|
||||
|
||||
extern void SimTransmissionConfig(tCar *car);
|
||||
extern void SimTransmissionUpdate(tCar *car);
|
||||
extern void SimGearboxUpdate(tCar *car);
|
||||
|
||||
extern void SimDifferentialConfig(void *hdle, const char *section, tDifferential *differential);
|
||||
extern void SimDifferentialUpdate(tCar *car, tDifferential *differential, int first);
|
||||
|
||||
extern void SimEngineConfig(tCar *car);
|
||||
extern void SimEngineUpdateTq(tCar *car);
|
||||
extern tdble SimEngineUpdateRpm(tCar *car, tdble axleRpm);
|
||||
extern void SimEngineShutdown(tCar *car);
|
||||
|
||||
extern void SimCarCollideZ(tCar *car);
|
||||
extern void SimCarCollideXYScene(tCar *car);
|
||||
extern void SimCarCollideCars(tSituation*);
|
||||
extern void SimCarCollideConfig(tCar *car, tTrack *track);
|
||||
extern void SimCarCollideShutdown(int nbcars);
|
||||
extern void SimCarCollideInit(tTrack *track);
|
||||
extern void SimCollideRemoveCar(tCar *car, int nbcars);
|
||||
|
||||
extern tdble SimDeltaTime;
|
||||
extern int SimTelemetry;
|
||||
extern tCar *SimCarTable;
|
||||
extern t3Dd vectStart[];
|
||||
extern t3Dd vectEnd[];
|
||||
|
||||
extern tdble simDammageFactor[];
|
||||
extern tdble simSkidFactor[];
|
||||
#endif
|
||||
|
||||
/// return a number drawn uniformly from [0,1]
|
||||
inline float urandom() {
|
||||
return ((((float)rand()-1)/((float)RAND_MAX)));
|
||||
}
|
||||
|
||||
#define SIM_VECT_COLL 12
|
||||
#define SIM_VECT_SPD 13
|
||||
#define SIM_VECT_ACCEL 14
|
||||
#define SIM_WHEEL_SPD 16
|
||||
#define SIM_WHEEL_ACCEL 20
|
||||
|
||||
#define SIM_Z_OFFSET 2.0
|
||||
|
||||
#endif /* _SIMFCT_H_ */
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,436 @@
|
|||
/***************************************************************************
|
||||
|
||||
file : simu.cpp
|
||||
created : Sun Mar 19 00:07:53 CET 2000
|
||||
copyright : (C) 2000 by Eric Espie
|
||||
email : torcs@free.fr
|
||||
version : $Id: simu.cpp 3945 2011-10-07 13:38:15Z wdbee $
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <memory.h>
|
||||
#include <cmath>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <portability.h>
|
||||
#include <tgf.h>
|
||||
#include <robottools.h>
|
||||
|
||||
#include <replay.h>
|
||||
|
||||
#include "sim.h"
|
||||
|
||||
tCar *SimCarTable = 0;
|
||||
int SimTelemetry = -1;
|
||||
static tTrack *PTrack = 0;
|
||||
static int SimNbCars = 0;
|
||||
|
||||
int replayForward;
|
||||
double lastCurTime;
|
||||
double replayTimeOffset;
|
||||
static tReplayElt curReplayData[50];
|
||||
static tReplayElt nextReplayData[50];
|
||||
|
||||
static int old_id;
|
||||
|
||||
/*
|
||||
* Check the input control from robots
|
||||
*/
|
||||
static void
|
||||
ctrlCheck(tCar *car)
|
||||
{
|
||||
}
|
||||
|
||||
/* Initial configuration */
|
||||
void
|
||||
SimConfig(tCarElt *carElt)
|
||||
{
|
||||
GfLogInfo("Replay SimConfig\n");
|
||||
|
||||
tCar *car = &(SimCarTable[carElt->index]);
|
||||
|
||||
memset(car, 0, sizeof(tCar));
|
||||
|
||||
car->carElt = carElt;
|
||||
|
||||
car->DynGC = carElt->_DynGC;
|
||||
car->DynGCg = carElt->pub.DynGCg;
|
||||
car->trkPos = carElt->_trkPos;
|
||||
car->ctrl = &carElt->ctrl;
|
||||
car->params = carElt->_carHandle;
|
||||
|
||||
#if 0
|
||||
SimCarConfig(car);
|
||||
|
||||
SimCarCollideConfig(car, PTrack);
|
||||
#endif
|
||||
sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
|
||||
(float) RAD2DEG(carElt->_yaw), (float) RAD2DEG(carElt->_roll), (float) RAD2DEG(carElt->_pitch));
|
||||
|
||||
replayTimeOffset = 0;
|
||||
}
|
||||
|
||||
/* After pit stop */
|
||||
void
|
||||
SimReConfig(tCarElt *carElt)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
RemoveCar(tCar *car, tSituation *s)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SimCarTelemetry(int nCarIndex, bool bOn)
|
||||
{
|
||||
SimTelemetry = bOn ? nCarIndex : -1;
|
||||
}
|
||||
|
||||
void
|
||||
SimUpdate(tSituation *s, double deltaTime)
|
||||
{
|
||||
tCar *car;
|
||||
tCarElt *pTgtCar;
|
||||
tReplayElt *pSrcCar, *pSrc2Car;
|
||||
|
||||
char command[200];
|
||||
int result, result2;
|
||||
int reload = 0;
|
||||
|
||||
if (replayDB == NULL) {
|
||||
GfLogInfo("Replay NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for reversal of time
|
||||
if (replayForward && s->currentTime < lastCurTime) {
|
||||
GfLogInfo("REPLAY: time running backward at timestamp %f\n", s->currentTime);
|
||||
reload = 1;
|
||||
replayForward = 0;
|
||||
} else if (replayForward == 0 && s->currentTime > lastCurTime) {
|
||||
GfLogInfo("REPLAY: time running forward at timestamp %f\n", s->currentTime);
|
||||
reload = 1;
|
||||
replayForward = 1;
|
||||
}
|
||||
|
||||
lastCurTime = s->currentTime;
|
||||
|
||||
// readback next race record as required
|
||||
for (int nCarInd = 0; nCarInd < s->_ncars; nCarInd++) {
|
||||
if (reload ||
|
||||
(replayForward && s->currentTime >= nextReplayData[nCarInd].currentTime) ||
|
||||
(replayForward == 0 && s->currentTime <= nextReplayData[nCarInd].currentTime)) {
|
||||
result = sqlite3_step(replayBlobs[nCarInd]);
|
||||
|
||||
// check if the previous SELECT has returned all it's rows
|
||||
if (replayForward && (result == SQLITE_DONE || reload)) {
|
||||
// and read another chunk
|
||||
GfLogInfo("REPLAY: Chunk forward timestamp %f (%f)\n", s->currentTime, deltaTime);
|
||||
sprintf(command, "SELECT datablob FROM car%d WHERE timestamp >= %f LIMIT %d",
|
||||
nCarInd, s->currentTime, REPLAY_CHUNK);
|
||||
result2 = sqlite3_prepare_v2(replayDB, command, -1, &replayBlobs[nCarInd], 0);
|
||||
|
||||
if (result2) {
|
||||
GfLogInfo("Unable to prepare car%d: %s\n", nCarInd, sqlite3_errmsg(replayDB));
|
||||
} else {
|
||||
result = sqlite3_step(replayBlobs[nCarInd]);
|
||||
}
|
||||
}
|
||||
if (replayForward == 0 && (result == SQLITE_DONE || reload)) {
|
||||
// and read another chunk
|
||||
GfLogInfo("REPLAY: Chunk backward timestamp %f (%f)\n", s->currentTime, deltaTime);
|
||||
sprintf(command, "SELECT datablob FROM car%d WHERE timestamp <= %f ORDER BY timestamp DESC LIMIT %d",
|
||||
nCarInd, s->currentTime, REPLAY_CHUNK);
|
||||
result2 = sqlite3_prepare_v2(replayDB, command, -1, &replayBlobs[nCarInd], 0);
|
||||
|
||||
if (result2) {
|
||||
GfLogInfo("Unable to prepare car%d: %s\n", nCarInd, sqlite3_errmsg(replayDB));
|
||||
} else {
|
||||
result = sqlite3_step(replayBlobs[nCarInd]);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == SQLITE_ROW) {
|
||||
curReplayData[nCarInd] = nextReplayData[nCarInd];
|
||||
memcpy(&nextReplayData[nCarInd], sqlite3_column_blob(replayBlobs[nCarInd], 0), sizeof(tReplayElt));
|
||||
|
||||
nextReplayData[nCarInd].currentTime += replayTimeOffset;
|
||||
}
|
||||
|
||||
// allow for replaying data again and again
|
||||
if (result == SQLITE_DONE) replayTimeOffset = s->currentTime;
|
||||
|
||||
//GfLogInfo("Replay read car%d: %f\n", nCarInd, curReplayData[nCarInd].currentTime);
|
||||
|
||||
car = &(SimCarTable[nCarInd]);
|
||||
pTgtCar = car->carElt;
|
||||
pSrcCar = &curReplayData[nCarInd];
|
||||
|
||||
#if 1
|
||||
// Really this should only be read once at start of race
|
||||
pSrcCar->race.pit = pTgtCar->race.pit;
|
||||
pSrcCar->race.bestSplitTime = pTgtCar->race.bestSplitTime;
|
||||
pSrcCar->race.curSplitTime = pTgtCar->race.curSplitTime;
|
||||
|
||||
memcpy(&pTgtCar->race, &pSrcCar->race, sizeof(tCarRaceInfo));
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// hack to fix trkpos
|
||||
pSrcCar->pub.trkPos = pTgtCar->pub.trkPos;
|
||||
|
||||
memcpy(&pTgtCar->pub, &pSrcCar->pub, sizeof(tPublicCar));
|
||||
pTgtCar->_glance = 0;
|
||||
pTgtCar->_oldglance = 0;
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
memcpy(&pTgtCar->info, &pSrcCar->info, sizeof(tInitCar));
|
||||
pTgtCar->_wrongWayTime = s->currentTime + 5.0;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
memcpy(&pTgtCar->priv, &pSrcCar->priv, sizeof(tPrivCar));
|
||||
#else
|
||||
// Selectively pick 'priv' data
|
||||
for(int i=0; i < 4; i++) {
|
||||
pTgtCar->priv.wheel[i] = pSrcCar->priv.wheel[i];
|
||||
pTgtCar->priv.wheel[i].seg = RtTrackGetSeg(&pTgtCar->_trkPos);
|
||||
pTgtCar->_skid[i] = pSrcCar->_skid[i];
|
||||
pTgtCar->priv.wheel[i].spinVel = pSrcCar->priv.wheel[i].spinVel;
|
||||
}
|
||||
pTgtCar->priv.gear = pSrcCar->priv.gear;
|
||||
pTgtCar->priv.fuel = pSrcCar->priv.fuel;
|
||||
pTgtCar->priv.enginerpm = pSrcCar->priv.enginerpm;
|
||||
pTgtCar->priv.enginerpmRedLine = pSrcCar->priv.enginerpmRedLine;
|
||||
pTgtCar->priv.dammage = pSrcCar->priv.dammage;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
memcpy(&pTgtCar->ctrl, &pSrcCar->ctrl, sizeof(tCarCtrl));
|
||||
#else
|
||||
pTgtCar->_steerCmd = pSrcCar->_steerCmd;
|
||||
pTgtCar->_brakeCmd = pSrcCar->_brakeCmd;
|
||||
pTgtCar->_clutchCmd = pSrcCar->_clutchCmd;
|
||||
pTgtCar->_gearCmd = pSrcCar->_gearCmd;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
memcpy(&pTgtCar->pitcmd, &pSrcCar->pitcmd, sizeof(tCarPitCmd));
|
||||
#endif
|
||||
|
||||
// figure out track segment (allowing that they may be allocated to different memory location)
|
||||
pTgtCar->_distFromStartLine = pSrcCar->_distFromStartLine;
|
||||
#if 0
|
||||
if (pTgtCar->pub.trkPos.seg->id != old_id) {
|
||||
printf("New TrkSeg %d @ %fs: DfS %f : %s = %fm", pTgtCar->pub.trkPos.seg->id, s->currentTime,
|
||||
pTgtCar->_distFromStartLine,
|
||||
pTgtCar->pub.trkPos.seg->name, pTgtCar->pub.trkPos.seg->lgfromstart);
|
||||
if (pTgtCar->pub.trkPos.seg->raceInfo & TR_LAST) printf(" LAST");
|
||||
if (pTgtCar->pub.trkPos.seg->raceInfo & TR_START) printf(" START");
|
||||
printf("\n");
|
||||
old_id = pTgtCar->pub.trkPos.seg->id;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pTgtCar->_distFromStartLine > pTgtCar->pub.trkPos.seg->next->lgfromstart) {
|
||||
// Next segment, forward direction
|
||||
pTgtCar->pub.trkPos.seg = pTgtCar->pub.trkPos.seg->next;
|
||||
} else if (pTgtCar->pub.trkPos.seg->raceInfo & TR_LAST == TR_LAST &&
|
||||
pTgtCar->pub.trkPos.seg->next->raceInfo & TR_START == TR_START &&
|
||||
pTgtCar->_distFromStartLine < pTgtCar->pub.trkPos.seg->lgfromstart/2) {
|
||||
// Crossing Start Line, forward direction
|
||||
// something weird here, sometime reports wrong lap completed
|
||||
pTgtCar->pub.trkPos.seg = pTgtCar->pub.trkPos.seg->next;
|
||||
} else if (pTgtCar->_distFromStartLine < pTgtCar->pub.trkPos.seg->lgfromstart) {
|
||||
// Previous segment, reverse direction
|
||||
pTgtCar->pub.trkPos.seg = pTgtCar->pub.trkPos.seg->prev;
|
||||
}
|
||||
}
|
||||
|
||||
if ((replayForward && s->currentTime < nextReplayData[nCarInd].currentTime) ||
|
||||
(replayForward == 0 && s->currentTime > nextReplayData[nCarInd].currentTime)) {
|
||||
// Interpolate position in between records
|
||||
double timeFrac;
|
||||
double yaw, roll, pitch;
|
||||
|
||||
car = &(SimCarTable[nCarInd]);
|
||||
pTgtCar = car->carElt;
|
||||
pSrcCar = &curReplayData[nCarInd];
|
||||
pSrc2Car = &nextReplayData[nCarInd];
|
||||
|
||||
if (replayForward)
|
||||
timeFrac = (s->currentTime - curReplayData[nCarInd].currentTime) /
|
||||
(nextReplayData[nCarInd].currentTime - curReplayData[nCarInd].currentTime);
|
||||
else
|
||||
timeFrac = (curReplayData[nCarInd].currentTime - s->currentTime) /
|
||||
(curReplayData[nCarInd].currentTime - nextReplayData[nCarInd].currentTime);
|
||||
|
||||
// position on track
|
||||
pTgtCar->_pos_X = pSrcCar->_pos_X + (pSrc2Car->_pos_X - pSrcCar->_pos_X) * timeFrac;
|
||||
pTgtCar->_pos_Y = pSrcCar->_pos_Y + (pSrc2Car->_pos_Y - pSrcCar->_pos_Y) * timeFrac;
|
||||
pTgtCar->_statGC_z = pSrcCar->_statGC_z + (pSrc2Car->_statGC_z - pSrcCar->_statGC_z) * timeFrac;
|
||||
pTgtCar->_pos_Z = pSrcCar->_pos_Z + (pSrc2Car->_pos_Z - pSrcCar->_pos_Z) * timeFrac - pTgtCar->_statGC_z;
|
||||
|
||||
yaw = pSrc2Car->_yaw;
|
||||
roll = pSrc2Car->_roll;
|
||||
pitch = pSrc2Car->_pitch;
|
||||
|
||||
// assumes that these can't change at high rate
|
||||
if (yaw < pSrcCar->_yaw - PI)
|
||||
yaw += 2 * PI;
|
||||
else if (yaw > pSrcCar->_yaw + PI)
|
||||
yaw -= 2 * PI;
|
||||
|
||||
if (roll < pSrcCar->_roll - PI)
|
||||
roll += 2 * PI;
|
||||
else if (roll > pSrcCar->_roll + PI)
|
||||
roll -= 2 * PI;
|
||||
|
||||
if (pitch < pSrcCar->_pitch - PI)
|
||||
pitch += 2 * PI;
|
||||
else if (pitch > pSrcCar->_pitch + PI)
|
||||
pitch -= 2 * PI;
|
||||
|
||||
pTgtCar->_yaw = pSrcCar->_yaw + (yaw - pSrcCar->_yaw) * timeFrac;
|
||||
pTgtCar->_roll = pSrcCar->_roll + (roll - pSrcCar->_roll) * timeFrac;
|
||||
pTgtCar->_pitch = pSrcCar->_pitch + (pitch - pSrcCar->_pitch) * timeFrac;
|
||||
|
||||
sgMakeCoordMat4(pTgtCar->pub.posMat, pTgtCar->_pos_X, pTgtCar->_pos_Y, pTgtCar->_pos_Z,
|
||||
(tdble) RAD2DEG(pTgtCar->_yaw), (tdble) RAD2DEG(pTgtCar->_roll),
|
||||
(tdble) RAD2DEG(pTgtCar->_pitch));
|
||||
|
||||
// some cameras use speed to determine rain behaviour
|
||||
pTgtCar->_speed_x = pSrcCar->_speed_x + (pSrc2Car->_speed_x - pSrcCar->_speed_x) * timeFrac;
|
||||
pTgtCar->_speed_y = pSrcCar->_speed_y + (pSrc2Car->_speed_y - pSrcCar->_speed_y) * timeFrac;
|
||||
pTgtCar->_speed_z = pSrcCar->_speed_z + (pSrc2Car->_speed_z - pSrcCar->_speed_z) * timeFrac;
|
||||
pTgtCar->_speed_xy = pSrcCar->_speed_xy + (pSrc2Car->_speed_xy - pSrcCar->_speed_xy) * timeFrac;
|
||||
|
||||
pTgtCar->_enginerpm = pSrcCar->_enginerpm + (pSrc2Car->_enginerpm - pSrcCar->_enginerpm) * timeFrac;
|
||||
|
||||
// Audio works in world cordinates
|
||||
pTgtCar->pub.DynGCg.pos.x = pSrcCar->pub.DynGCg.pos.x + (pSrc2Car->pub.DynGCg.pos.x - pSrcCar->pub.DynGCg.pos.x) * timeFrac;
|
||||
pTgtCar->pub.DynGCg.pos.y = pSrcCar->pub.DynGCg.pos.y + (pSrc2Car->pub.DynGCg.pos.y - pSrcCar->pub.DynGCg.pos.y) * timeFrac;
|
||||
pTgtCar->pub.DynGCg.pos.z = pSrcCar->pub.DynGCg.pos.z + (pSrc2Car->pub.DynGCg.pos.z - pSrcCar->pub.DynGCg.pos.z) * timeFrac;
|
||||
|
||||
pTgtCar->pub.DynGCg.vel.x = pSrcCar->pub.DynGCg.vel.x + (pSrc2Car->pub.DynGCg.vel.x - pSrcCar->pub.DynGCg.vel.x) * timeFrac;
|
||||
pTgtCar->pub.DynGCg.vel.y = pSrcCar->pub.DynGCg.vel.y + (pSrc2Car->pub.DynGCg.vel.y - pSrcCar->pub.DynGCg.vel.y) * timeFrac;
|
||||
pTgtCar->pub.DynGCg.vel.z = pSrcCar->pub.DynGCg.vel.z + (pSrc2Car->pub.DynGCg.vel.z - pSrcCar->pub.DynGCg.vel.z) * timeFrac;
|
||||
|
||||
// Sound uses accelCmd to antenuate engine
|
||||
pTgtCar->_accelCmd = pSrcCar->_accelCmd + (pSrc2Car->_accelCmd - pSrcCar->_accelCmd) * timeFrac;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimInit(int nbcars, tTrack* track)
|
||||
{
|
||||
tCar *car;
|
||||
tCarElt *pTgtCar;
|
||||
char command[200];
|
||||
int result;
|
||||
|
||||
|
||||
GfLogInfo("Replay SimInit\n");
|
||||
|
||||
if (replayDB == NULL) {
|
||||
GfLogInfo("Replay Database Not Opened!!\n\n\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SimNbCars = nbcars;
|
||||
SimCarTable = (tCar*)calloc(nbcars, sizeof(tCar));
|
||||
PTrack = track;
|
||||
//SimCarCollideInit(PTrack);
|
||||
|
||||
for (int nCarInd = 0; nCarInd < nbcars; nCarInd++) {
|
||||
sprintf(command, "SELECT datablob FROM car%d LIMIT %d", nCarInd, REPLAY_CHUNK);
|
||||
result = sqlite3_prepare_v2(replayDB, command, -1, &replayBlobs[nCarInd], 0);
|
||||
|
||||
if (result) {
|
||||
GfLogInfo("Unable to prepare car%d: %s\n", nCarInd, sqlite3_errmsg(replayDB));
|
||||
} else {
|
||||
replayForward = 1;
|
||||
lastCurTime = -10.0;
|
||||
|
||||
// read the first 2 records for each car
|
||||
result = sqlite3_step(replayBlobs[nCarInd]);
|
||||
if (result == SQLITE_ROW) {
|
||||
memcpy(&curReplayData[nCarInd], sqlite3_column_blob(replayBlobs[nCarInd], 0), sizeof(tReplayElt));
|
||||
lastCurTime = curReplayData[nCarInd].currentTime;
|
||||
}
|
||||
|
||||
result = sqlite3_step(replayBlobs[nCarInd]);
|
||||
if (result == SQLITE_ROW) {
|
||||
memcpy(&nextReplayData[nCarInd], sqlite3_column_blob(replayBlobs[nCarInd], 0), sizeof(tReplayElt));
|
||||
}
|
||||
#if 0
|
||||
// preload info into structure
|
||||
car = &(SimCarTable[nCarInd]);
|
||||
pTgtCar = car->carElt;
|
||||
memcpy(&pTgtCar->info, &curReplayData[nCarInd].info, sizeof(tInitCar));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
GfLogInfo("SimuReplay recording starts at %f\n", lastCurTime);
|
||||
}
|
||||
|
||||
void
|
||||
SimShutdown(void)
|
||||
{
|
||||
tCar *car;
|
||||
int ncar;
|
||||
|
||||
//SimCarCollideShutdown(SimNbCars);
|
||||
if (SimCarTable) {
|
||||
for (ncar = 0; ncar < SimNbCars; ncar++) {
|
||||
car = &(SimCarTable[ncar]);
|
||||
//SimEngineShutdown(car);
|
||||
}
|
||||
free(SimCarTable);
|
||||
SimCarTable = 0;
|
||||
}
|
||||
|
||||
PTrack = 0;
|
||||
}
|
||||
|
||||
/* Used for network games to update client physics */
|
||||
void
|
||||
UpdateSimCarTable(tDynPt DynGCG,int index)
|
||||
{
|
||||
tCar *pCar = SimCarTable;
|
||||
pCar[index].DynGCg = DynGCG;
|
||||
}
|
||||
|
||||
/* Used for network games get current physics values*/
|
||||
tDynPt *
|
||||
GetSimCarTable(int index)
|
||||
{
|
||||
tCar *pCar = SimCarTable;
|
||||
return &pCar[index].DynGCg;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SimUpdateSingleCar(int index, double deltaTime,tSituation *s)
|
||||
{
|
||||
GfLogInfo("Replay UpdateSingleCar\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/***************************************************************************
|
||||
|
||||
file : simureplay.cpp
|
||||
created : Sun Mar 19 00:08:04 CET 2000
|
||||
copyright : (C) 2000 by Eric Espie
|
||||
email : torcs@free.fr
|
||||
version : $Id: simuv4.cpp 3568 2011-05-15 15:55:24Z pouillot $
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "simureplay.h"
|
||||
|
||||
#include "sim.h"
|
||||
|
||||
|
||||
// The Simureplay: singleton.
|
||||
SimuReplay* SimuReplay::_pSelf = 0;
|
||||
|
||||
int openGfModule(const char* pszShLibName, void* hShLibHandle)
|
||||
{
|
||||
// Instanciate the (only) module instance.
|
||||
SimuReplay::_pSelf = new SimuReplay(pszShLibName, hShLibHandle);
|
||||
|
||||
// Register it to the GfModule module manager if OK.
|
||||
if (SimuReplay::_pSelf)
|
||||
GfModule::register_(SimuReplay::_pSelf);
|
||||
|
||||
// Report about success or error.
|
||||
return SimuReplay::_pSelf ? 0 : 1;
|
||||
}
|
||||
|
||||
int closeGfModule()
|
||||
{
|
||||
// Unregister it from the GfModule module manager.
|
||||
if (SimuReplay::_pSelf)
|
||||
GfModule::unregister(SimuReplay::_pSelf);
|
||||
|
||||
// Delete the (only) module instance.
|
||||
delete SimuReplay::_pSelf;
|
||||
SimuReplay::_pSelf = 0;
|
||||
|
||||
// Report about success or error.
|
||||
return 0;
|
||||
}
|
||||
|
||||
SimuReplay& SimuReplay::self()
|
||||
{
|
||||
// Pre-condition : 1 successfull openGfModule call.
|
||||
return *_pSelf;
|
||||
}
|
||||
|
||||
SimuReplay::SimuReplay(const std::string& strShLibName, void* hShLibHandle)
|
||||
: GfModule(strShLibName, hShLibHandle)
|
||||
{
|
||||
}
|
||||
|
||||
SimuReplay::~SimuReplay()
|
||||
{
|
||||
}
|
||||
|
||||
// Implementation of IPhysicsEngine.
|
||||
void SimuReplay::initialize(int nCars, struct Track* pTrack)
|
||||
{
|
||||
::SimInit(nCars, pTrack);
|
||||
}
|
||||
|
||||
void SimuReplay::configureCar(struct CarElt* pCar)
|
||||
{
|
||||
::SimConfig(pCar);
|
||||
}
|
||||
|
||||
void SimuReplay::reconfigureCar(struct CarElt* pCar)
|
||||
{
|
||||
::SimReConfig(pCar);
|
||||
}
|
||||
|
||||
void SimuReplay::toggleCarTelemetry(int nCarIndex, bool bOn)
|
||||
{
|
||||
::SimCarTelemetry(nCarIndex, bOn);
|
||||
}
|
||||
|
||||
void SimuReplay::updateSituation(struct Situation *pSituation, double fDeltaTime)
|
||||
{
|
||||
::SimUpdate(pSituation, fDeltaTime);
|
||||
}
|
||||
|
||||
void SimuReplay::updateCar(struct Situation *pSituation, double fDeltaTime, int nCarIndex)
|
||||
{
|
||||
::SimUpdateSingleCar(nCarIndex, fDeltaTime, pSituation);
|
||||
}
|
||||
|
||||
void SimuReplay::setCar(const struct DynPt& dynGCG, int nCarIndex)
|
||||
{
|
||||
::UpdateSimCarTable(dynGCG, nCarIndex);
|
||||
}
|
||||
|
||||
tDynPt* SimuReplay::getCar(int nCarIndex)
|
||||
{
|
||||
return ::GetSimCarTable(nCarIndex);
|
||||
}
|
||||
|
||||
void SimuReplay::shutdown()
|
||||
{
|
||||
::SimShutdown();
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/***************************************************************************
|
||||
|
||||
file : simuv4.h
|
||||
copyright : (C) 2011 by Jean-Philippe Meuret
|
||||
(C) 2013 by Wolf-Dieter Beelitz
|
||||
email : pouillot@users.sourceforge.net
|
||||
version : $Id: simuv4.h 4903 2012-08-27 11:31:33Z kmetykog $
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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
|
||||
The "Simu V4" physics engine module
|
||||
@version $Id: simuv4.h 4903 2012-08-27 11:31:33Z kmetykog $
|
||||
*/
|
||||
|
||||
#ifndef _SIMUREPLAY_H_
|
||||
#define _SIMUREPLAY_H_
|
||||
|
||||
#include <iphysicsengine.h>
|
||||
|
||||
#include <tgf.hpp>
|
||||
|
||||
|
||||
// DLL exported symbols declarator for Windows.
|
||||
#ifdef WIN32
|
||||
# ifdef SIMUREPLAY_DLL
|
||||
# define SIMUREPLAY_API __declspec(dllexport)
|
||||
# else
|
||||
# define SIMUREPLAY_API __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define SIMUREPLAY_API
|
||||
#endif
|
||||
|
||||
|
||||
// The C interface of the module.
|
||||
extern "C" int SIMUREPLAY_API openGfModule(const char* pszShLibName, void* hShLibHandle);
|
||||
extern "C" int SIMUREPLAY_API closeGfModule();
|
||||
|
||||
// The module main class (Singleton, inherits GfModule, and implements IPhysicsEngine).
|
||||
class SIMUREPLAY_API SimuReplay : public GfModule, public IPhysicsEngine
|
||||
{
|
||||
public:
|
||||
|
||||
// Implementation of IPhysicsEngine.
|
||||
virtual void initialize(int nCars, struct Track* pTrack);
|
||||
virtual void configureCar(struct CarElt* pCar);
|
||||
virtual void reconfigureCar(struct CarElt* pCar);
|
||||
virtual void toggleCarTelemetry(int nCarIndex, bool bOn = true);
|
||||
virtual void updateSituation(struct Situation *pSituation, double fDeltaTime);
|
||||
virtual void updateCar(struct Situation *pSituation, double fDeltaTime, int nCarIndex);
|
||||
virtual void setCar(const struct DynPt& dynGCG, int nCarIndex);
|
||||
virtual struct DynPt* getCar(int nCarIndex);
|
||||
virtual void shutdown();
|
||||
|
||||
// Accessor to the singleton.
|
||||
static SimuReplay& self();
|
||||
|
||||
// Destructor.
|
||||
virtual ~SimuReplay();
|
||||
|
||||
protected:
|
||||
|
||||
// Protected constructor to avoid instanciation outside (but friends).
|
||||
SimuReplay(const std::string& strShLibName, void* hShLibHandle);
|
||||
|
||||
// Make the C interface functions nearly member functions.
|
||||
friend int openGfModule(const char* pszShLibName, void* hShLibHandle);
|
||||
friend int closeGfModule();
|
||||
|
||||
protected:
|
||||
|
||||
// The singleton.
|
||||
static SimuReplay* _pSelf;
|
||||
};
|
||||
|
||||
#endif /* _SIMUREPLAY_H_ */
|
|
@ -38,8 +38,8 @@
|
|||
/* list of available simulation engine */
|
||||
static const int DefaultSimuVersion = 1;
|
||||
static const char *SimuVersionList[] =
|
||||
{RM_VAL_MOD_SIMU_V2, RM_VAL_MOD_SIMU_V2_1, RM_VAL_MOD_SIMU_V3, RM_VAL_MOD_SIMU_V4};
|
||||
static const char *SimuVersionDispNameList[] = {"V2.0 (old)", "V2.1 (obsolete)", "V3.0 (incomplete)", "V4.0 (default)"};
|
||||
{RM_VAL_MOD_SIMU_V2, RM_VAL_MOD_SIMU_V2_1, RM_VAL_MOD_SIMU_V3, RM_VAL_MOD_SIMU_V4, RM_VAL_MOD_SIMU_REPLAY};
|
||||
static const char *SimuVersionDispNameList[] = {"V2.0", "V2.1", "V3.0", "V4.0", "Replay"};
|
||||
static const int NbSimuVersions = sizeof(SimuVersionList) / sizeof(SimuVersionList[0]);
|
||||
static int CurSimuVersion = DefaultSimuVersion;
|
||||
|
||||
|
@ -54,10 +54,17 @@ static const int NbThreadAffinitySchemes = sizeof(ThreadAffinitySchemeList) / si
|
|||
static int CurMultiThreadScheme = 0; // Auto
|
||||
static int CurThreadAffinityScheme = 0; // On
|
||||
|
||||
/* list of available replay record schemes */
|
||||
static const char *ReplaySchemeList[] = {RM_VAL_REPLAY_OFF, RM_VAL_REPLAY_LOW, RM_VAL_REPLAY_NORMAL, RM_VAL_REPLAY_HIGH, RM_VAL_REPLAY_PERFECT};
|
||||
static const char *ReplaySchemeDispNameList[] = {"off", "Low", "Normal", "High", "Perfect"};
|
||||
static const int NbReplaySchemes = sizeof(ReplaySchemeList) / sizeof(ReplaySchemeList[0]);
|
||||
static int CurReplayScheme = 0;
|
||||
|
||||
/* gui label ids */
|
||||
static int SimuVersionId;
|
||||
static int MultiThreadSchemeId;
|
||||
static int ThreadAffinitySchemeId;
|
||||
static int ReplayRateSchemeId;
|
||||
|
||||
/* gui screen handles */
|
||||
static void *ScrHandle = NULL;
|
||||
|
@ -69,6 +76,7 @@ static void loadSimuCfg(void)
|
|||
const char *simuVersionName;
|
||||
const char *multiThreadSchemeName;
|
||||
const char *threadAffinitySchemeName;
|
||||
const char *replayRateSchemeName;
|
||||
int i;
|
||||
|
||||
char buf[1024];
|
||||
|
@ -112,11 +120,28 @@ static void loadSimuCfg(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Replay Rate
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
replayRateSchemeName = GfParmGetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_REPLAY_RATE, ReplaySchemeList[0]);
|
||||
for (i = 0; i < NbReplaySchemes; i++) {
|
||||
if (strcmp(replayRateSchemeName, ReplaySchemeList[i]) == 0) {
|
||||
CurReplayScheme = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
CurReplayScheme = 0;
|
||||
#endif
|
||||
|
||||
GfParmReleaseHandle(paramHandle);
|
||||
|
||||
GfuiLabelSetText(ScrHandle, SimuVersionId, SimuVersionDispNameList[CurSimuVersion]);
|
||||
GfuiLabelSetText(ScrHandle, MultiThreadSchemeId, MultiThreadSchemeList[CurMultiThreadScheme]);
|
||||
GfuiLabelSetText(ScrHandle, ThreadAffinitySchemeId, ThreadAffinitySchemeList[CurThreadAffinityScheme]);
|
||||
GfuiLabelSetText(ScrHandle, ReplayRateSchemeId, ReplaySchemeDispNameList[CurReplayScheme]);
|
||||
#ifndef THIRD_PARTY_SQLITE3
|
||||
GfuiEnable(ScrHandle, ReplayRateSchemeId, GFUI_DISABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -130,6 +155,7 @@ static void storeSimuCfg(void * /* dummy */)
|
|||
GfParmSetStr(paramHandle, RM_SECT_MODULES, RM_ATTR_MOD_SIMU, SimuVersionList[CurSimuVersion]);
|
||||
GfParmSetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_MULTI_THREADING, MultiThreadSchemeList[CurMultiThreadScheme]);
|
||||
GfParmSetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_THREAD_AFFINITY, ThreadAffinitySchemeList[CurThreadAffinityScheme]);
|
||||
GfParmSetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_REPLAY_RATE, ReplaySchemeList[CurReplayScheme]);
|
||||
GfParmWriteFile(NULL, paramHandle, "raceengine");
|
||||
GfParmReleaseHandle(paramHandle);
|
||||
|
||||
|
@ -182,6 +208,17 @@ onChangeThreadAffinityScheme(void *vp)
|
|||
}
|
||||
|
||||
|
||||
/* Change the replay rate scheme */
|
||||
static void
|
||||
onChangeReplayRateScheme(void *vp)
|
||||
{
|
||||
CurReplayScheme =
|
||||
(CurReplayScheme + NbReplaySchemes + (int)(long)vp) % NbReplaySchemes;
|
||||
|
||||
GfuiLabelSetText(ScrHandle, ReplayRateSchemeId, ReplaySchemeDispNameList[CurReplayScheme]);
|
||||
}
|
||||
|
||||
|
||||
static void onActivate(void * /* dummy */)
|
||||
{
|
||||
loadSimuCfg();
|
||||
|
@ -217,6 +254,12 @@ SimuMenuInit(void *prevMenu)
|
|||
GfuiMenuCreateButtonControl(ScrHandle, menuDescHdle, "threadaffleftarrow", (void*)-1, onChangeThreadAffinityScheme);
|
||||
GfuiMenuCreateButtonControl(ScrHandle, menuDescHdle, "threadaffrightarrow", (void*)1, onChangeThreadAffinityScheme);
|
||||
|
||||
ReplayRateSchemeId = GfuiMenuCreateLabelControl(ScrHandle, menuDescHdle, "replayratelabel");
|
||||
#ifdef THIRD_PARTY_SQLITE3
|
||||
GfuiMenuCreateButtonControl(ScrHandle, menuDescHdle, "replayrateleftarrow", (void*)-1, onChangeReplayRateScheme);
|
||||
GfuiMenuCreateButtonControl(ScrHandle, menuDescHdle, "replayraterightarrow", (void*)1, onChangeReplayRateScheme);
|
||||
#endif
|
||||
|
||||
GfuiMenuCreateButtonControl(ScrHandle, menuDescHdle, "ApplyButton", PrevScrHandle, storeSimuCfg);
|
||||
GfuiMenuCreateButtonControl(ScrHandle, menuDescHdle, "CancelButton", PrevScrHandle, GfuiScreenActivate);
|
||||
|
||||
|
|
|
@ -37,12 +37,19 @@
|
|||
|
||||
|
||||
static int rmSaveButtonId;
|
||||
static int rmReplayButtonId;
|
||||
static void *rmScrHdle = NULL;
|
||||
|
||||
static void rmPracticeResults(void *prevHdle, tRmInfo *info, int start);
|
||||
static void rmRaceResults(void *prevHdle, tRmInfo *info, int start);
|
||||
static void rmQualifResults(void *prevHdle, tRmInfo *info, const char*pszTitle, int start);
|
||||
|
||||
static const int DefaultSimuVersion = 1;
|
||||
static const char *SimuVersionList[] =
|
||||
{RM_VAL_MOD_SIMU_V2, RM_VAL_MOD_SIMU_V2_1, RM_VAL_MOD_SIMU_V3, RM_VAL_MOD_SIMU_V4, RM_VAL_MOD_SIMU_REPLAY};
|
||||
static const int NbSimuVersions = sizeof(SimuVersionList) / sizeof(SimuVersionList[0]);
|
||||
static int CurSimuVersion = DefaultSimuVersion;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *prevHdle;
|
||||
|
@ -55,6 +62,37 @@ tRaceCall RmNextRace;
|
|||
tRaceCall RmPrevRace;
|
||||
|
||||
|
||||
static void
|
||||
rmReplayRace(void * /* dummy */)
|
||||
{
|
||||
const char *simuVersionName;
|
||||
int i;
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG);
|
||||
|
||||
void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
|
||||
|
||||
// Temporarily overwrite Simulation Type
|
||||
CurSimuVersion = DefaultSimuVersion;
|
||||
simuVersionName = GfParmGetStr(paramHandle, RM_SECT_MODULES, RM_ATTR_MOD_SIMU, SimuVersionList[DefaultSimuVersion]);
|
||||
for (i = 0; i < NbSimuVersions; i++) {
|
||||
if (strcmp(simuVersionName, SimuVersionList[i]) == 0) {
|
||||
CurSimuVersion = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GfParmSetStr(paramHandle, RM_SECT_MODULES, RM_ATTR_MOD_SIMU, SimuVersionList[4]);
|
||||
GfParmWriteFile(NULL, paramHandle, "raceengine");
|
||||
|
||||
LmRaceEngine().startNewRace();
|
||||
|
||||
// Restore original Simulation type
|
||||
GfParmSetStr(paramHandle, RM_SECT_MODULES, RM_ATTR_MOD_SIMU, SimuVersionList[CurSimuVersion]);
|
||||
GfParmWriteFile(NULL, paramHandle, "raceengine");
|
||||
GfParmReleaseHandle(paramHandle);
|
||||
}
|
||||
|
||||
static void
|
||||
rmSaveRes(void *vInfo)
|
||||
{
|
||||
|
@ -89,6 +127,8 @@ rmPracticeResults(void *prevHdle, tRmInfo *info, int start)
|
|||
static char path[1024];
|
||||
char *str;
|
||||
int damages;
|
||||
void *paramHandle;
|
||||
const char *replayRateSchemeName;
|
||||
|
||||
// Create screen, load menu XML descriptor and create static controls.
|
||||
rmScrHdle = GfuiScreenCreate();
|
||||
|
@ -182,6 +222,16 @@ rmPracticeResults(void *prevHdle, tRmInfo *info, int start)
|
|||
// Add "Continue" button
|
||||
GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "ContinueButton", prevHdle, GfuiScreenReplace);
|
||||
|
||||
// Add "Replay" button (if available)
|
||||
snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG);
|
||||
paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
|
||||
replayRateSchemeName = GfParmGetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_REPLAY_RATE, RM_VAL_REPLAY_OFF);
|
||||
|
||||
rmReplayButtonId = GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "ReplayButton", prevHdle, rmReplayRace);
|
||||
if (strcmp(replayRateSchemeName, RM_VAL_REPLAY_OFF) == 0)
|
||||
GfuiEnable(rmScrHdle, rmReplayButtonId, GFUI_DISABLE);
|
||||
GfParmReleaseHandle(paramHandle);
|
||||
|
||||
//Create 'save' button in the bottom right
|
||||
//rmSaveButtonId = GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "SaveButton", info, rmSaveRes);
|
||||
|
||||
|
@ -221,6 +271,8 @@ rmRaceResults(void *prevHdle, tRmInfo *info, int start)
|
|||
static char buf[256];
|
||||
static char path[512];
|
||||
char *str;
|
||||
void *paramHandle;
|
||||
const char *replayRateSchemeName;
|
||||
|
||||
GfLogTrace("Entering Race Results menu\n");
|
||||
|
||||
|
@ -337,7 +389,17 @@ rmRaceResults(void *prevHdle, tRmInfo *info, int start)
|
|||
|
||||
// Add "Continue" button
|
||||
GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "ContinueButton", prevHdle, GfuiScreenReplace);
|
||||
|
||||
|
||||
// Add "Replay" button (if available)
|
||||
snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG);
|
||||
paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
|
||||
replayRateSchemeName = GfParmGetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_REPLAY_RATE, RM_VAL_REPLAY_OFF);
|
||||
|
||||
rmReplayButtonId = GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "ReplayButton", prevHdle, rmReplayRace);
|
||||
if (strcmp(replayRateSchemeName, RM_VAL_REPLAY_OFF) == 0)
|
||||
GfuiEnable(rmScrHdle, rmReplayButtonId, GFUI_DISABLE);
|
||||
GfParmReleaseHandle(paramHandle);
|
||||
|
||||
//Create 'save' button in the bottom right
|
||||
//rmSaveButtonId = GfuiMenuCreateButtonControl(rmScrHdle, hmenu, "SaveButton", info, rmSaveRes);
|
||||
|
||||
|
|
Loading…
Reference in New Issue