Skip to content

Commit

Permalink
Road editor: optional smoothing (specify how many splits)
Browse files Browse the repository at this point in the history
Currently cannot be controlled from TOBJ file format, only from scripting.

New script API:
* ImGui::SetNextItemWidth(float)
* ImGui::InputInt(string, int&)
* int ProceduralObjectClass.smoothing_num_splits
  • Loading branch information
ohlidalp committed Nov 30, 2022
1 parent abe0e04 commit 3719127
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 14 deletions.
27 changes: 18 additions & 9 deletions resources/scripts/road_editor.as
Expand Up @@ -106,13 +106,20 @@ class TerrainEditor
this.drawAiWaypointsPanel();
}

// Slider for selecting nodes
this.drawRoadEditPanel();

// End window
ImGui::End();
}

void drawRoadEditPanel()
{
ImGui::PushID("road edit box");

TerrainClass@ terrain = game.getTerrain();
ProceduralManagerClass@ roads = terrain.getProceduralManager();
if (roads.getNumObjects() > 0)
{
ImGui::PushID("road edit box");

ProceduralObjectClass@ obj = roads.getObject(m_selected_road);
ImGui::Text("Road: " + obj.getName());
ImGui::Text("Total points: " + obj.getNumPoints());
Expand Down Expand Up @@ -145,20 +152,22 @@ class TerrainEditor
{
obj.deletePoint(m_selected_point);
}

ImGui::SetNextItemWidth(120.f);
ImGui::InputInt("Num splits (smoothing, 0=off)", obj.smoothing_num_splits);

if (ImGui::Button("> Rebuild road mesh <"))
{
roads.removeObject(obj); // Clears the existing mesh
this.recalculateRotations(obj);
roads.addObject(obj); // Generates new mesh
// Because we removed and re-added the ProceduralObject from/to the manager,
// it got new index, so our selection is invalid. Update it.
this.setSelectedRoad(roads.getNumObjects() - 1);
}
}

ImGui::PopID(); // road edit box
}
}

// End window
ImGui::End();
ImGui::PopID(); // "road edit box"
}

void recalculateRotations(ProceduralObjectClass@ obj)
Expand Down
3 changes: 3 additions & 0 deletions source/main/scripting/bindings/ImGuiAngelscript.cpp
Expand Up @@ -102,6 +102,7 @@ void RoR::RegisterImGuiBindings(AngelScript::asIScriptEngine* engine)
engine->RegisterGlobalFunction("ImDrawList@ GetWindowDrawList()", asFUNCTIONPR(ImGui::GetWindowDrawList, (), ImDrawList*), asCALL_CDECL);
engine->RegisterGlobalFunction("void PushStyleColor(int index, const color&in color)", asFUNCTIONPR([](int index, Ogre::ColourValue const& col) { ImGui::PushStyleColor(index, (ImU32)ImColor(col.r, col.g, col.b, col.a)); }, (int, Ogre::ColourValue const&), void), asCALL_CDECL);
engine->RegisterGlobalFunction("void PopStyleColor(int count)", asFUNCTIONPR(ImGui::PopStyleColor, (int), void), asCALL_CDECL);
engine->RegisterGlobalFunction("void SetNextItemWidth(float)", asFUNCTIONPR(ImGui::SetNextItemWidth, (float), void), asCALL_CDECL);

