Add atan2, which was conspicuously absent, to the VM
- DECORATE now has atan2(y,x) and VectorAngle(x,y) functions. They are identical except for the order of their parameters. The returned angle is in degrees (not radians).
This commit is contained in:
parent
30a530b178
commit
e83bc53678
6 changed files with 135 additions and 0 deletions
|
|
@ -1991,6 +1991,99 @@ ExpEmit FxAbs::Emit(VMFunctionBuilder *build)
|
|||
return out;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
FxATan2::FxATan2(FxExpression *y, FxExpression *x, const FScriptPosition &pos)
|
||||
: FxExpression(pos)
|
||||
{
|
||||
yval = y;
|
||||
xval = x;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
FxATan2::~FxATan2()
|
||||
{
|
||||
SAFE_DELETE(yval);
|
||||
SAFE_DELETE(xval);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
FxExpression *FxATan2::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(yval, ctx);
|
||||
SAFE_RESOLVE(xval, ctx);
|
||||
|
||||
if (!yval->IsNumeric() || !xval->IsNumeric())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter");
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
if (yval->isConstant() && xval->isConstant())
|
||||
{
|
||||
double y = static_cast<FxConstant *>(yval)->GetValue().GetFloat();
|
||||
double x = static_cast<FxConstant *>(xval)->GetValue().GetFloat();
|
||||
FxExpression *z = new FxConstant(g_atan2(y, x) * (180 / M_PI), ScriptPosition);
|
||||
delete this;
|
||||
return z;
|
||||
}
|
||||
if (yval->ValueType->GetRegType() != REGT_FLOAT && !yval->isConstant())
|
||||
{
|
||||
yval = new FxFloatCast(yval);
|
||||
}
|
||||
if (xval->ValueType->GetRegType() != REGT_FLOAT && !xval->isConstant())
|
||||
{
|
||||
xval = new FxFloatCast(xval);
|
||||
}
|
||||
ValueType = TypeFloat64;
|
||||
return this;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
ExpEmit FxATan2::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit yreg = ToReg(build, yval);
|
||||
ExpEmit xreg = ToReg(build, xval);
|
||||
yreg.Free(build);
|
||||
xreg.Free(build);
|
||||
ExpEmit out(build, REGT_FLOAT);
|
||||
build->Emit(OP_ATAN2, out.RegNum, yreg.RegNum, xreg.RegNum);
|
||||
return out;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue