forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   FAQ (http://forum.boolean.name/forumdisplay.php?f=15)
-   -   getMathElement() (http://forum.boolean.name/showthread.php?t=16625)

burovalex 11.04.2012 12:38

getMathElement()
 
Взял пример с хелпа

Код:

Graphics3D 640,480
SetBuffer BackBuffer()

camera=CreateCamera()
PositionEntity camera,0,0,-5

light=CreateLight()
RotateEntity light,90,0,0

sphere=CreateSphere()

PositionEntity sphere,0,0,0
ScaleEntity sphere,1,2,3
RotateEntity sphere,0,0,0

While Not KeyDown(1)
RenderWorld

Text 0,0,GetMatElement#(sphere,1,1)

Flip
Wend
End

Выводит двойку масштаба
Перебла все комбинации от 0-3, все остальные ноль :crazy:
Помогите чайнику :rolleyes:

Платон Александрович 11.04.2012 13:18

Ответ: getMathElement()
 
Цитата:

Сообщение от burovalex (Сообщение 225108)
Взял пример с хелпа

Код:

Graphics3D 640,480
SetBuffer BackBuffer()

camera=CreateCamera()
PositionEntity camera,0,0,-5

light=CreateLight()
RotateEntity light,90,0,0

sphere=CreateSphere()

PositionEntity sphere,0,0,0
ScaleEntity sphere,1,2,3
RotateEntity sphere,0,0,0

While Not KeyDown(1)
RenderWorld

Text 0,0,GetMatElement#(sphere,1,1)

Flip
Wend
End

Выводит двойку масштаба
Перебла все комбинации от 0-3, все остальные ноль :crazy:
Помогите чайнику :rolleyes:

Чайнику надо почитать про матрицы и вектора.

GetMatElement возвращает элемент матрицы трансформации энтити. Матрица квадратная порядка 4. Т.е. 4х4 - четыре 4-хмерных вектора.

Т.к. эта матрица трансформации комбинирует в себе масштаб, поворот и смещение, то просто так извлечь какую-то трансформацию нельзя.
В твоем случае, чтобы извлечь масштаб, надо взять длины векторов по каждой оси:

Код:

;  | 0 1 2 3
; ------------
; 0 | X Y Z W
; 1 | X Y Z W
; 2 | X Y Z W
; 3 | X Y Z W

; чистая матрица масштаба выглядит так:
; X 0 0 0
; 0 Y 0 0
; 0 0 Z 0
; 0 0 0 1

XAxisX# = GetMatElement ( Entity, 0, 0 )
XAxisY# = GetMatElement ( Entity, 0, 1 )
XAxisZ# = GetMatElement ( Entity, 0, 2 )

YAxisX# = GetMatElement ( Entity, 1, 0 )
YAxisY# = GetMatElement ( Entity, 1, 1 )
YAxisZ# = GetMatElement ( Entity, 1, 2 )

ZAxisX# = GetMatElement ( Entity, 2, 0 )
ZAxisY# = GetMatElement ( Entity, 2, 1 )
ZAxisZ# = GetMatElement ( Entity, 2, 2 )

ScaleX# = Sqr ( XAxisX * XAxisX + XAxisY * XAxisY + XAxisZ * XAxisZ )
ScaleY# = Sqr ( YAxisX * YAxisX + YAxisY * YAxisY + YAxisZ * YAxisZ )
ScaleZ# = Sqr ( ZAxisX * ZAxisX + ZAxisY * ZAxisY + ZAxisZ * ZAxisZ )

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

burovalex 11.04.2012 16:21

Ответ: getMathElement()
 
Спасибо большое!
Я тоже изучал матрицы, но дело тов том, что в справках не расписывают в каком элементе матрицы что лежит, даже на blitz etc
Подскажите пожалуйста еще в каких ячейках находятся поворот и смещения, для полной информации

Платон Александрович 11.04.2012 17:36

Ответ: getMathElement()
 
Цитата:

Сообщение от burovalex (Сообщение 225127)
Подскажите пожалуйста еще в каких ячейках находятся поворот и смещения, для полной информации

смещение тут:
Код:

1 0 0 0
0 1 0 0
0 0 1 0
X Y Z 1

т.е.
Код:

X# = GetMatElement ( Entity, 3, 0 )
Y# = GetMatElement ( Entity, 3, 1 )
Z# = GetMatElement ( Entity, 3, 2 )

матрица вращения это вот эта 3x3 часть:
Код:

X Y Z 0
X Y Z 0
X Y Z 0
0 0 0 1

извлечь из нее углы Эйлера можно так:
Код:

XAxisY# = GetMatElement ( Entity, 0, 1 )

YAxisY# = GetMatElement ( Entity, 1, 1 )

ZAxisX# = GetMatElement ( Entity, 2, 0 )
ZAxisY# = GetMatElement ( Entity, 2, 1 )
ZAxisZ# = GetMatElement ( Entity, 2, 2 )

Pitch# = ATan2 ( ZAxisY, Sqr ( ZAxisX * ZAxisX + ZAxisZ * ZAxisZ ) )
Yaw# = ATan2 ( ZAxisX, ZAxisZ )
Roll# = ATan2 ( XAxisY, YAxisY )

Но для блица это не практично, т.к. встроеные EntityPitch|Yaw|Roll будут производительнее, к тому-же эти углы и смещения глобальны, т.е. с учетом трансформации всех предков энтити.

Черный крыс 31.05.2012 22:37

Ответ: getMathElement()
 
так я не понял... а какого фига они глобальны ? Ведь система обьектов предпологает, что вся инфа о трансформациях должна хранится в относительных координатах ( относительно родительских ). Тогда в чем вообще их смысл ?

Я же считал, что извлечение глобыльных параметров происходит за счет перебора всех родителей.

Платон Александрович 01.06.2012 08:37

Ответ: getMathElement()
 
Цитата:

Сообщение от Diablo1909 (Сообщение 229146)
так я не понял... а какого фига они глобальны ? Ведь система обьектов предпологает, что вся инфа о трансформациях должна хранится в относительных координатах ( относительно родительских ). Тогда в чем вообще их смысл ?

Я же считал, что извлечение глобыльных параметров происходит за счет перебора всех родителей.

Не совсем так. Когда меняется координаты\угол ентити, происходит отложенный перерасчет матриц его самого и его чайлдов. Т.е. там флажок который указывает что трансформации надо перерасчитать. Это делается либо по необходимости (например тем же самым вызовом GetMatElement) до рендера, либо непосредственно перед ним, чтобы получить глобальную матрицу для каждого ентити. Эта матрица и передается в Direct3D для трансформации вершин. GetMatElement возвращает элементы этой матрицы.
Подробнее можно посмотреть в исходниках miniB3D, там в файле geom.h почти вся 3д математика. А устройство иерархии (впрочем и geom.h там же) в исходниках sdk.

Черный крыс 01.06.2012 12:03

Ответ: getMathElement()
 
Мой вариант системы энтити - правда он 2Д и на БМаксе, но тут исповедуется моя религия.

Код:

Private
Type TPivot Extends TEntity
 Field _parent:TPivot {no_save = 1}
 Field _childs:TListEx = New TListEx
 
 Field _ang:Float
 Field _pos:Float2 = New Float2
 Field _scl:Float2 = New Float2.Create(1.0, 1.0)
 
 Field _tps:Float2 = New Float2
 
 Field _call(entity:TEntity, dt:Float) = NullCallBack {no_save = 1}
 
 Function NullCallBack(entity:TEntity, dt:Float)
 End Function
 
 Method SetCallBack(func(entity:TEntity, dt:Float) = Null, isGlobal:Byte = False) Final
  Super.SetCallBack(func, isGlobal)
  If func = Null Then func = NullCallBack
  _call = func
 End Method
 
 Method New()
  world.AddLast(Self)
 End Method
 
 Method Free()
  Super.Free()
  _pos = Null
  _scl = Null
  _tps = Null
  _ang = Null
  _childs = Null
  GetParentList().Remove(Self)
  _parent = Null
 End Method
 
 Method Copy:TEntity(parent:TEntity = Null)
  Local pivot:TPivot = New TPivot
  pivot.name = "copy_" + name
  pivot.hide = hide
  'pivot.data = data
  pivot._pos = _pos.Copy()
  pivot._scl = _scl.Copy()
  pivot._tps = _tps.Copy()
  pivot._ang = _ang
  pivot.SetParent(parent)
  If parent Then pivot.SetPosition(New Float2)
  Return pivot
 End Method
 
 Method ToString:String()
  Return "Pivot"
 End Method
 
 Method SetPosition(position:Float2, isGlobal:Byte = False) Final
  If isGlobal And _parent
  _tps = position.Sub(_parent.GetGlobalTransformedPosition())
  _pos = _tps.UnRotate(New Float2.ForAngle(_parent._ang))
  _pos = _pos.Div(_parent._scl)
  Else
  _pos = position.Copy()
  Transform()
  End If
  'TranslateChilds()
 End Method
 
 Method GetPosition:Float2(isGlobal:Byte = False) Final
  If isGlobal
  Return GetGlobalTransformedPosition()
  Else
  Return _pos.Copy()
  End If
 End Method
 
 Method SetRotation(angle:Float, isGlobal:Byte = False) Final
  Local da:Float = _ang
  If isGlobal
  _ang = angle
  Else
  _ang = angle + GetParentAngle()
  End If
  RotateChilds(_ang - da)
 End Method
 
 Method GetRotation:Float(isGlobal:Byte = False) Final
  If isGlobal Then Return _ang
  Return _ang - GetParentAngle()
 End Method
 
 Method SetScale(scale:Float2, isGlobal:Byte = False) Final
  Local ds:Float2 = _scl.Copy()
  If isGlobal
  _scl = scale.Copy()
  Else
  _scl = scale.Mul(GetParentScale())
  End If
  ScaleChilds(_scl.Div(ds))
 End Method
 
 Method GetScale:Float2(isGlobal:Byte = False) Final
  If isGlobal Then Return _scl.Copy()
  Return _scl.Div(GetParentScale())
 End Method
 
 Method SetTransform(angle:Float, scale:Float2, isGlobal:Byte = False) Final
  Local da:Float = _ang
  Local ds:Float2 = _scl.Copy()
  If isGlobal
  _ang = angle
  _scl = scale.Copy()
  Else
  _ang = angle + GetParentAngle()
  _scl = _scl.Mul(GetParentScale())
  End If
  TransformChilds(_scl.Div(ds), _ang - da)
 End Method
 
 Method SetParent(parent:TEntity) Final
  If _parent = parent Then Return
  GetParentList().Remove(Self)
  _parent = TPivot(parent)
  GetParentList().AddLast(Self)
  If _parent
  _ang = _parent._ang
  _scl = _parent._scl.Copy()
  SetPosition(New Float2)
  End If
 End Method
 
 Method GetParent:TEntity() Final
  Return _parent
 End Method
 
 Method CountChildren:Int() Final
  Return _childs.Count()
 End Method
 
 Method GetChild:TEntity(index:Int) Final
  Return TEntity(_childs.ValueAtIndex(index))
 End Method
 
 Method ObjectEnumerator:TListEnum() Final
  Return _childs.ObjectEnumerator()
 End Method
 
 Method Intersect:Byte(entity:TEntity)
  Select entity.ToString()
  Case "Pivot" Return False
  End Select
 
 End Method
 
 Method SetOrder(order:Int) Final
  Local list:TListEx = GetParentList()
  Select Sgn(order)
  Case 1 list.MoveDown(Self, order)
  Case - 1 list.MoveUp(Self, - order)
  End Select
 End Method
 
 'PRIVATE
 
 Method Build(parent:TPivot)
  'If _parent = parent Then Return
  For Local child:TPivot = EachIn _childs
  child.Build(Self)
  Next
  _parent = parent
  If Not GetParentList().Contains(Self) Then GetParentList().AddLast(Self)
 End Method
 
 Method Update(dt:Float)
  If hide Then Return
  _call(Self, dt)
  For Local child:TPivot = EachIn _childs
  child.Update(dt)
  Next
 End Method
 
 Method Draw(position:Float2)
  If hide Then Return
  Local mypos:Float2 = position.Add(_tps)
  If Debug
  .SetTransform()
  .SetColor(255, 255, 255)
  .SetAlpha(1.0)
  .SetBlend(ALPHABLEND)
  DrawOval(mypos.x - 3, mypos.y - 3, 6, 6)
  End If
  For Local child:TPivot = EachIn _childs
  child.Draw(mypos)
  Next
 End Method
 
 Method GetParentList:TListEx() Final
  If _parent Then Return _parent._childs
  Return world
 End Method
 
 Method GetParentScale:Float2() Final
  If _parent Then Return _parent._scl
  Return New Float2.Create(1.0, 1.0)
 End Method
 
 Method GetParentAngle:Float() Final
  If _parent Then Return _parent._ang
  Return 0.0
 End Method
 
 Method ScaleChilds(ds:Float2) Final
  For Local child:TPivot = EachIn _childs
  child._scl = child._scl.Mul(ds)
  child.Transform()
  child.ScaleChilds(ds)
  Next
 End Method
 
 Method RotateChilds(da:Float) Final
  For Local child:TPivot = EachIn _childs
  child._ang:+da
  child.Transform()
  child.RotateChilds(da)
  Next
 End Method
 
 'Method TranslateChilds()
 ' For Local child:TPivot = EachIn _childs
 '  'Calc BBox
 '  child.TranslateChilds()
 ' Next
 'End Method
 
 Method TransformChilds(ds:Float2, da:Float) Final
  For Local child:TPivot = EachIn _childs
  child._scl = child._scl.Mul(ds)
  child._ang:+da
  child.Transform()
  child.TransformChilds(ds, da)
  Next
 End Method
 
 Method Transform() Final
  _tps = _pos.Mul(GetParentScale())
  _tps = _tps.Rotate(New Float2.ForAngle(GetParentAngle()))
 End Method
 
 Method GetGlobalTransformedPosition:Float2() Final
  Local pos:Float2 = _tps.Copy()
  Local pivot:TPivot = _parent
  While pivot
  pos = pos.Add(pivot._tps)
  pivot = pivot._parent
  Wend
  Return pos
 End Method
 
 '*******************
 
 Method GetPick:Byte()
 End Method
 
 Method GetAlpha:Float()
 End Method
 
 Method GetBlend:Byte()
 End Method
 
 Method GetColor:TColor()
 End Method
 
 Method Align(vector:Float2) Final
  SetRotation(vector.ToAngle() + 90.0, True)
 End Method
 
 Method Point(target:TEntity) Final
  Align(TPivot(target).GetGlobalTransformedPosition().Sub(GetGlobalTransformedPosition()))
 End Method
 
 Method Delta:Float(target:TEntity) Final
  Return (target.GetRotation(True) - _ang)
 End Method
 
 Method Distance:Float(target:TEntity) Final
  Return GetGlobalTransformedPosition().Sub(TPivot(target).GetGlobalTransformedPosition()).Length()
 End Method
 
 Method Move(speed:Float2) Final
  _pos = _pos.Add(speed.Rotate(New Float2.ForAngle(_ang)))
  Transform()
 End Method
 
 Method Turn(speed:Float) Final
  _ang:+speed
  RotateChilds(speed)
 End Method
 
 Method Translate(speed:Float2) Final
  _pos = _pos.Add(speed)
  _tps = _tps.Add(speed)
  Transform()
 End Method
End Type



Часовой пояс GMT +4, время: 04:15.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot