【发布时间】:2021-12-27 17:45:01
【问题描述】:
我尝试了解 3d 的工作原理,并创建了 3d 形状,例如立方体。
我填写mesh.data.VertexBuffer.Vertices 和mesh.data.IndexBuffer。
在屏幕上看起来一切正常,但不是阴影。
我不明白如何为顶点提供法线?我可以考虑 triangles 的法线,但我无法想象单个顶点。一个verticle可以被多个三角形共享,是还是不是?例如。对于立方体,一个角的顶点可以被 3 面墙共享。
也许我的理解是错误的。
问题是:
- 我应该像现在一样只为立方体获得 8 分吗?并在 indexbuffer 中使用它们。
- 或者我应该为每个三角形设置单独的点,即使它们与其他三角形点具有相同的坐标,以便能够计算法线?例如。对于我应该拥有的立方体:
6 walls * 4 points = 24 points而不是我目前的 8 个?
更新
unit UnitMain;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Viewport3D, System.Math.Vectors, FMX.Types3D,
FMX.Controls3D, FMX.Objects3D, FMX.MaterialSources;
type
TFormCube = class(TForm)
Viewport3D1: TViewport3D;
Camera1: TCamera;
Light1: TLight;
Mesh1: TMesh;
LightMaterialSource1: TLightMaterialSource;
LightMaterialSource2: TLightMaterialSource;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
FormCube: TFormCube;
implementation
{$R *.fmx}
procedure TFormCube.FormCreate(Sender: TObject);
Var idx: Integer;
begin
Mesh1.Data.VertexBuffer.Length:= 8;
Mesh1.Data.VertexBuffer.Vertices[0]:= Point3d(1, 1, 1);
Mesh1.Data.VertexBuffer.Vertices[1]:= Point3d(1, -1, 1);
Mesh1.Data.VertexBuffer.Vertices[2]:= Point3d(-1, -1, 1);
Mesh1.Data.VertexBuffer.Vertices[3]:= Point3d(-1, 1, 1);
Mesh1.Data.VertexBuffer.Vertices[4]:= Point3d(1, 1, -1);
Mesh1.Data.VertexBuffer.Vertices[5]:= Point3d(1, -1, -1);
Mesh1.Data.VertexBuffer.Vertices[6]:= Point3d(-1, -1, -1);
Mesh1.Data.VertexBuffer.Vertices[7]:= Point3d(-1, 1, -1);
Mesh1.Data.IndexBuffer.Length:= 8*2*3;
//front
idx:= 0;
Mesh1.Data.IndexBuffer[idx + 0]:= 0;
Mesh1.Data.IndexBuffer[idx + 1]:= 3;
Mesh1.Data.IndexBuffer[idx + 2]:= 2;
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 0;
Mesh1.Data.IndexBuffer[idx + 1]:= 2;
Mesh1.Data.IndexBuffer[idx + 2]:= 1;
//right
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 4;
Mesh1.Data.IndexBuffer[idx + 1]:= 0;
Mesh1.Data.IndexBuffer[idx + 2]:= 1;
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 4;
Mesh1.Data.IndexBuffer[idx + 1]:= 1;
Mesh1.Data.IndexBuffer[idx + 2]:= 5;
//back
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 7;
Mesh1.Data.IndexBuffer[idx + 1]:= 4;
Mesh1.Data.IndexBuffer[idx + 2]:= 5;
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 7;
Mesh1.Data.IndexBuffer[idx + 1]:= 5;
Mesh1.Data.IndexBuffer[idx + 2]:= 6;
//left
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 3;
Mesh1.Data.IndexBuffer[idx + 1]:= 7;
Mesh1.Data.IndexBuffer[idx + 2]:= 6;
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 3;
Mesh1.Data.IndexBuffer[idx + 1]:= 6;
Mesh1.Data.IndexBuffer[idx + 2]:= 2;
//top
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 4;
Mesh1.Data.IndexBuffer[idx + 1]:= 7;
Mesh1.Data.IndexBuffer[idx + 2]:= 3;
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 4;
Mesh1.Data.IndexBuffer[idx + 1]:= 3;
Mesh1.Data.IndexBuffer[idx + 2]:= 0;
//bottom
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 1;
Mesh1.Data.IndexBuffer[idx + 1]:= 2;
Mesh1.Data.IndexBuffer[idx + 2]:= 6;
inc(idx, 3);
Mesh1.Data.IndexBuffer[idx + 0]:= 1;
Mesh1.Data.IndexBuffer[idx + 1]:= 6;
Mesh1.Data.IndexBuffer[idx + 2]:= 5;
end;
end.
和 dfm
object FormCube: TFormCube
Left = 0
Top = 0
Caption = 'Cube'
ClientHeight = 823
ClientWidth = 1166
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
OnCreate = FormCreate
DesignerMasterStyle = 0
object Viewport3D1: TViewport3D
Align = Client
Camera = Camera1
Color = claBlack
Size.Width = 1166.000000000000000000
Size.Height = 823.000000000000000000
Size.PlatformDefault = False
UsingDesignCamera = False
object Camera1: TCamera
AngleOfView = 45.000000000000000000
Position.X = -2.000000000000000000
Position.Y = -2.000000000000000000
Position.Z = -10.000000000000000000
Width = 1.000000000000000000
Height = 1.000000000000000000
Depth = 1.000000000000000000
end
object Light1: TLight
Color = claWhite
LightType = Directional
SpotCutOff = 180.000000000000000000
Position.X = -9.222618103027344000
Position.Y = 2.758471012115479000
RotationAngle.Y = 21.211906433105470000
Width = 1.000000000000000000
Height = 1.000000000000000000
Depth = 1.000000000000000000
Quanternion = '(0,-0.184053480625153,0,-0.982916116714478)'
end
object Mesh1: TMesh
Width = 1.000000000000000000
Height = 1.000000000000000000
Depth = 1.000000000000000000
TwoSide = True
MaterialSource = LightMaterialSource2
end
object LightMaterialSource1: TLightMaterialSource
Diffuse = claRed
Ambient = claBlue
Emissive = claGreen
Specular = claWhite
Shininess = 30
Left = 280
Top = 168
end
end
object LightMaterialSource2: TLightMaterialSource
Diffuse = claWhite
Ambient = xFF202020
Emissive = claNull
Specular = xFF606060
Shininess = 30
Left = 248
Top = 256
end
end
【问题讨论】:
-
您是否在场景中添加了光源?在没有光源的情况下,对象的所有面都显示出来,根本没有任何阴影。只有当您添加至少一个光源时,才会计算正确的阴影。
-
我在现场有灯光并且它正在工作,但没有适当的法线(如果我有 8 个点,我不知道如何计算)。当我旋转立方体时,一切都没有被正确地“遮蔽”。我必须知道如何对基本立方体执行此操作,因为我有更多图形,例如管道、圆环 ....
-
请提供minimal reproducible example(包括 .pas 和 .fmx 文件)
标签: delphi 3d firemonkey