363 lines
12 KiB
C++
363 lines
12 KiB
C++
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
|
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
|
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
|
|
|
#include "SerializationCommon.h"
|
|
|
|
#include <fstream>
|
|
#include <sstream>
|
|
|
|
namespace snippetvehicle
|
|
{
|
|
|
|
bool openDocument(const char* directory, const char* filename,
|
|
rapidjson::Document& document)
|
|
{
|
|
// Check the json file exists.
|
|
std::string fileWithPath(directory);
|
|
fileWithPath.push_back('/');
|
|
fileWithPath.append(filename);
|
|
std::ifstream inputFile(fileWithPath);
|
|
if (!inputFile.is_open())
|
|
{
|
|
printf("Opening file \"%s\" failed.\n", fileWithPath.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Check the json file can be loaded by rapidjson.
|
|
// Failures might be missing commas or braces.
|
|
std::string inputData{ std::istreambuf_iterator<char>(inputFile), std::istreambuf_iterator<char>() };
|
|
document.Parse(inputData.c_str());
|
|
inputFile.close();
|
|
if (!document.IsObject())
|
|
{
|
|
printf("Parsing file \"%s\" failed.\n", fileWithPath.c_str());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool readCommandResponseParams
|
|
(const rapidjson::Value& value, const PxVehicleAxleDescription& axleDesc,
|
|
PxVehicleCommandResponseParams& responseParams)
|
|
{
|
|
if (!value.HasMember("MaxResponse"))
|
|
return false;
|
|
responseParams.maxResponse = static_cast<PxReal>(value["MaxResponse"].GetDouble());
|
|
|
|
if (!value.HasMember("WheelResponseMultipliers"))
|
|
return false;
|
|
const rapidjson::Value& responseMultipliers = value["WheelResponseMultipliers"];
|
|
|
|
if (responseMultipliers.Size() < axleDesc.nbWheels)
|
|
return false;
|
|
if (responseMultipliers.Size() > PxVehicleLimits::eMAX_NB_WHEELS)
|
|
return false;
|
|
|
|
for (PxU32 i = 0; i < responseMultipliers.Size(); i++)
|
|
{
|
|
responseParams.wheelResponseMultipliers[i] = static_cast<PxReal>(responseMultipliers[i].GetDouble());
|
|
}
|
|
|
|
//Nonlinear response is not mandatory.
|
|
responseParams.nonlinearResponse.clear();
|
|
if(!value.HasMember("NonLinearResponse"))
|
|
return true;
|
|
const rapidjson::Value& nonlinearResponse = value["NonLinearResponse"];
|
|
const int nbCommandValues = nonlinearResponse.Size();
|
|
for (int i = 0; i < nbCommandValues; i++)
|
|
{
|
|
PxVehicleCommandValueResponseTable commandValueResponse;
|
|
|
|
//Read the throttle value and set it.
|
|
const rapidjson::Value& commandAndResponse = nonlinearResponse[i];
|
|
if (!commandAndResponse.HasMember("Throttle"))
|
|
return false;
|
|
const PxReal commandValue = static_cast<PxReal>(commandAndResponse["Throttle"].GetDouble());
|
|
commandValueResponse.commandValue = commandValue;
|
|
|
|
//Read the array of (speed, torque) entries.
|
|
if (!commandAndResponse.HasMember("ResponseCurve"))
|
|
return false;
|
|
const rapidjson::Value& torqueCurve = commandAndResponse["ResponseCurve"];
|
|
const PxU32 nbItems = torqueCurve.Size();
|
|
for (PxU32 j = 0; j < nbItems; j++)
|
|
{
|
|
const rapidjson::Value& torqueCurveItem = torqueCurve[j];
|
|
if (torqueCurveItem.Size() != 2)
|
|
return false;
|
|
const PxReal speed = static_cast<PxReal>(torqueCurveItem[0].GetDouble());
|
|
const PxReal normalisedResponse = static_cast<PxReal>(torqueCurveItem[1].GetDouble());
|
|
commandValueResponse.speedResponses.addPair(speed, normalisedResponse);
|
|
}
|
|
|
|
responseParams.nonlinearResponse.addResponse(commandValueResponse);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool writeCommandResponseParams
|
|
(const PxVehicleCommandResponseParams& responseParams, const PxVehicleAxleDescription& axleDesc,
|
|
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
|
{
|
|
writer.Key("MaxResponse");
|
|
writer.Double(static_cast<double>(responseParams.maxResponse));
|
|
|
|
writer.Key("WheelResponseMultipliers");
|
|
writer.StartArray();
|
|
for(PxU32 i = 0; i < axleDesc.nbWheels; i++)
|
|
{
|
|
const PxU32 wheelId = axleDesc.wheelIdsInAxleOrder[i];
|
|
writer.Double(static_cast<double>(responseParams.wheelResponseMultipliers[wheelId]));
|
|
}
|
|
writer.EndArray();
|
|
|
|
writer.Key("ResponseCurve");
|
|
writer.StartArray();
|
|
for (PxU32 i = 0; i < responseParams.nonlinearResponse.nbCommandValues; i++)
|
|
{
|
|
writer.Key("Throttle");
|
|
writer.Double(static_cast<double>(responseParams.nonlinearResponse.commandValues[i]));
|
|
|
|
writer.Key("ResponseCurve");
|
|
writer.StartArray();
|
|
const PxReal* speeds = responseParams.nonlinearResponse.speedResponses + responseParams.nonlinearResponse.speedResponsesPerCommandValue[i];
|
|
const PxReal* responses = speeds + responseParams.nonlinearResponse.nbSpeedResponsesPerCommandValue[i];
|
|
for (PxU32 j = 0; j < responseParams.nonlinearResponse.nbSpeedResponsesPerCommandValue[i]; j++)
|
|
{
|
|
writer.StartArray();
|
|
writer.Double(static_cast<double>(speeds[j]));
|
|
writer.Double(static_cast<double>(responses[j]));
|
|
writer.EndArray();
|
|
}
|
|
writer.EndArray();
|
|
}
|
|
writer.EndArray();
|
|
|
|
return true;
|
|
}
|
|
|
|
void writeCommandResponseParams
|
|
(const PxVehicleAxleDescription& axleDesc, const PxVehicleCommandResponseParams& throttleResponseParams,
|
|
rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
|
{
|
|
writer.StartObject();
|
|
|
|
writer.Key("MaxResponse");
|
|
writer.Double(static_cast<double>(throttleResponseParams.maxResponse));
|
|
|
|
writer.Key("WheelResponseMultipliers");
|
|
writer.StartArray();
|
|
for(PxU32 i = 0; i < axleDesc.nbWheels; i++)
|
|
{
|
|
const PxU32 wheelId = axleDesc.wheelIdsInAxleOrder[i];
|
|
writer.Double(static_cast<double>(throttleResponseParams.wheelResponseMultipliers[wheelId]));
|
|
}
|
|
writer.EndArray();
|
|
|
|
writer.EndObject();
|
|
}
|
|
|
|
|
|
bool readVec3(const rapidjson::Value& values, PxVec3& r)
|
|
{
|
|
if (values.Size() != 3)
|
|
return false;
|
|
|
|
r.x = static_cast<PxReal>(values[0].GetDouble());
|
|
r.y = static_cast<PxReal>(values[1].GetDouble());
|
|
r.z = static_cast<PxReal>(values[2].GetDouble());
|
|
return true;
|
|
}
|
|
|
|
bool writeVec3(const PxVec3& r, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
|
{
|
|
writer.StartArray();
|
|
writer.Double(static_cast<double>(r.x));
|
|
writer.Double(static_cast<double>(r.y));
|
|
writer.Double(static_cast<double>(r.z));
|
|
writer.EndArray();
|
|
return true;
|
|
}
|
|
|
|
|
|
bool readQuat(const rapidjson::Value& values, PxQuat& r)
|
|
{
|
|
if (values.Size() != 4)
|
|
return false;
|
|
|
|
r.x = static_cast<PxReal>(values[0].GetDouble());
|
|
r.y = static_cast<PxReal>(values[1].GetDouble());
|
|
r.z = static_cast<PxReal>(values[2].GetDouble());
|
|
r.w = static_cast<PxReal>(values[3].GetDouble());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool writeQuat(const PxQuat& r, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
|
{
|
|
writer.StartArray();
|
|
writer.Double(static_cast<double>(r.x));
|
|
writer.Double(static_cast<double>(r.y));
|
|
writer.Double(static_cast<double>(r.z));
|
|
writer.Double(static_cast<double>(r.w));
|
|
writer.EndArray();
|
|
return true;
|
|
}
|
|
|
|
bool readTransform(const rapidjson::Value& values, PxTransform& r)
|
|
{
|
|
if (!values.HasMember("Pos"))
|
|
return false;
|
|
if (!values.HasMember("Quat"))
|
|
return false;
|
|
|
|
if (!readVec3(values["Pos"], r.p))
|
|
return false;
|
|
if (!readQuat(values["Quat"], r.q))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool writeTransform(const PxTransform& r, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
|
{
|
|
writer.StartObject();
|
|
writer.Key("Pos");
|
|
writeVec3(r.p, writer);
|
|
writer.Key("Quat");
|
|
writeQuat(r.q, writer);
|
|
writer.EndObject();
|
|
return true;
|
|
}
|
|
|
|
template<const PxU32 N>
|
|
bool readFloatLookupTableN(const rapidjson::Value& values, PxVehicleFixedSizeLookupTable<PxReal, N>& lookupTable)
|
|
{
|
|
lookupTable.clear();
|
|
|
|
if (values.Size() > N)
|
|
return false;
|
|
|
|
for (PxU32 i = 0; i < values.Size(); i++)
|
|
{
|
|
const rapidjson::Value& element = values[i];
|
|
if (element.Size() != 2)
|
|
return false;
|
|
|
|
const PxReal x = static_cast<PxReal>(values[i][0].GetDouble());
|
|
const PxReal y = static_cast<PxReal>(values[i][1].GetDouble());
|
|
lookupTable.addPair(x, y);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool readFloatLookupTable
|
|
(const rapidjson::Value& values, PxVehicleFixedSizeLookupTable<PxReal, 3>& lookupTable)
|
|
{
|
|
return readFloatLookupTableN<3>(values, lookupTable);
|
|
}
|
|
|
|
bool readFloatLookupTable
|
|
(const rapidjson::Value& values, PxVehicleFixedSizeLookupTable<PxReal, PxVehicleEngineParams::eMAX_NB_ENGINE_TORQUE_CURVE_ENTRIES>& lookupTable)
|
|
{
|
|
return readFloatLookupTableN<PxVehicleEngineParams::eMAX_NB_ENGINE_TORQUE_CURVE_ENTRIES>(values, lookupTable);
|
|
}
|
|
|
|
template<const PxU32 N>
|
|
bool writeFloatLookupTable(const PxVehicleFixedSizeLookupTable<PxReal, N>& lookupTable, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
|
{
|
|
writer.StartArray();
|
|
for (PxU32 i = 0; i < lookupTable.nbDataPairs; i++)
|
|
{
|
|
writer.StartArray();
|
|
writer.Double(static_cast<double>(lookupTable.xVals[i]));
|
|
writer.Double(static_cast<double>(lookupTable.yVals[i]));
|
|
writer.EndArray();
|
|
}
|
|
writer.EndArray();
|
|
return true;
|
|
}
|
|
|
|
bool writeFloatLookupTable(const PxVehicleFixedSizeLookupTable<PxReal, 3>& lookupTable, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
|
{
|
|
return writeFloatLookupTable<3>(lookupTable, writer);
|
|
}
|
|
|
|
bool writeFloatLookupTable(const PxVehicleFixedSizeLookupTable<PxReal, PxVehicleEngineParams::eMAX_NB_ENGINE_TORQUE_CURVE_ENTRIES>& lookupTable, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
|
{
|
|
return writeFloatLookupTable<PxVehicleEngineParams::eMAX_NB_ENGINE_TORQUE_CURVE_ENTRIES>(lookupTable, writer);
|
|
}
|
|
|
|
bool readVec3LookupTable(const rapidjson::Value& values, PxVehicleFixedSizeLookupTable<PxVec3, 3>& lookupTable)
|
|
{
|
|
lookupTable.clear();
|
|
|
|
if (values.Size() > 3)
|
|
return false;
|
|
|
|
for (PxU32 i = 0; i < values.Size(); i++)
|
|
{
|
|
const rapidjson::Value& element = values[i];
|
|
if (element.Size() != 4)
|
|
return false;
|
|
|
|
const PxReal x = static_cast<PxReal>(values[i][0].GetDouble());
|
|
const PxVec3 y(static_cast<PxReal>(
|
|
values[i][1].GetDouble()), static_cast<PxReal>(values[i][2].GetDouble()), static_cast<PxReal>(values[i][3].GetDouble()));
|
|
lookupTable.addPair(x, y);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool writeVec3LookupTable(const PxVehicleFixedSizeLookupTable<PxVec3, 3>& lookupTable, rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer)
|
|
{
|
|
writer.StartArray();
|
|
for (PxU32 i = 0; i < lookupTable.nbDataPairs; i++)
|
|
{
|
|
writer.StartArray();
|
|
writer.Double(static_cast<double>(lookupTable.xVals[i]));
|
|
writer.Double(static_cast<double>(lookupTable.yVals[i].x));
|
|
writer.Double(static_cast<double>(lookupTable.yVals[i].y));
|
|
writer.Double(static_cast<double>(lookupTable.yVals[i].z));
|
|
writer.EndArray();
|
|
}
|
|
writer.EndArray();
|
|
return true;
|
|
|
|
}
|
|
|
|
}//namespace snippetvehicle
|
|
|
|
|
|
|
|
|