engine->RegisterGlobalFunction("vector2 GetContentRegionMax()", asFUNCTIONPR([]() {
auto v = ImGui::GetContentRegionMax(); return Vector2(v.x, v.y); }, (), Vector2), asCALL_CDECL);
Expand Down Expand Up @@ -312,8 +313,10 @@ void RoR::RegisterImGuiBindings(AngelScript::asIScriptEngine* engine)
/* --- TODO: Register Vector4
engine->RegisterGlobalFunction("bool InputFloat4(const string&, Vector4&inout)", asFUNCTIONPR([](const string& id, Vector4& val) {
return ImGui::InputFloat4(id.c_str(), &val.x_); }, (const string&, Vector4&),bool), asCALL_CDECL);
*/
engine->RegisterGlobalFunction("bool InputInt(const string&, int&inout)", asFUNCTIONPR([](const string& id, int& val) {
return ImGui::InputInt(id.c_str(), &val); }, (const string&, int&), bool), asCALL_CDECL);
/*
engine->RegisterGlobalFunction("bool InputInt2(const string&, IntVector2&inout)", asFUNCTIONPR([](const string& id, IntVector2& val) {
return ImGui::InputInt2(id.c_str(), &val.x_); }, (const string&, IntVector2&),bool), asCALL_CDECL);
engine->RegisterGlobalFunction("bool InputInt3(const string&, IntVector3&inout)", asFUNCTIONPR([](const string& id, IntVector3& val) {
Expand Down
Expand Up @@ -105,6 +105,7 @@ void RoR::RegisterProceduralRoad(asIScriptEngine* engine)
result = engine->RegisterObjectMethod("ProceduralObjectClass", "ProceduralPointClassPtr @getPoint(int pos)", asMETHOD(RoR::ProceduralObject, getPoint), asCALL_THISCALL); ROR_ASSERT(result >= 0);
result = engine->RegisterObjectMethod("ProceduralObjectClass", "int getNumPoints()", asMETHOD(RoR::ProceduralObject, getNumPoints), asCALL_THISCALL); ROR_ASSERT(result >= 0);
result = engine->RegisterObjectMethod("ProceduralObjectClass", "ProceduralRoadClassPtr @getRoad()", asMETHOD(ProceduralObject, getRoad), asCALL_THISCALL); ROR_ASSERT(result >= 0);
result = engine->RegisterObjectProperty("ProceduralObjectClass", "int smoothing_num_splits", offsetof(ProceduralObject, smoothing_num_splits)); ROR_ASSERT(result >= 0);

// class ProceduralManager (ref)
ProceduralManager::RegisterRefCountingObject(engine, "ProceduralManagerClass");
Expand Down
45 changes: 43 additions & 2 deletions source/main/terrain/ProceduralManager.cpp
Expand Up @@ -116,9 +116,50 @@ void ProceduralManager::updateObject(ProceduralObjectPtr po)
// In diagnostic mode, disable collisions (speeds up terrain loading)
po->road->setCollisionEnabled(!App::diag_terrn_log_roads->getBool());

for (ProceduralPointPtr& pp: po->points)
Ogre::SimpleSpline spline;
if (po->smoothing_num_splits > 0)
{
po->road->addBlock(pp->position, pp->rotation, pp->type, pp->width, pp->bwidth, pp->bheight, pp->pillartype);
// Init smoothing
spline.setAutoCalculate(false);
for (ProceduralPointPtr& pp : po->points)
{
spline.addPoint(pp->position);
}
spline.recalcTangents();
}

for (int i_point = 0; i_point < po->getNumPoints(); i_point++)
{
ProceduralPointPtr pp = po->getPoint(i_point);
if (po->smoothing_num_splits > 0)
{
// smoothing on
for (int i_split = 1; i_split <= po->smoothing_num_splits; i_split++)
{
if (i_split == 0 || i_point == 0)
{
po->road->addBlock(pp->position, pp->rotation, pp->type, pp->width, pp->bwidth, pp->bheight, pp->pillartype);
}
else
{
const float progress = static_cast<float>(i_split) / static_cast<float>(po->smoothing_num_splits);
ProceduralPointPtr prev_pp = po->getPoint(i_point - 1);

const Ogre::Vector3 smooth_pos = spline.interpolate(i_point - 1, progress);
const Ogre::Quaternion smooth_rot = Quaternion::nlerp(progress, prev_pp->rotation, pp->rotation);
const float smooth_width = Math::lerp(prev_pp->width, pp->width, progress);
const float smooth_bwidth = Math::lerp(prev_pp->bwidth, pp->bwidth, progress);
const float smooth_bheight = Math::lerp(prev_pp->bheight, pp->bheight, progress);

po->road->addBlock(smooth_pos, smooth_rot, pp->type, smooth_width, smooth_bwidth, smooth_bheight, pp->pillartype);
}
}
}
else
{
// smoothing off
po->road->addBlock(pp->position, pp->rotation, pp->type, pp->width, pp->bwidth, pp->bheight, pp->pillartype);
}
}
po->road->finish();
}
Expand Down
1 change: 1 addition & 0 deletions source/main/terrain/ProceduralManager.h
Expand Up @@ -57,6 +57,7 @@ struct ProceduralObject: public RefCountingObject<ProceduralObject>
std::string name;
std::vector<ProceduralPointPtr> points;
ProceduralRoadPtr road;
int smoothing_num_splits = 0; // 0=off
};

class ProceduralManager: public RefCountingObject<ProceduralManager>
Expand Down
6 changes: 3 additions & 3 deletions source/main/terrain/ProceduralRoad.h
Expand Up @@ -85,12 +85,12 @@ class ProceduralRoad : public RefCountingObject<ProceduralRoad>
void computePoints(Ogre::Vector3* pts, Ogre::Vector3 pos, Ogre::Quaternion rot, RoadType type, float width, float bwidth, float bheight);
void textureFit(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3, Ogre::Vector3 p4, TextureFit texfit, Ogre::Vector2* texc, Ogre::Vector3 pos, Ogre::Vector3 lastpos, float width);

typedef struct
struct CoVertice_t
{
Ogre::Vector3 vertex;
Ogre::Vector3 normal;
Ogre::Vector2 texcoord;
} CoVertice_t;
};

Ogre::MeshPtr msh;
Ogre::SubMesh* mainsub = nullptr;
Expand All @@ -99,7 +99,7 @@ class ProceduralRoad : public RefCountingObject<ProceduralRoad>
Ogre::Vector3 vertex[MAX_VERTEX] = {};
int tricount = 0;
int vertexcount = 0;
short tris[MAX_TRIS * 3] = {};
uint16_t tris[MAX_TRIS * 3] = {};

Ogre::Quaternion lastrot;
Ogre::SceneNode* snode = nullptr;
Expand Down

0 comments on commit 3719127

Please sign in to comment.