2013-08-18 1 views
7

Это код неисправности ..Постоянный объект не может быть передан в качестве параметра вар

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; 

любую идею, почему я получаю эту ошибку и как это исправить?

ответ

13

Ответ на заданный вами вопрос заключается в том, что параметры для mult должны быть const. Вы не изменяете их (и не должны), поэтому сделайте их const. Затем ваш код компилируется.

В том же духе, это плохая форма для Conjugate, чтобы изменить его входной параметр. Это делает функцию ужасной для использования. Не делай этого.

Рассмотрим следующую строку:

multresult := mult(mult(temp, quatview), conjugate(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 как вещи, которых следует избегать. По возможности попробуйте написать код без них.

+0

Спасибо, отличный совет. В то время как я попытаюсь использовать это снова ... на данный момент я должен выяснить, как использовать это с камерой firemonkey .. как FMX имеет положение (x, y, z) и rotateposition (x, y, z) Пока все В примерах я мог бы найти внешний вид opengl (positionx, y, z, viewx, y, z, upx, y, z), так что работая над этим. –

5

Метод mult объявляет параметр A как var, поэтому вы должны передать переменную методу для работы, например.

multresult := mult(temp, quatview); 
multresult := mult(multresult, conjugate(temp)); 
+0

Спасибо, не знал, что мне пришлось разделить его. –

+1

@GlenMorse Я думаю, что вы объявляете параметр как ** var ** из-за ошибки компиляции, если нет. Попытайтесь избавиться от этого var, и все будет хорошо –

+5

Я думаю, что этот ответ является несколько неглубоким анализом проблемы. Да, это изменение сделает компиляцию кода. Но после этого вы остаетесь с множеством дальнейших проблем. И даже тогда предлагаемое здесь решение плохое, поскольку первая ошибка для преодоления - ошибочное использование параметра var. Кажется, это повторяющаяся тема. –