mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-29 15:22:08 +00:00
- added LengthSquared and Angle intrinsics for all vector types, also allow calling VectorAngle with a full vector as a single parameter.
This commit is contained in:
parent
54f1cabed9
commit
f3b33f7cf8
4 changed files with 126 additions and 24 deletions
|
@ -151,7 +151,9 @@ xx(stateinfo)
|
||||||
|
|
||||||
xx(DamageFunction)
|
xx(DamageFunction)
|
||||||
xx(Length)
|
xx(Length)
|
||||||
|
xx(LengthSquared)
|
||||||
xx(Unit)
|
xx(Unit)
|
||||||
|
xx(Angle)
|
||||||
xx(Size)
|
xx(Size)
|
||||||
xx(Push)
|
xx(Push)
|
||||||
xx(Insert)
|
xx(Insert)
|
||||||
|
|
|
@ -5127,6 +5127,23 @@ FxExpression *FxATan2::Resolve(FCompileContext &ctx)
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// The atan2 opcode only takes registers as parameters, so any constants
|
||||||
|
// must be loaded into registers first.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
ExpEmit FxATan2::ToReg(VMFunctionBuilder* build, FxExpression* val)
|
||||||
|
{
|
||||||
|
if (val->isConstant())
|
||||||
|
{
|
||||||
|
ExpEmit reg(build, REGT_FLOAT);
|
||||||
|
build->Emit(OP_LKF, reg.RegNum, build->GetConstantFloat(static_cast<FxConstant*>(val)->GetValue().GetFloat()));
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
return val->Emit(build);
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -5143,6 +5160,61 @@ ExpEmit FxATan2::Emit(VMFunctionBuilder *build)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
FxATan2Vec::FxATan2Vec(FxExpression* v, const FScriptPosition& pos)
|
||||||
|
: FxExpression(EFX_ATan2Vec, pos)
|
||||||
|
{
|
||||||
|
vval = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
FxATan2Vec::~FxATan2Vec()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(vval);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
FxExpression* FxATan2Vec::Resolve(FCompileContext& ctx)
|
||||||
|
{
|
||||||
|
CHECKRESOLVED();
|
||||||
|
SAFE_RESOLVE(vval, ctx);
|
||||||
|
|
||||||
|
if (!vval->IsVector())
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "vector value expected for parameter");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
ValueType = TypeFloat64;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
ExpEmit FxATan2Vec::Emit(VMFunctionBuilder* build)
|
||||||
|
{
|
||||||
|
ExpEmit vreg = vval->Emit(build);
|
||||||
|
vreg.Free(build);
|
||||||
|
ExpEmit out(build, REGT_FLOAT);
|
||||||
|
build->Emit(OP_ATAN2, out.RegNum, vreg.RegNum + 1, vreg.RegNum);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -5278,23 +5350,6 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build)
|
||||||
return emitters.EmitCall(build);
|
return emitters.EmitCall(build);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// The atan2 opcode only takes registers as parameters, so any constants
|
|
||||||
// must be loaded into registers first.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
ExpEmit FxATan2::ToReg(VMFunctionBuilder *build, FxExpression *val)
|
|
||||||
{
|
|
||||||
if (val->isConstant())
|
|
||||||
{
|
|
||||||
ExpEmit reg(build, REGT_FLOAT);
|
|
||||||
build->Emit(OP_LKF, reg.RegNum, build->GetConstantFloat(static_cast<FxConstant*>(val)->GetValue().GetFloat()));
|
|
||||||
return reg;
|
|
||||||
}
|
|
||||||
return val->Emit(build);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -7967,11 +8022,19 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
case NAME_ATan2:
|
case NAME_ATan2:
|
||||||
case NAME_VectorAngle:
|
case NAME_VectorAngle:
|
||||||
if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition))
|
if (CheckArgSize(MethodName, ArgList, 1, 2, ScriptPosition))
|
||||||
|
{
|
||||||
|
if (ArgList.Size() == 2)
|
||||||
{
|
{
|
||||||
func = MethodName == NAME_ATan2 ? new FxATan2(ArgList[0], ArgList[1], ScriptPosition) : new FxATan2(ArgList[1], ArgList[0], ScriptPosition);
|
func = MethodName == NAME_ATan2 ? new FxATan2(ArgList[0], ArgList[1], ScriptPosition) : new FxATan2(ArgList[1], ArgList[0], ScriptPosition);
|
||||||
ArgList[0] = ArgList[1] = nullptr;
|
ArgList[0] = ArgList[1] = nullptr;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
func = new FxATan2Vec(ArgList[0], ScriptPosition);
|
||||||
|
ArgList[0] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_New:
|
case NAME_New:
|
||||||
|
@ -8201,7 +8264,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
else if (Self->IsVector())
|
else if (Self->IsVector())
|
||||||
{
|
{
|
||||||
// handle builtins: Vectors got 2: Length and Unit.
|
// handle builtins: Vectors got 2: Length and Unit.
|
||||||
if (MethodName == NAME_Length || MethodName == NAME_Unit)
|
if (MethodName == NAME_Length || MethodName == NAME_LengthSquared || MethodName == NAME_Unit || MethodName == NAME_Angle)
|
||||||
{
|
{
|
||||||
if (ArgList.Size() > 0)
|
if (ArgList.Size() > 0)
|
||||||
{
|
{
|
||||||
|
@ -9190,7 +9253,23 @@ FxExpression *FxVectorBuiltin::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
SAFE_RESOLVE(Self, ctx);
|
SAFE_RESOLVE(Self, ctx);
|
||||||
assert(Self->IsVector()); // should never be created for anything else.
|
assert(Self->IsVector()); // should never be created for anything else.
|
||||||
ValueType = Function == NAME_Length ? TypeFloat64 : Self->ValueType;
|
switch (Function.GetIndex())
|
||||||
|
{
|
||||||
|
case NAME_Length:
|
||||||
|
case NAME_LengthSquared:
|
||||||
|
case NAME_Angle:
|
||||||
|
ValueType = TypeFloat64;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAME_Unit:
|
||||||
|
ValueType = Self->ValueType;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ValueType = TypeError;
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9206,13 +9285,21 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
build->Emit(vecSize == 2 ? OP_LENV2 : vecSize == 3 ? OP_LENV3 : OP_LENV4, to.RegNum, op.RegNum);
|
build->Emit(vecSize == 2 ? OP_LENV2 : vecSize == 3 ? OP_LENV3 : OP_LENV4, to.RegNum, op.RegNum);
|
||||||
}
|
}
|
||||||
else
|
else if (Function == NAME_LengthSquared)
|
||||||
|
{
|
||||||
|
build->Emit(vecSize == 2 ? OP_DOTV2_RR : vecSize == 3 ? OP_DOTV3_RR : OP_DOTV4_RR, to.RegNum, op.RegNum, op.RegNum);
|
||||||
|
}
|
||||||
|
else if (Function == NAME_Unit)
|
||||||
{
|
{
|
||||||
ExpEmit len(build, REGT_FLOAT);
|
ExpEmit len(build, REGT_FLOAT);
|
||||||
build->Emit(vecSize == 2 ? OP_LENV2 : vecSize == 3 ? OP_LENV3 : OP_LENV4, len.RegNum, op.RegNum);
|
build->Emit(vecSize == 2 ? OP_LENV2 : vecSize == 3 ? OP_LENV3 : OP_LENV4, len.RegNum, op.RegNum);
|
||||||
build->Emit(vecSize == 2 ? OP_DIVVF2_RR : vecSize == 3 ? OP_DIVVF3_RR : OP_DIVVF4_RR, to.RegNum, op.RegNum, len.RegNum);
|
build->Emit(vecSize == 2 ? OP_DIVVF2_RR : vecSize == 3 ? OP_DIVVF3_RR : OP_DIVVF4_RR, to.RegNum, op.RegNum, len.RegNum);
|
||||||
len.Free(build);
|
len.Free(build);
|
||||||
}
|
}
|
||||||
|
else if (Function == NAME_Angle)
|
||||||
|
{
|
||||||
|
build->Emit(OP_ATAN2, to.RegNum, op.RegNum + 1, op.RegNum);
|
||||||
|
}
|
||||||
op.Free(build);
|
op.Free(build);
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,6 +248,7 @@ enum EFxType
|
||||||
EFX_Conditional,
|
EFX_Conditional,
|
||||||
EFX_Abs,
|
EFX_Abs,
|
||||||
EFX_ATan2,
|
EFX_ATan2,
|
||||||
|
EFX_ATan2Vec,
|
||||||
EFX_New,
|
EFX_New,
|
||||||
EFX_MinMax,
|
EFX_MinMax,
|
||||||
EFX_Random,
|
EFX_Random,
|
||||||
|
@ -1201,6 +1202,18 @@ private:
|
||||||
ExpEmit ToReg(VMFunctionBuilder *build, FxExpression *val);
|
ExpEmit ToReg(VMFunctionBuilder *build, FxExpression *val);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FxATan2Vec : public FxExpression
|
||||||
|
{
|
||||||
|
FxExpression* vval;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FxATan2Vec(FxExpression* y, const FScriptPosition& pos);
|
||||||
|
~FxATan2Vec();
|
||||||
|
FxExpression* Resolve(FCompileContext&);
|
||||||
|
ExpEmit Emit(VMFunctionBuilder* build);
|
||||||
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -481,7 +481,7 @@ xx(ResolveState)
|
||||||
|
|
||||||
// UDMF keywords (todo: take these out of the global name table
|
// UDMF keywords (todo: take these out of the global name table
|
||||||
xx(Alpha)
|
xx(Alpha)
|
||||||
xx(Angle)
|
//xx(Angle)
|
||||||
xx(Args)
|
xx(Args)
|
||||||
xx(CeilingZ)
|
xx(CeilingZ)
|
||||||
xx(FloorZ)
|
xx(FloorZ)
|
||||||
|
|
Loading…
Reference in a new issue