Skip to content

Commit

Permalink
move Unit::localModel to SolidObject (features now have a non-animate…
Browse files Browse the repository at this point in the history
…d LM)

move SolidObject::LuaObjectMaterialData to LocalModel where it now belongs

this enables LuaObjectRendering::SetPieceList for features; as a byproduct
features (that have models) can use per-piece collision volumes and also
gain a last-hit piece with associated benefits

make DebugColVolDrawer draw piece volumes (if present) for features
make CollisionHandler only know about SolidObject

add Spring.{Get,Set}FeaturePieceCollisionVolumeData callouts
add Spring.GetFeatureLastAttackedPiece callout

reduce VectorInsertUnique's line-count
  • Loading branch information
rtri committed Dec 3, 2015
1 parent cde4943 commit e22aeb5
Show file tree
Hide file tree
Showing 29 changed files with 526 additions and 381 deletions.
9 changes: 7 additions & 2 deletions doc/changelog.txt
Expand Up @@ -14,22 +14,27 @@ Lua:
- new Spring.GetUICommands function to obtain a list of all UI commands (e.g. /luaui reload)
- new VFS.CalculateHash function that calculates hash (in base64 form) of a given string (with md5 support initially)
- new Spring.SetFeatureFade(featureID, bool) to control whether a feature will fade or not when zoomed out.
- add Spring.GetFeatureLastAttackedPiece callout
- add Spring.{Get,Set}FeaturePieceCollisionVolumeData callouts

- add Spring.FeatureRendering API; allows custom shaders (technically,
materials) for features as its Spring.UnitRendering counterpart does
for units
note: the following functions are no-ops
note: the following two functions are no-ops
Spring.UnitRendering.SetFeatureLuaDraw
Spring.FeatureRendering.SetUnitLuaDraw
Spring.FeatureRendering.SetPieceList

- add new callin DrawGroundPostDeferred; this runs at the end of its
respective deferred pass and allows proper frame compositing (with
ground flashes/decals/foliage/etc, which are drawn between it and
DrawWorldPreUnit)

- add new callins DrawUnitsPostDeferred and DrawFeaturesPostDeferred
these run at the end of their respective deferred passes to inform
Lua code it should make use of the $model_gbuffer_* textures before
another pass overwrites them (and to allow proper blending with e.g.
cloaked objects which are drawn between these events and DrawWorld)

