mirror of
https://github.com/ZDoom/Raze.git
synced 2025-05-31 09:20:59 +00:00
- Backend update from GZDoom.
Bone model support in GLES and ZScript quaternions.
This commit is contained in:
parent
c94d2fb3d0
commit
6e49f0bf8f
17 changed files with 250 additions and 61 deletions
|
@ -809,6 +809,34 @@ ExpEmit FxVectorValue::Emit(VMFunctionBuilder *build)
|
|||
return out;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxQuaternionValue::FxQuaternionValue(FxExpression* x, FxExpression* y, FxExpression* z, FxExpression* w, const FScriptPosition& sc) : FxVectorValue(x, y, z, w, sc)
|
||||
{
|
||||
}
|
||||
|
||||
FxExpression* FxQuaternionValue::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
auto base = FxVectorValue::Resolve(ctx);
|
||||
if (base)
|
||||
{
|
||||
if (base->ValueType->GetRegCount() != 4)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Quat expression requires 4 arguments, got %d instead", base->ValueType->GetRegCount());
|
||||
delete base;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
base->ValueType = TypeQuaternion;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -1727,7 +1755,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
|||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if ((basex->IsVector2() && IsVector2()) || (basex->IsVector3() && IsVector3()) || (basex->IsVector4() && IsVector4()))
|
||||
else if ((basex->IsVector2() && IsVector2()) || (basex->IsVector3() && IsVector3()) || (basex->IsVector4() && IsVector4()) || (basex->IsQuaternion() && IsQuaternion()))
|
||||
{
|
||||
auto x = basex;
|
||||
basex = nullptr;
|
||||
|
@ -1799,7 +1827,7 @@ FxExpression *FxPlusSign::Resolve(FCompileContext& ctx)
|
|||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(Operand, ctx);
|
||||
|
||||
if (Operand->IsNumeric() || Operand->IsVector())
|
||||
if (Operand->IsNumeric() || Operand->IsVector() || Operand->IsQuaternion())
|
||||
{
|
||||
FxExpression *e = Operand;
|
||||
Operand = nullptr;
|
||||
|
@ -1853,7 +1881,7 @@ FxExpression *FxMinusSign::Resolve(FCompileContext& ctx)
|
|||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(Operand, ctx);
|
||||
|
||||
if (Operand->IsNumeric() || Operand->IsVector())
|
||||
if (Operand->IsNumeric() || Operand->IsVector() || Operand->IsQuaternion())
|
||||
{
|
||||
if (Operand->isConstant())
|
||||
{
|
||||
|
@ -2441,7 +2469,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
|
|||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
if (!Base->IsVector() && Base->ValueType->isStruct())
|
||||
if (!Base->IsVector() && !Base->IsQuaternion() && Base->ValueType->isStruct())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Struct assignment not implemented yet");
|
||||
delete this;
|
||||
|
@ -2839,6 +2867,10 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
ValueType = TypeTextureID;
|
||||
}
|
||||
else if (left->IsQuaternion() && right->IsQuaternion())
|
||||
{
|
||||
ValueType = left->ValueType;
|
||||
}
|
||||
else if (left->IsVector() && right->IsVector())
|
||||
{
|
||||
// a vector2 can be added to or subtracted from a vector 3 but it needs to be the right operand.
|
||||
|
@ -2944,6 +2976,13 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build)
|
|||
}
|
||||
return to;
|
||||
}
|
||||
else if (IsQuaternion())
|
||||
{
|
||||
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
||||
assert(op1.RegCount == 4 && op2.RegCount == 4);
|
||||
build->Emit(OP_ADDV4_RR, to.RegNum, op1.RegNum, op2.RegNum);
|
||||
return to;
|
||||
}
|
||||
else if (ValueType->GetRegType() == REGT_FLOAT)
|
||||
{
|
||||
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
||||
|
@ -2972,6 +3011,13 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build)
|
|||
build->Emit(right->IsVector4() ? OP_SUBV4_RR : right->IsVector3() ? OP_SUBV3_RR : OP_SUBV2_RR, to.RegNum, op1.RegNum, op2.RegNum);
|
||||
return to;
|
||||
}
|
||||
else if (IsQuaternion())
|
||||
{
|
||||
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
||||
assert(op1.RegCount == 4 && op2.RegCount == 4);
|
||||
build->Emit(OP_SUBV4_RR, to.RegNum, op1.RegNum, op2.RegNum);
|
||||
return to;
|
||||
}
|
||||
else if (ValueType->GetRegType() == REGT_FLOAT)
|
||||
{
|
||||
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
||||
|
@ -3037,7 +3083,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (left->IsVector() || right->IsVector())
|
||||
if (left->IsVector() || right->IsVector() || left->IsQuaternion() || right->IsQuaternion())
|
||||
{
|
||||
switch (Operator)
|
||||
{
|
||||
|
@ -3047,7 +3093,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
|||
[[fallthrough]];
|
||||
|
||||
case '*':
|
||||
if (left->IsVector() && right->IsNumeric())
|
||||
if ((left->IsVector() || left->IsQuaternion()) && right->IsNumeric())
|
||||
{
|
||||
if (right->IsInteger())
|
||||
{
|
||||
|
@ -3062,7 +3108,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
|||
ValueType = left->ValueType;
|
||||
break;
|
||||
}
|
||||
else if (right->IsVector() && left->IsNumeric())
|
||||
else if ((right->IsVector() || right->IsQuaternion()) && left->IsNumeric())
|
||||
{
|
||||
if (left->IsInteger())
|
||||
{
|
||||
|
@ -3162,7 +3208,7 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit op1 = left->Emit(build);
|
||||
ExpEmit op2 = right->Emit(build);
|
||||
|
||||
if (IsVector())
|
||||
if (IsVector() || IsQuaternion())
|
||||
{
|
||||
assert(Operator != '%');
|
||||
if (right->IsVector())
|
||||
|
@ -3641,7 +3687,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
|
||||
// identical types are always comparable, if they can be placed in a register, so we can save most checks if this is the case.
|
||||
if (left->ValueType != right->ValueType && !(left->IsVector2() && right->IsVector2()) && !(left->IsVector3() && right->IsVector3()) && !(left->IsVector4() && right->IsVector4()))
|
||||
if (left->ValueType != right->ValueType && !(left->IsVector2() && right->IsVector2()) && !(left->IsVector3() && right->IsVector3()) && !(left->IsVector4() && right->IsVector4()) && !(left->IsQuaternion() && right->IsQuaternion()))
|
||||
{
|
||||
FxExpression *x;
|
||||
if (left->IsNumeric() && right->ValueType == TypeString && (x = StringConstToChar(right)))
|
||||
|
@ -7139,7 +7185,7 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
|
|||
classx = nullptr;
|
||||
return x;
|
||||
}
|
||||
else if (classx->ExprType == EFX_LocalVariable && classx->IsVector()) // vectors are a special case because they are held in registers
|
||||
else if (classx->ExprType == EFX_LocalVariable && (classx->IsVector() || classx->IsQuaternion())) // vectors are a special case because they are held in registers
|
||||
{
|
||||
// since this is a vector, all potential things that may get here are single float or an xy-vector.
|
||||
auto locvar = static_cast<FxLocalVariable *>(classx);
|
||||
|
@ -8058,6 +8104,25 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
break;
|
||||
|
||||
case NAME_FQuat:
|
||||
case NAME_Quat:
|
||||
if (CheckArgSize(MethodName, ArgList, 1, 4, ScriptPosition))
|
||||
{
|
||||
// Reuse vector expression
|
||||
func = new FxQuaternionValue(
|
||||
ArgList[0],
|
||||
ArgList.Size() >= 2 ? ArgList[1] : nullptr,
|
||||
ArgList.Size() >= 3 ? ArgList[2] : nullptr,
|
||||
ArgList.Size() >= 4 ? ArgList[3] : nullptr,
|
||||
ScriptPosition
|
||||
);
|
||||
ArgList.Clear();
|
||||
|
||||
delete this;
|
||||
auto vector = func->Resolve(ctx);
|
||||
return vector;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars());
|
||||
|
@ -8273,7 +8338,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
else if (Self->IsVector())
|
||||
{
|
||||
// handle builtins: Vectors got 5.
|
||||
if (MethodName == NAME_Length || MethodName == NAME_LengthSquared || MethodName == NAME_Sum || MethodName == NAME_Unit || MethodName == NAME_Angle)
|
||||
if (MethodName == NAME_Length || MethodName == NAME_LengthSquared || MethodName == NAME_Unit || MethodName == NAME_Angle)
|
||||
{
|
||||
if (ArgList.Size() > 0)
|
||||
{
|
||||
|
@ -8301,6 +8366,24 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
return x->Resolve(ctx);
|
||||
}
|
||||
}
|
||||
else if (Self->IsQuaternion())
|
||||
{
|
||||
// Reuse vector built-ins for quaternion
|
||||
if (MethodName == NAME_Length || MethodName == NAME_LengthSquared || MethodName == NAME_Unit)
|
||||
{
|
||||
if (ArgList.Size() > 0)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Too many parameters in call to %s", MethodName.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
auto x = new FxVectorBuiltin(Self, MethodName);
|
||||
Self = nullptr;
|
||||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else if (Self->ValueType == TypeString)
|
||||
{
|
||||
|
@ -9275,13 +9358,14 @@ FxVectorBuiltin::~FxVectorBuiltin()
|
|||
FxExpression *FxVectorBuiltin::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
SAFE_RESOLVE(Self, ctx);
|
||||
assert(Self->IsVector()); // should never be created for anything else.
|
||||
assert(Self->IsVector() || Self->IsQuaternion()); // should never be created for anything else.
|
||||
switch (Function.GetIndex())
|
||||
{
|
||||
case NAME_Angle:
|
||||
assert(Self->IsVector());
|
||||
case NAME_Length:
|
||||
case NAME_LengthSquared:
|
||||
case NAME_Sum:
|
||||
case NAME_Angle:
|
||||
ValueType = TypeFloat64;
|
||||
break;
|
||||
|
||||
|
@ -10691,7 +10775,7 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx)
|
|||
else if (retCount == 1)
|
||||
{
|
||||
// If we already know the real return type we need at least try to cast the value to its proper type (unless in an anonymous function.)
|
||||
if (hasProto && protoRetCount > 0 && ctx.Function->SymbolName != NAME_None)
|
||||
if (hasProto && protoRetCount > 0 && ctx.Function->SymbolName != NAME_None && Args[0]->ValueType != ctx.ReturnProto->ReturnTypes[0])
|
||||
{
|
||||
Args[0] = new FxTypeCast(Args[0], ctx.ReturnProto->ReturnTypes[0], false, false);
|
||||
Args[0] = Args[0]->Resolve(ctx);
|
||||
|
@ -10701,11 +10785,15 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx)
|
|||
}
|
||||
else
|
||||
{
|
||||
assert(ctx.ReturnProto != nullptr);
|
||||
for (unsigned i = 0; i < retCount; i++)
|
||||
{
|
||||
Args[i] = new FxTypeCast(Args[i], ctx.ReturnProto->ReturnTypes[i], false, false);
|
||||
Args[i] = Args[i]->Resolve(ctx);
|
||||
if (Args[i] == nullptr) fail = true;
|
||||
if (Args[i]->ValueType != ctx.ReturnProto->ReturnTypes[i])
|
||||
{
|
||||
Args[i] = new FxTypeCast(Args[i], ctx.ReturnProto->ReturnTypes[i], false, false);
|
||||
Args[i] = Args[i]->Resolve(ctx);
|
||||
if (Args[i] == nullptr) fail = true;
|
||||
}
|
||||
}
|
||||
if (fail)
|
||||
{
|
||||
|
@ -11083,6 +11171,7 @@ FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name,
|
|||
if (type == TypeFVector2) type = TypeVector2;
|
||||
else if (type == TypeFVector3) type = TypeVector3;
|
||||
else if (type == TypeFVector4) type = TypeVector4;
|
||||
else if (type == TypeFQuaternion) type = TypeQuaternion;
|
||||
|
||||
ValueType = type;
|
||||
VarFlags = varflags;
|
||||
|
|
|
@ -343,6 +343,7 @@ public:
|
|||
bool IsVector2() const { return ValueType == TypeVector2 || ValueType == TypeFVector2; };
|
||||
bool IsVector3() const { return ValueType == TypeVector3 || ValueType == TypeFVector3; };
|
||||
bool IsVector4() const { return ValueType == TypeVector4 || ValueType == TypeFVector4; };
|
||||
bool IsQuaternion() const { return ValueType == TypeQuaternion || ValueType == TypeFQuaternion; };
|
||||
bool IsBoolCompat() const { return ValueType->isScalar(); }
|
||||
bool IsObject() const { return ValueType->isObjectPointer(); }
|
||||
bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); }
|
||||
|
@ -577,6 +578,20 @@ public:
|
|||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxQuaternionValue : public FxVectorValue
|
||||
{
|
||||
public:
|
||||
FxQuaternionValue(FxExpression* x, FxExpression* y, FxExpression* z, FxExpression* w, const FScriptPosition& sc);
|
||||
FxExpression* Resolve(FCompileContext&);
|
||||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue