这是故障代码。。
multresult := mult(mult(temp, quatview), conjugate(temp));
全过程
procedure TForm2.RotateCamera(var angle: Single; x: Single; y: Single; z: Single);
var
temp, QuatView, multResult : TQuaternion;
begin
temp.x := x * sin(Angle/2);
temp.y := y * sin(Angle/2);
temp.z := z * sin(Angle/2);
temp.w := cos(Angle/2);
quatview.x := camera1.Position.x;
quatview.y := camera1.Position.y;
quatview.z := camera1.Position.z;
quatview.w := 0;
multresult := mult(mult(temp, quatview), conjugate(temp));
camera1.Position.x := multresult.x;
camera1.Position.y := multresult.y;
camera1.Position.z := multresult.z;
end;
多功能
function TForm2.mult(var A: TQuaternion; B: TQuaternion) :TQuaternion;
var
c : TQuaternion;
begin
C.x := A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y;
C.y := A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x;
C.z := A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w;
C.w := A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z;
result := C;
End;
和共轭
function TForm2.conjugate( var quat:TQuaternion) :TQuaternion;
begin
quat.x := -quat.x;
quat.y := -quat.y;
quat.z := -quat.z;
result := quat;
end;
如果需要,TQuaternion
type
TQuaternion = class
x: single;
y: single;
z: single;
w: single;
end;
知道我为什么会出现这个错误以及如何修复它吗?
您所问问题的答案是mult的参数应该是const。你不会修改它们(也不应该修改),所以让它们const。然后编译您的代码。
同样,共轭修改其输入参数也是一种糟糕的形式。这使得函数使用起来很可怕。不要那样做。
考虑这一行:
multresult := mult(mult(temp, quatview), conjugate(temp) );
由于共轭修改了temp,您最好希望在其他使用temp之后调用共轭。该语言没有这样的保证。所以,祈祷吧!
算术代码值得遵循的原则之一是,永远不应该修改输入参数/操作数,并且函数总是返回新的值。遵循这个原则,你就永远不会陷入上面强调的陷阱。请参阅我答案的第二部分以获取说明。
但是,即使进行了这些更改,代码也无法工作,因为您没有实例化TQuaternion类的任何实例。你确定这不是唱片吗?
当你创建一个好的四元数类型时,真正的进步就会到来。这应该是一种值类型,因为算术运算更适合于值类型,原因有很多。
在现代Delphi中,您希望使用带有运算符的记录。这是你需要的口味,随时可以根据需要扩展。
type
TQuaternion = record
x: single;
y: single;
z: single;
w: single;
function Conjugate: TQuaternion;
class operator Multiply(const A, B: TQuaternion): TQuaternion;
end;
function TQuaternion.Conjugate: TQuaternion;
begin
Result.x := -x;
Result.y := -y;
Result.z := -z;
Result.w := w;
end;
class operator TQuaternion.Multiply(const A, B: TQuaternion): TQuaternion;
begin
Result.x := A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y;
Result.y := A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x;
Result.z := A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w;
Result.w := A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z;
end;
使用这种类型,您的乘法调用变为:
multresult := temp*quatview*temp.Conjugate;
您肯定需要为这种类型编写更多的运算符和辅助函数。
将算术函数移入这种类型和移出表单非常重要。不要使用高级GUI表单类来实现低级算术。
最后一条建议。您的代码重复错误使用var参数。我建议您将var参数视为需要避免的事情。如果可能的话,试着在没有它们的情况下编写代码。
mult
方法将A
参数声明为var
,因此您必须向该方法传递一个变量才能工作,就像这样。
multresult := mult(temp, quatview);
multresult := mult(multresult, conjugate(temp));