- allow Lua to disable the forward {Unit,Feature,Ground}Drawer passes;
use the callouts
Spring.SetDrawGroundDeferred(
Expand Down
17 changes: 10 additions & 7 deletions rts/Game/GameHelper.cpp
Expand Up @@ -108,14 +108,14 @@ void CGameHelper::DoExplosionDamage(
if (ignoreOwner && (unit == owner))
return;

const LocalModelPiece* lap = unit->GetLastAttackedPiece(gs->frameNum);
const CollisionVolume* vol = unit->GetCollisionVolume(lap);
const LocalModelPiece* lhp = unit->GetLastHitPiece(gs->frameNum);
const CollisionVolume* vol = unit->GetCollisionVolume(lhp);

const float3& lapPos = (lap != NULL && vol == lap->GetCollisionVolume())? lap->GetAbsolutePos(): ZeroVector;
const float3& volPos = vol->GetWorldSpacePos(unit, lapPos);
const float3& lhpPos = (lhp != NULL && vol == lhp->GetCollisionVolume())? lhp->GetAbsolutePos(): ZeroVector;
const float3& volPos = vol->GetWorldSpacePos(unit, lhpPos);

// linear damage falloff with distance
const float expDist = (expRadius != 0.0f) ? vol->GetPointSurfaceDistance(unit, lap, expPos) : 0.0f;
const float expDist = (expRadius != 0.0f) ? vol->GetPointSurfaceDistance(unit, lhp, expPos) : 0.0f;
const float expRim = expDist * expEdgeEffect;

// return early if (distance > radius)
Expand Down Expand Up @@ -164,8 +164,11 @@ void CGameHelper::DoExplosionDamage(
) {
assert(feature != NULL);

const CollisionVolume* vol = feature->GetCollisionVolume(NULL);
const float3& volPos = vol->GetWorldSpacePos(feature, ZeroVector);
const LocalModelPiece* lhp = feature->GetLastHitPiece(gs->frameNum);
const CollisionVolume* vol = feature->GetCollisionVolume(lhp);

const float3& lhpPos = (lhp != NULL && vol == lhp->GetCollisionVolume())? lhp->GetAbsolutePos(): ZeroVector;
const float3& volPos = vol->GetWorldSpacePos(feature, lhpPos);

const float expDist = (expRadius != 0.0f) ? vol->GetPointSurfaceDistance(feature, NULL, expPos) : 0.0f;
const float expRim = expDist * expEdgeEffect;
Expand Down
36 changes: 19 additions & 17 deletions rts/Game/TraceRay.cpp
Expand Up @@ -203,7 +203,7 @@ float TraceRay(
if (!f->HasCollidableStateBit(CSolidObject::CSTATE_BIT_QUADMAPRAYS))
continue;

if (CCollisionHandler::DetectHit(f, start, start + dir * length, &cq, true)) {
if (CCollisionHandler::DetectHit(f, f->GetTransformMatrix(true), start, start + dir * length, &cq, true)) {
const float len = cq.GetHitPosDist(start, dir);

// we want the closest feature (intersection point) on the ray
Expand Down Expand Up @@ -236,7 +236,7 @@ float TraceRay(
if (ignoreCloaked && u->IsCloaked())
continue;

if (CCollisionHandler::DetectHit(u, start, start + dir * length, &cq, true)) {
if (CCollisionHandler::DetectHit(u, u->GetTransformMatrix(true), start, start + dir * length, &cq, true)) {
const float len = cq.GetHitPosDist(start, dir);

// we want the closest unit (intersection point) on the ray
Expand Down Expand Up @@ -312,38 +312,38 @@ float GuiTraceRay(
const CQuadField::Quad& quad = quadField->GetQuad(quadIdx);

// Unit Intersection
for (CUnit* unit: quad.units) {
const bool unitIsEnemy = !teamHandler->Ally(unit->allyteam, gu->myAllyTeam);
const bool unitOnRadar = (useRadar && losHandler->InRadar(unit, gu->myAllyTeam));
const bool unitInSight = (unit->losStatus[gu->myAllyTeam] & (LOS_INLOS | LOS_CONTRADAR));
for (CUnit* u: quad.units) {
const bool unitIsEnemy = !teamHandler->Ally(u->allyteam, gu->myAllyTeam);
const bool unitOnRadar = (useRadar && losHandler->InRadar(u, gu->myAllyTeam));
const bool unitInSight = (u->losStatus[gu->myAllyTeam] & (LOS_INLOS | LOS_CONTRADAR));
const bool unitVisible = !unitIsEnemy || unitOnRadar || unitInSight || gu->spectatingFullView;

if (unit == exclude)
if (u == exclude)
continue;
// test this bit only in synced traces, rely on noSelect here
if (false && !unit->HasCollidableStateBit(CSolidObject::CSTATE_BIT_QUADMAPRAYS))
if (false && !u->HasCollidableStateBit(CSolidObject::CSTATE_BIT_QUADMAPRAYS))
continue;
if (unit->noSelect)
if (u->noSelect)
continue;
if (!unitVisible)
continue;

CollisionVolume cv(unit->collisionVolume);
CollisionVolume cv = u->collisionVolume;

if (unit->isIcon || (!unitInSight && unitOnRadar && unitIsEnemy)) {
// for iconified units, just pretend the collision
if (u->isIcon || (!unitInSight && unitOnRadar && unitIsEnemy)) {
// for iconified us, just pretend the collision
// volume is a sphere of radius <unit->IconRadius>
// (count radar blips as such too)
cv.InitSphere(unit->iconRadius);
cv.InitSphere(u->iconRadius);
}

if (CCollisionHandler::MouseHit(unit, start, start + dir * guiRayLength, &cv, &cq)) {
if (CCollisionHandler::MouseHit(u, u->GetTransformMatrix(false), start, start + dir * guiRayLength, &cv, &cq)) {
// get the distance to the ray-volume ingress point
// (not likely to generate inside-hit special cases)
const float ingressDist = cq.GetIngressPosDist(start, dir);
const float egressDist = cq.GetEgressPosDist(start, dir);

const bool factoryUnderCursor = unit->unitDef->IsFactoryUnit();
const bool factoryUnderCursor = u->unitDef->IsFactoryUnit();
const bool factoryHitBeforeUnit = ((hitFactory && ingressDist < minIngressDist) || (!hitFactory && egressDist < minIngressDist));
const bool unitHitInsideFactory = ((hitFactory && ingressDist < minEgressDist) || (!hitFactory && ingressDist < minIngressDist));

Expand All @@ -353,7 +353,7 @@ float GuiTraceRay(
minIngressDist = ingressDist;
minEgressDist = egressDist;

hitUnit = unit;
hitUnit = u;
hitFeature = NULL;
}
}
Expand All @@ -369,7 +369,9 @@ float GuiTraceRay(
if (f->noSelect)
continue;

if (CCollisionHandler::DetectHit(f, start, start + dir * guiRayLength, &cq, true)) {
CollisionVolume cv = f->collisionVolume;

if (CCollisionHandler::MouseHit(f, f->GetTransformMatrix(false), start, start + dir * guiRayLength, &cv, &cq)) {
const float hitDist = cq.GetHitPosDist(start, dir);

const bool factoryHitBeforeUnit = ( hitFactory && hitDist < minEgressDist);
Expand Down
14 changes: 8 additions & 6 deletions rts/Lua/LuaObjectRendering.cpp
Expand Up @@ -163,17 +163,18 @@ int LuaObjectRenderingImpl::SetLODDistance(lua_State* L)

int LuaObjectRenderingImpl::SetPieceList(lua_State* L)
{
CUnit* unit = ParseUnit(L, __FUNCTION__, 1);
if (unit == nullptr)
CSolidObject* obj = ParseSolidObject(L, __FUNCTION__, 1, GetObjectType());

if (obj == nullptr)
return 0;

const unsigned int lod = luaL_checknumber(L, 2) - 1;
LocalModelPiece* localPiece = ParseUnitLocalModelPiece(L, unit, 3);
const LuaObjectMaterialData* lmd = obj->GetLuaMaterialData();
LocalModelPiece* localPiece = ParseObjectLocalModelPiece(L, obj, 3);

if (localPiece == nullptr)
return 0;

const LuaObjectMaterialData* lmd = unit->GetLuaMaterialData();
const unsigned int lod = luaL_checknumber(L, 2) - 1;

if (lod >= lmd->GetLODCount())
return 0;
Expand All @@ -184,7 +185,8 @@ int LuaObjectRenderingImpl::SetPieceList(lua_State* L)
CLuaDisplayLists& displayLists = CLuaHandle::GetActiveDisplayLists(L);
dlist = displayLists.GetDList(luaL_checknumber(L, 4));
} else {
dlist = localPiece->dispListID; // set to the default
// set to the default
dlist = localPiece->dispListID;
}

localPiece->lodDispLists[lod] = dlist;
Expand Down
9 changes: 4 additions & 5 deletions rts/Lua/LuaObjectRendering.h
Expand Up @@ -32,7 +32,6 @@ class LuaObjectRenderingImpl {
static int SetLODLength(lua_State* L);
static int SetLODDistance(lua_State* L);

// LUAOBJ_UNIT only
static int SetPieceList(lua_State* L);

static int GetMaterial(lua_State* L);
Expand Down Expand Up @@ -107,10 +106,10 @@ template<LuaObjType T> class LuaObjectRendering {


static int SetPieceList(lua_State* L) {
if (T != LUAOBJ_UNIT)
return 0;

return (LuaObjectRenderingImpl::SetPieceList(L));
LuaObjectRenderingImpl::PushObjectType(T);
const int ret = LuaObjectRenderingImpl::SetPieceList(L);
LuaObjectRenderingImpl::PopObjectType();
return ret;
}


Expand Down
11 changes: 6 additions & 5 deletions rts/Lua/LuaOpenGL.cpp
Expand Up @@ -1442,17 +1442,17 @@ int LuaOpenGL::UnitMultMatrix(lua_State* L)

int LuaOpenGL::UnitPiece(lua_State* L)
{
CUnit* unit = ParseUnit(L, __FUNCTION__, 1);
const CUnit* unit = ParseUnit(L, __FUNCTION__, 1);

if (unit == nullptr)
return 0;

LocalModelPiece* localPiece = ParseUnitLocalModelPiece(L, unit, 2);
const LocalModelPiece* localPiece = ParseObjectLocalModelPiece(L, unit, 2);

if (localPiece == nullptr)
return 0;

glCallList(localPiece->dispListID);

return 0;
}

Expand All @@ -1466,11 +1466,12 @@ int LuaOpenGL::UnitPieceMultMatrix(lua_State* L)
{
CheckDrawingEnabled(L, __FUNCTION__);

CUnit* unit = ParseUnit(L, __FUNCTION__, 1);
const CUnit* unit = ParseUnit(L, __FUNCTION__, 1);

if (unit == nullptr)
return 0;

LocalModelPiece* localPiece = ParseUnitLocalModelPiece(L, unit, 2);
const LocalModelPiece* localPiece = ParseObjectLocalModelPiece(L, unit, 2);

if (localPiece == nullptr)
return 0;
Expand Down
59 changes: 35 additions & 24 deletions rts/Lua/LuaSyncedCtrl.cpp
Expand Up @@ -584,6 +584,30 @@ static int SetSolidObjectPhysicalState(lua_State* L, CSolidObject* o)
return 0;
}

static int SetSolidObjectPieceCollisionVolumeData(lua_State* L, CSolidObject* obj)
{
if (obj == NULL)
return 0;

LocalModelPiece* lmp = ParseObjectLocalModelPiece(L, obj, 2);

if (lmp == nullptr)
luaL_argerror(L, 2, "invalid piece");

CollisionVolume* vol = lmp->GetCollisionVolume();

const float3 scales(luaL_checkfloat(L, 4), luaL_checkfloat(L, 5), luaL_checkfloat(L, 6));
const float3 offset(luaL_checkfloat(L, 7), luaL_checkfloat(L, 8), luaL_checkfloat(L, 9));

const unsigned int vType = luaL_optint(L, 10, vol->GetVolumeType());
const unsigned int pAxis = luaL_optint(L, 11, vol->GetPrimaryAxis());

// piece volumes are not allowed to use discrete hit-testing
vol->InitShape(scales, offset, vType, CollisionVolume::COLVOL_HITTEST_CONT, pAxis);
vol->SetIgnoreHits(!luaL_checkboolean(L, 3));
return 0;
}

static int SetWorldObjectAlwaysVisible(lua_State* L, CWorldObject* o, const char* caller)
{
if (o == NULL)
Expand Down Expand Up @@ -2109,13 +2133,13 @@ int LuaSyncedCtrl::SetUnitPieceParent(lua_State* L)
if (unit == NULL)
return 0;

LocalModelPiece* lmpAlteredPiece = ParseUnitLocalModelPiece(L, unit, 2);
LocalModelPiece* lmpAlteredPiece = ParseObjectLocalModelPiece(L, unit, 2);
if (lmpAlteredPiece == nullptr) {
luaL_error(L, "invalid piece");
return 0;
}

LocalModelPiece* lmpParentPiece = ParseUnitLocalModelPiece(L, unit, 3);
LocalModelPiece* lmpParentPiece = ParseObjectLocalModelPiece(L, unit, 3);
if (lmpParentPiece == nullptr) {
luaL_error(L, "invalid parent piece");
return 0;
Expand All @@ -2132,35 +2156,15 @@ int LuaSyncedCtrl::SetUnitPieceParent(lua_State* L)
return 0;
}


int LuaSyncedCtrl::SetUnitCollisionVolumeData(lua_State* L)
{
return (SetSolidObjectCollisionVolumeData(L, ParseUnit(L, __FUNCTION__, 1)));
}

int LuaSyncedCtrl::SetUnitPieceCollisionVolumeData(lua_State* L)
{
CUnit* unit = ParseUnit(L, __FUNCTION__, 1);

if (unit == NULL)
return 0;

LocalModelPiece* lmp = ParseUnitLocalModelPiece(L, unit, 2);

if (lmp == nullptr)
luaL_argerror(L, 2, "invalid piece");

CollisionVolume* vol = lmp->GetCollisionVolume();

const float3 scales(luaL_checkfloat(L, 4), luaL_checkfloat(L, 5), luaL_checkfloat(L, 6));
const float3 offset(luaL_checkfloat(L, 7), luaL_checkfloat(L, 8), luaL_checkfloat(L, 9));

const unsigned int vType = luaL_optint(L, 10, vol->GetVolumeType());
const unsigned int pAxis = luaL_optint(L, 11, vol->GetPrimaryAxis());

// piece volumes are not allowed to use discrete hit-testing
vol->InitShape(scales, offset, vType, CollisionVolume::COLVOL_HITTEST_CONT, pAxis);
vol->SetIgnoreHits(!luaL_checkboolean(L, 3));
return 0;
return (SetSolidObjectPieceCollisionVolumeData(L, ParseUnit(L, __FUNCTION__, 1)));
}


Expand Down Expand Up @@ -2800,11 +2804,18 @@ int LuaSyncedCtrl::SetFeatureRadiusAndHeight(lua_State* L)
return 1;
}


int LuaSyncedCtrl::SetFeatureCollisionVolumeData(lua_State* L)
{
return (SetSolidObjectCollisionVolumeData(L, ParseFeature(L, __FUNCTION__, 1)));
}

int LuaSyncedCtrl::SetFeaturePieceCollisionVolumeData(lua_State* L)
{
return (SetSolidObjectPieceCollisionVolumeData(L, ParseFeature(L, __FUNCTION__, 1)));
}


/******************************************************************************/
/******************************************************************************/

Expand Down
1 change: 1 addition & 0 deletions rts/Lua/LuaSyncedCtrl.h
Expand Up @@ -125,6 +125,7 @@ class LuaSyncedCtrl
static int SetFeatureMidAndAimPos(lua_State* L);
static int SetFeatureRadiusAndHeight(lua_State* L);
static int SetFeatureCollisionVolumeData(lua_State* L);
static int SetFeaturePieceCollisionVolumeData(lua_State* L);

static int SetProjectileAlwaysVisible(lua_State* L);
static int SetProjectileMoveControl(lua_State* L);
Expand Down

4 comments on commit e22aeb5

@jk3064
Copy link
Contributor

@jk3064 jk3064 commented on e22aeb5 Dec 3, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:D

@ashdnazg
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
What prevents us at the moment from combining FeatureDrawer and UnitDrawer?

@rtri
Copy link
Contributor

@rtri rtri commented on e22aeb5 Dec 3, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not much. Unifying them has been on my todo-list for a long time, there is just less immediate payoff to it.

@FLOZi
Copy link
Contributor

@FLOZi FLOZi commented on e22aeb5 Dec 3, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.