Changeset 472 for GraphicTest/Packages/bgrabitmap/bgrascene3d.pas
- Timestamp:
- Apr 9, 2015, 9:58:36 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest/Packages/bgrabitmap/bgrascene3d.pas
r452 r472 9 9 10 10 type 11 TProjection3D = BGRAMatrix3D.TProjection3D; 12 TBox3D = record 13 min,max: TPoint3D; 14 end; 15 16 TLightingNormal3D = (lnNone, lnFace, lnVertex, lnFaceVertexMix); 17 TLightingInterpolation3D = (liLowQuality, liSpecularHighQuality, liAlwaysHighQuality); 18 TAntialiasingMode3D = (am3dNone, am3dMultishape, am3dResample); 19 TPerspectiveMode3D = (pmLinearMapping, pmPerspectiveMapping, pmZBuffer); 20 21 TRenderingOptions = record 22 LightingInterpolation: TLightingInterpolation3D; 23 AntialiasingMode: TAntialiasingMode3D; 24 AntialiasingResampleLevel: integer; 25 PerspectiveMode: TPerspectiveMode3D; 26 TextureInterpolation: boolean; 27 MinZ: single; 28 end; 29 11 30 PSceneLightingContext = ^TSceneLightingContext; 12 31 TSceneLightingContext = packed record … … 23 42 SaturationHigh: integer; 24 43 SaturationHighF: single; 25 end;26 27 TProjection3D = packed record28 Zoom, Center: TPointF;29 end;30 31 TBox3D = record32 min,max: TPoint3D;33 end;34 35 TLightingNormal3D = (lnNone, lnFace, lnVertex, lnFaceVertexMix);36 TLightingInterpolation3D = (liLowQuality, liSpecularHighQuality, liAlwaysHighQuality);37 TAntialiasingMode3D = (am3dNone, am3dMultishape, am3dResample);38 TPerspectiveMode3D = (pmLinearMapping, pmPerspectiveMapping, pmZBuffer);39 40 type41 TRenderingOptions = record42 LightingInterpolation: TLightingInterpolation3D;43 AntialiasingMode: TAntialiasingMode3D;44 AntialiasingResampleLevel: integer;45 PerspectiveMode: TPerspectiveMode3D;46 TextureInterpolation: boolean;47 MinZ: single;48 44 end; 49 45 … … 81 77 function GetLightCount: integer; 82 78 function GetMaterial(AIndex: integer): IBGRAMaterial3D; 79 function GetNormalCount: integer; 83 80 function GetObject(AIndex: integer): IBGRAObject3D; 84 81 function GetVertexCount: integer; … … 111 108 function ApplyNoLighting(Context: PSceneLightingContext; Color: TBGRAPixel): TBGRAPixel; virtual; 112 109 procedure UseMaterial(AMaterialName: string; AFace: IBGRAFace3D); virtual; 110 function FetchTexture({%H-}AName: string; out texSize: TPointF): IBGRAScanner; virtual; 113 111 114 112 public … … 116 114 DefaultMaterial : IBGRAMaterial3D; 117 115 RenderingOptions: TRenderingOptions; 116 UnknownColor: TBGRAPixel; 118 117 119 118 constructor Create; 120 119 constructor Create(ASurface: TBGRACustomBitmap); 121 120 destructor Destroy; override; 122 procedure Clear; 121 procedure Clear; virtual; 123 122 function LoadObjectFromFile(AFilename: string; SwapFacesOrientation: boolean = true): IBGRAObject3D; 123 function LoadObjectFromFileUTF8(AFilename: string; SwapFacesOrientation: boolean = true): IBGRAObject3D; 124 function LoadObjectFromStream(AStream: TStream; SwapFacesOrientation: boolean = true): IBGRAObject3D; 125 procedure LoadMaterialsFromFile(AFilename: string); 126 procedure LoadMaterialsFromFileUTF8(AFilename: string); 127 procedure LoadMaterialsFromStream(AStream: TStream); 124 128 procedure LookAt(AWhere: TPoint3D; ATopDir: TPoint3D); 125 129 procedure LookLeft(angleDeg: single); … … 145 149 function CreateMaterial: IBGRAMaterial3D; 146 150 function CreateMaterial(ASpecularIndex: integer): IBGRAMaterial3D; 151 function GetMaterialByName(AName: string): IBGRAMaterial3D; 147 152 procedure UpdateMaterials; virtual; 148 153 procedure UpdateMaterial(AMaterialName: string); virtual; 154 procedure ForEachVertex(ACallback: TVertex3DCallback); 155 procedure ForEachFace(ACallback: TFace3DCallback); 149 156 property ViewCenter: TPointF read GetViewCenter write SetViewCenter; 150 157 property AutoViewCenter: boolean read FAutoViewCenter write SetAutoViewCenter; … … 154 161 property Object3DCount: integer read FObjectCount; 155 162 property VertexCount: integer read GetVertexCount; 163 property NormalCount: integer read GetNormalCount; 156 164 property FaceCount: integer read GetFaceCount; 157 165 property Zoom: TPointF read GetZoom write SetZoom; … … 169 177 implementation 170 178 171 uses BGRAPolygon, BGRAPolygonAliased, BGRACoordPool3D; 179 uses BGRAPolygon, BGRAPolygonAliased, BGRACoordPool3D, BGRAResample, 180 lazutf8classes; 172 181 173 182 {$i lightingclasses3d.inc} 183 {$i vertex3d.inc} 184 {$i face3d.inc} 174 185 175 186 type … … 200 211 function AddFace(const AVertices: array of IBGRAVertex3D; AColors: array of TBGRAPixel): IBGRAFace3D; 201 212 function AddFaceReversed(const AVertices: array of IBGRAVertex3D): IBGRAFace3D; 202 procedure ComputeWithMatrix(const AMatrix: TMatrix3D; constAProjection: TProjection3D);213 procedure ComputeWithMatrix(constref AMatrix: TMatrix3D; constref AProjection: TProjection3D); 203 214 function GetColor: TBGRAPixel; 204 215 function GetLight: Single; … … 210 221 function GetFaceCount: integer; 211 222 function GetTotalVertexCount: integer; 223 function GetTotalNormalCount: integer; 212 224 function GetMaterial: IBGRAMaterial3D; 213 225 procedure SetLightingNormal(const AValue: TLightingNormal3D); … … 222 234 function GetRefCount: integer; 223 235 procedure SetBiface(AValue : boolean); 224 end; 225 226 {$i shape3D.inc} 227 228 type 229 { TBGRAPart3D } 230 231 TBGRAPart3D = class(TInterfacedObject,IBGRAPart3D) 232 private 233 FVertices: array of IBGRAVertex3D; 234 FVertexCount: integer; 235 FMatrix: TMatrix3D; 236 FParts: array of IBGRAPart3D; 237 FPartCount: integer; 238 FContainer: IBGRAPart3D; 239 FCoordPool: TBGRACoordPool3D; 240 public 241 constructor Create(AContainer: IBGRAPart3D); 242 destructor Destroy; override; 243 procedure Clear(ARecursive: boolean); 244 function Add(x,y,z: single): IBGRAVertex3D; 245 function Add(pt: TPoint3D): IBGRAVertex3D; 246 function Add(pt: TPoint3D_128): IBGRAVertex3D; 247 function Add(const coords: array of single): arrayOfIBGRAVertex3D; 248 function Add(const pts: array of TPoint3D): arrayOfIBGRAVertex3D; 249 function Add(const pts: array of TPoint3D_128): arrayOfIBGRAVertex3D; 250 procedure Add(const pts: array of IBGRAVertex3D); 251 procedure Add(AVertex: IBGRAVertex3D); 252 procedure RemoveVertex(Index: integer); 253 function GetBoundingBox: TBox3D; 254 function GetRadius: single; 255 function GetMatrix: TMatrix3D; 256 function GetPart(AIndex: Integer): IBGRAPart3D; 257 function GetPartCount: integer; 258 function GetVertex(AIndex: Integer): IBGRAVertex3D; 259 function GetVertexCount: integer; 260 function GetTotalVertexCount: integer; 261 function GetContainer: IBGRAPart3D; 262 procedure SetVertex(AIndex: Integer; const AValue: IBGRAVertex3D); 263 procedure ResetTransform; 264 procedure Translate(x,y,z: single; Before: boolean = true); 265 procedure Translate(ofs: TPoint3D; Before: boolean = true); 266 procedure Scale(size: single; Before: boolean = true); 267 procedure Scale(x,y,z: single; Before: boolean = true); 268 procedure Scale(size: TPoint3D; Before: boolean = true); 269 procedure RotateXDeg(angle: single; Before: boolean = true); 270 procedure RotateYDeg(angle: single; Before: boolean = true); 271 procedure RotateZDeg(angle: single; Before: boolean = true); 272 procedure RotateXRad(angle: single; Before: boolean = true); 273 procedure RotateYRad(angle: single; Before: boolean = true); 274 procedure RotateZRad(angle: single; Before: boolean = true); 275 procedure SetMatrix(const AValue: TMatrix3D); 276 procedure ComputeWithMatrix(const AMatrix: TMatrix3D; const AProjection: TProjection3D); 277 function ComputeCoordinate(var ASceneCoord: TPoint3D_128; const AProjection: TProjection3D): TPointF; 278 procedure NormalizeViewNormal; 279 function CreatePart: IBGRAPart3D; 280 procedure LookAt(ALookWhere,ATopDir: TPoint3D); 281 procedure RemoveUnusedVertices; 282 function IndexOf(AVertex: IBGRAVertex3D): integer; 283 end; 284 285 { TBGRAFace3D } 286 287 PBGRAFaceVertexDescription = ^TBGRAFaceVertexDescription; 288 TBGRAFaceVertexDescription = record 289 Vertex: IBGRAVertex3D; 290 Color: TBGRAPixel; 291 TexCoord: TPointF; 292 ColorOverride: boolean; 293 TexCoordOverride: boolean; 294 end; 295 296 TBGRAFace3D = class(TInterfacedObject,IBGRAFace3D) 297 private 298 FVertices: packed array of TBGRAFaceVertexDescription; 299 FVertexCount: integer; 300 FTexture: IBGRAScanner; 301 FMaterial: IBGRAMaterial3D; 302 FMaterialName: string; 303 FParentTexture: boolean; 304 FViewNormal: TPoint3D_128; 305 FViewCenter: TPoint3D_128; 306 FObject3D : IBGRAObject3D; 307 FBiface: boolean; 308 FLightThroughFactor: single; 309 FLightThroughFactorOverride: boolean; 310 function GetVertexDescription(AIndex : integer): PBGRAFaceVertexDescription; 311 public 312 function GetObject3D: IBGRAObject3D; 313 constructor Create(AObject3D: IBGRAObject3D; AVertices: array of IBGRAVertex3D); 314 destructor Destroy; override; 315 procedure AddVertex(AVertex: IBGRAVertex3D); 316 function GetParentTexture: boolean; 317 function GetTexture: IBGRAScanner; 318 function GetVertex(AIndex: Integer): IBGRAVertex3D; 319 function GetVertexColor(AIndex: Integer): TBGRAPixel; 320 function GetVertexColorOverride(AIndex: Integer): boolean; 321 function GetVertexCount: integer; 322 function GetMaterial: IBGRAMaterial3D; 323 function GetMaterialName: string; 324 function GetTexCoord(AIndex: Integer): TPointF; 325 function GetTexCoordOverride(AIndex: Integer): boolean; 326 function GetViewNormal: TPoint3D; 327 function GetViewNormal_128: TPoint3D_128; 328 function GetViewCenter: TPoint3D; 329 function GetViewCenter_128: TPoint3D_128; 330 function GetViewCenterZ: single; 331 function GetBiface: boolean; 332 function GetLightThroughFactor: single; 333 function GetLightThroughFactorOverride: boolean; 334 procedure SetParentTexture(const AValue: boolean); 335 procedure SetTexture(const AValue: IBGRAScanner); 336 procedure SetColor(AColor: TBGRAPixel); 337 procedure SetVertexColor(AIndex: Integer; const AValue: TBGRAPixel); 338 procedure SetVertexColorOverride(AIndex: Integer; const AValue: boolean); 339 procedure SetTexCoord(AIndex: Integer; const AValue: TPointF); 340 procedure SetTexCoordOverride(AIndex: Integer; const AValue: boolean); 341 procedure SetBiface(const AValue: boolean); 342 procedure SetLightThroughFactor(const AValue: single); 343 procedure SetLightThroughFactorOverride(const AValue: boolean); 344 procedure SetVertex(AIndex: Integer; const AValue: IBGRAVertex3D); 345 procedure ComputeViewNormalAndCenter; 346 procedure SetMaterial(const AValue: IBGRAMaterial3D); 347 procedure SetMaterialName(const AValue: string); 348 function GetAsObject: TObject; 349 property Texture: IBGRAScanner read GetTexture write SetTexture; 350 property ParentTexture: boolean read GetParentTexture write SetParentTexture; 351 property VertexCount: integer read GetVertexCount; 352 property Vertex[AIndex: Integer]: IBGRAVertex3D read GetVertex write SetVertex; 353 property VertexColor[AIndex: Integer]: TBGRAPixel read GetVertexColor write SetVertexColor; 354 property VertexColorOverride[AIndex: Integer]: boolean read GetVertexColorOverride write SetVertexColorOverride; 355 property TexCoord[AIndex: Integer]: TPointF read GetTexCoord write SetTexCoord; 356 property TexCoordOverride[AIndex: Integer]: boolean read GetTexCoordOverride write SetTexCoordOverride; 357 property ViewNormal: TPoint3D read GetViewNormal; 358 property ViewNormal_128: TPoint3D_128 read GetViewNormal_128; 359 property ViewCenter: TPoint3D read GetViewCenter; 360 property ViewCenter_128: TPoint3D_128 read GetViewCenter_128; 361 property ViewCenterZ: single read GetViewCenterZ; 362 property Object3D: IBGRAObject3D read GetObject3D; 363 property Biface: boolean read GetBiface write SetBiface; 364 property LightThroughFactor: single read GetLightThroughFactor write SetLightThroughFactor; 365 property LightThroughFactorOverride: boolean read GetLightThroughFactorOverride write SetLightThroughFactorOverride; 366 property Material: IBGRAMaterial3D read GetMaterial write SetMaterial; 367 property VertexDescription[AIndex : integer]: PBGRAFaceVertexDescription read GetVertexDescription; 368 end; 369 370 { TBGRAVertex3D } 371 372 TBGRAVertex3D = class(TInterfacedObject,IBGRAVertex3D) 373 private 374 FColor: TBGRAPixel; 375 FParentColor: boolean; 376 FLight: Single; 377 FTexCoord: TPointF; 378 FCoordPool: TBGRACoordPool3D; 379 FCoordPoolIndex: integer; 380 function GetCoordData: PBGRACoordData3D; 381 procedure Init(ACoordPool: TBGRACoordPool3D; ASceneCoord: TPoint3D_128); 382 public 383 constructor Create(ACoordPool: TBGRACoordPool3D; ASceneCoord: TPoint3D); overload; 384 constructor Create(ACoordPool: TBGRACoordPool3D; ASceneCoord: TPoint3D_128); overload; 385 destructor Destroy; override; 386 function GetColor: TBGRAPixel; 387 function GetLight: Single; 388 function GetViewNormal: TPoint3D; 389 function GetViewNormal_128: TPoint3D_128; 390 function GetSceneCoord: TPoint3D; 391 function GetSceneCoord_128: TPoint3D_128; 392 function GetTexCoord: TPointF; 393 function GetViewCoord: TPoint3D; 394 function GetViewCoord_128: TPoint3D_128; 395 function GetUsage: integer; 396 procedure SetColor(const AValue: TBGRAPixel); 397 procedure SetLight(const AValue: Single); 398 procedure SetViewNormal(const AValue: TPoint3D); 399 procedure SetViewNormal_128(const AValue: TPoint3D_128); 400 procedure NormalizeViewNormal; 401 procedure AddViewNormal(const AValue: TPoint3D_128); 402 procedure SetSceneCoord(const AValue: TPoint3D); 403 procedure SetSceneCoord_128(const AValue: TPoint3D_128); 404 procedure SetTexCoord(const AValue: TPointF); 405 procedure SetViewCoord(const AValue: TPoint3D); 406 procedure SetViewCoord_128(const AValue: TPoint3D_128); 407 function GetViewCoordZ: single; 408 function GetParentColor: Boolean; 409 procedure SetParentColor(const AValue: Boolean); 410 function GetProjectedCoord: TPointF; 411 procedure SetProjectedCoord(const AValue: TPointF); 412 procedure ComputeCoordinateAndClearNormal(const AMatrix: TMatrix3D; const AProjection: TProjection3D); 413 property SceneCoord: TPoint3D read GetSceneCoord write SetSceneCoord; 414 property SceneCoord_128: TPoint3D_128 read GetSceneCoord_128 write SetSceneCoord_128; 415 property ViewCoord: TPoint3D read GetViewCoord write SetViewCoord; 416 property ViewCoord_128: TPoint3D_128 read GetViewCoord_128 write SetViewCoord_128; 417 property ViewCoordZ: single read GetViewCoordZ; 418 property ProjectedCoord: TPointF read GetProjectedCoord write SetProjectedCoord; 419 property TexCoord: TPointF read GetTexCoord write SetTexCoord; 420 property Color: TBGRAPixel read GetColor write SetColor; 421 property ParentColor: Boolean read GetParentColor write SetParentColor; 422 property Light: Single read GetLight write SetLight; 423 property ViewNormal: TPoint3D read GetViewNormal write SetViewNormal; 424 property ViewNormal_128: TPoint3D_128 read GetViewNormal_128 write SetViewNormal_128; 425 property Usage: integer read GetUsage; 426 property CoordData: PBGRACoordData3D read GetCoordData; 427 function GetAsObject: TObject; 428 end; 429 430 { TBGRAVertex3D } 431 432 procedure TBGRAVertex3D.Init(ACoordPool: TBGRACoordPool3D; ASceneCoord: TPoint3D_128); 433 begin 434 FCoordPool := ACoordPool; 435 FCoordPoolIndex := FCoordPool.Add; 436 FColor := BGRAWhite; 437 FParentColor := True; 438 FLight := 1; 439 SceneCoord_128 := ASceneCoord; 440 end; 441 442 function TBGRAVertex3D.GetCoordData: PBGRACoordData3D; 443 begin 444 result := FCoordPool.CoordData[FCoordPoolIndex]; 445 end; 446 447 constructor TBGRAVertex3D.Create(ACoordPool: TBGRACoordPool3D; ASceneCoord: TPoint3D); 448 begin 449 Init(ACoordPool, Point3D_128(ASceneCoord)); 450 end; 451 452 constructor TBGRAVertex3D.Create(ACoordPool: TBGRACoordPool3D; ASceneCoord: TPoint3D_128); 453 begin 454 Init(ACoordPool, ASceneCoord); 455 end; 456 457 destructor TBGRAVertex3D.Destroy; 458 begin 459 FCoordPool.Remove(FCoordPoolIndex); 460 inherited Destroy; 461 end; 462 463 function TBGRAVertex3D.GetColor: TBGRAPixel; 464 begin 465 result := FColor; 466 end; 467 468 function TBGRAVertex3D.GetLight: Single; 469 begin 470 result := FLight; 471 end; 472 473 function TBGRAVertex3D.GetViewNormal: TPoint3D; 474 begin 475 result := Point3D(FCoordPool.CoordData[FCoordPoolIndex]^.viewNormal); 476 end; 477 478 function TBGRAVertex3D.GetViewNormal_128: TPoint3D_128; 479 begin 480 result := FCoordPool.CoordData[FCoordPoolIndex]^.viewNormal; 481 end; 482 483 function TBGRAVertex3D.GetSceneCoord: TPoint3D; 484 begin 485 result := Point3D(FCoordPool.CoordData[FCoordPoolIndex]^.sceneCoord); 486 end; 487 488 function TBGRAVertex3D.GetSceneCoord_128: TPoint3D_128; 489 begin 490 result := FCoordPool.CoordData[FCoordPoolIndex]^.sceneCoord; 491 end; 492 493 function TBGRAVertex3D.GetTexCoord: TPointF; 494 begin 495 result := FTexCoord; 496 end; 497 498 function TBGRAVertex3D.GetViewCoord: TPoint3D; 499 begin 500 result := Point3D(FCoordPool.CoordData[FCoordPoolIndex]^.viewCoord); 501 end; 502 503 function TBGRAVertex3D.GetViewCoord_128: TPoint3D_128; 504 begin 505 result := FCoordPool.CoordData[FCoordPoolIndex]^.viewCoord; 506 end; 507 508 function TBGRAVertex3D.GetUsage: integer; 509 begin 510 result := frefcount; 511 end; 512 513 procedure TBGRAVertex3D.SetColor(const AValue: TBGRAPixel); 514 begin 515 FColor := AValue; 516 FParentColor := false; 517 end; 518 519 procedure TBGRAVertex3D.SetLight(const AValue: Single); 520 begin 521 FLight := AValue; 522 end; 523 524 procedure TBGRAVertex3D.SetViewNormal(const AValue: TPoint3D); 525 begin 526 FCoordPool.CoordData[FCoordPoolIndex]^.viewNormal := Point3D_128(AValue); 527 end; 528 529 procedure TBGRAVertex3D.SetViewNormal_128(const AValue: TPoint3D_128); 530 begin 531 FCoordPool.CoordData[FCoordPoolIndex]^.viewNormal := AValue; 532 end; 533 534 procedure TBGRAVertex3D.SetSceneCoord(const AValue: TPoint3D); 535 begin 536 FCoordPool.CoordData[FCoordPoolIndex]^.sceneCoord := Point3D_128(AValue); 537 end; 538 539 procedure TBGRAVertex3D.SetSceneCoord_128(const AValue: TPoint3D_128); 540 begin 541 FCoordPool.CoordData[FCoordPoolIndex]^.sceneCoord := AValue; 542 end; 543 544 procedure TBGRAVertex3D.SetTexCoord(const AValue: TPointF); 545 begin 546 FTexCoord := AValue; 547 end; 548 549 procedure TBGRAVertex3D.SetViewCoord(const AValue: TPoint3D); 550 begin 551 FCoordPool.CoordData[FCoordPoolIndex]^.viewCoord := Point3D_128(AValue); 552 end; 553 554 procedure TBGRAVertex3D.SetViewCoord_128(const AValue: TPoint3D_128); 555 begin 556 FCoordPool.CoordData[FCoordPoolIndex]^.viewCoord := AValue; 557 end; 558 559 function TBGRAVertex3D.GetViewCoordZ: single; 560 begin 561 result := FCoordPool.CoordData[FCoordPoolIndex]^.viewCoord.Z; 562 end; 563 564 function TBGRAVertex3D.GetParentColor: Boolean; 565 begin 566 result := FParentColor; 567 end; 568 569 procedure TBGRAVertex3D.SetParentColor(const AValue: Boolean); 570 begin 571 FParentColor := AValue; 572 end; 573 574 function TBGRAVertex3D.GetProjectedCoord: TPointF; 575 begin 576 result := FCoordPool.CoordData[FCoordPoolIndex]^.projectedCoord; 577 end; 578 579 procedure TBGRAVertex3D.SetProjectedCoord(const AValue: TPointF); 580 begin 581 FCoordPool.CoordData[FCoordPoolIndex]^.projectedCoord := AValue; 582 end; 583 584 procedure TBGRAVertex3D.ComputeCoordinateAndClearNormal(const AMatrix: TMatrix3D; const AProjection : TProjection3D); 585 var P: PBGRACoordData3D; 586 begin 587 P := FCoordPool.CoordData[FCoordPoolIndex]; 588 with p^ do 589 begin 590 viewCoord := AMatrix*sceneCoord; 591 ClearPoint3D_128(viewNormal); 592 if viewCoord.z > 0 then 593 begin 594 InvZ := 1/viewCoord.z; 595 projectedCoord := PointF(viewCoord.x*InvZ*AProjection.Zoom.x + AProjection.Center.x, 596 viewCoord.y*InvZ*AProjection.Zoom.Y + AProjection.Center.y); 597 end else 598 projectedCoord := PointF(0,0); 599 end; 600 end; 601 602 function TBGRAVertex3D.GetAsObject: TObject; 603 begin 604 result := self; 605 end; 606 607 procedure TBGRAVertex3D.NormalizeViewNormal; 608 begin 609 Normalize3D_128(FCoordPool.CoordData[FCoordPoolIndex]^.viewNormal); 610 end; 611 612 procedure TBGRAVertex3D.AddViewNormal(const AValue: TPoint3D_128); 613 begin 614 Add3D_Aligned(FCoordPool.CoordData[FCoordPoolIndex]^.viewNormal, AValue); 615 end; 616 617 { TBGRAFace3D } 618 619 function TBGRAFace3D.GetVertexDescription(AIndex : integer 620 ): PBGRAFaceVertexDescription; 621 begin 622 result := @FVertices[AIndex]; 623 end; 624 625 function TBGRAFace3D.GetObject3D: IBGRAObject3D; 626 begin 627 result := FObject3D; 628 end; 629 630 constructor TBGRAFace3D.Create(AObject3D: IBGRAObject3D; 631 AVertices: array of IBGRAVertex3D); 632 var 633 i: Integer; 634 begin 635 SetLength(FVertices, length(AVertices)); 636 for i:= 0 to high(AVertices) do 637 AddVertex(AVertices[i]); 638 FObject3D := AObject3D; 639 FBiface := false; 640 FParentTexture := True; 641 FLightThroughFactor:= 0; 642 FLightThroughFactorOverride:= false; 643 end; 644 645 destructor TBGRAFace3D.Destroy; 646 begin 647 fillchar(FTexture,sizeof(FTexture),0); 648 inherited Destroy; 649 end; 650 651 procedure TBGRAFace3D.AddVertex(AVertex: IBGRAVertex3D); 652 begin 653 if FVertexCount = length(FVertices) then 654 setlength(FVertices, FVertexCount*2+3); 655 with FVertices[FVertexCount] do 656 begin 657 Color := BGRAWhite; 658 ColorOverride := false; 659 TexCoord := PointF(0,0); 660 TexCoordOverride := false; 661 Vertex := AVertex; 662 end; 663 inc(FVertexCount); 664 end; 665 666 function TBGRAFace3D.GetParentTexture: boolean; 667 begin 668 result := FParentTexture; 669 end; 670 671 function TBGRAFace3D.GetTexture: IBGRAScanner; 672 begin 673 result := FTexture; 674 end; 675 676 function TBGRAFace3D.GetVertex(AIndex: Integer): IBGRAVertex3D; 677 begin 678 if (AIndex < 0) or (AIndex >= FVertexCount) then 679 raise Exception.Create('Index out of bounds'); 680 result := FVertices[AIndex].Vertex; 681 end; 682 683 procedure TBGRAFace3D.SetVertex(AIndex: Integer; const AValue: IBGRAVertex3D); 684 begin 685 if (AIndex < 0) or (AIndex >= FVertexCount) then 686 raise Exception.Create('Index out of bounds'); 687 FVertices[AIndex].Vertex := AValue; 688 end; 689 690 function TBGRAFace3D.GetVertexColor(AIndex: Integer): TBGRAPixel; 691 begin 692 if (AIndex < 0) or (AIndex >= FVertexCount) then 693 raise Exception.Create('Index out of bounds'); 694 result := FVertices[AIndex].Color; 695 end; 696 697 function TBGRAFace3D.GetVertexColorOverride(AIndex: Integer): boolean; 698 begin 699 if (AIndex < 0) or (AIndex >= FVertexCount) then 700 raise Exception.Create('Index out of bounds'); 701 result := FVertices[AIndex].ColorOverride; 702 end; 703 704 function TBGRAFace3D.GetVertexCount: integer; 705 begin 706 result := FVertexCount; 707 end; 708 709 function TBGRAFace3D.GetMaterial: IBGRAMaterial3D; 710 begin 711 result := FMaterial; 712 end; 713 714 function TBGRAFace3D.GetMaterialName: string; 715 begin 716 result := FMaterialName; 717 end; 718 719 procedure TBGRAFace3D.SetParentTexture(const AValue: boolean); 720 begin 721 FParentTexture := AValue; 722 end; 723 724 procedure TBGRAFace3D.SetTexture(const AValue: IBGRAScanner); 725 begin 726 FTexture := AValue; 727 FParentTexture := false; 728 end; 729 730 procedure TBGRAFace3D.SetColor(AColor: TBGRAPixel); 731 var i: integer; 732 begin 733 for i := 0 to GetVertexCount-1 do 734 SetVertexColor(i,AColor); 735 end; 736 737 procedure TBGRAFace3D.SetVertexColor(AIndex: Integer; const AValue: TBGRAPixel 738 ); 739 begin 740 if (AIndex < 0) or (AIndex >= FVertexCount) then 741 raise Exception.Create('Index out of bounds'); 742 with FVertices[AIndex] do 743 begin 744 Color := AValue; 745 ColorOverride := true; 746 end; 747 end; 748 749 procedure TBGRAFace3D.SetVertexColorOverride(AIndex: Integer; 750 const AValue: boolean); 751 begin 752 if (AIndex < 0) or (AIndex >= FVertexCount) then 753 raise Exception.Create('Index out of bounds'); 754 FVertices[AIndex].ColorOverride := AValue; 755 end; 756 757 function TBGRAFace3D.GetTexCoord(AIndex: Integer): TPointF; 758 begin 759 if (AIndex < 0) or (AIndex >= FVertexCount) then 760 raise Exception.Create('Index out of bounds'); 761 result := FVertices[AIndex].TexCoord; 762 end; 763 764 function TBGRAFace3D.GetTexCoordOverride(AIndex: Integer): boolean; 765 begin 766 if (AIndex < 0) or (AIndex >= FVertexCount) then 767 raise Exception.Create('Index out of bounds'); 768 result := FVertices[AIndex].TexCoordOverride; 769 end; 770 771 procedure TBGRAFace3D.SetTexCoord(AIndex: Integer; const AValue: TPointF); 772 begin 773 if (AIndex < 0) or (AIndex >= FVertexCount) then 774 raise Exception.Create('Index out of bounds'); 775 FVertices[AIndex].TexCoord := AValue; 776 FVertices[AIndex].TexCoordOverride := true; 777 end; 778 779 procedure TBGRAFace3D.SetTexCoordOverride(AIndex: Integer; const AValue: boolean 780 ); 781 begin 782 if (AIndex < 0) or (AIndex >= FVertexCount) then 783 raise Exception.Create('Index out of bounds'); 784 FVertices[AIndex].TexCoordOverride := AValue; 785 end; 786 787 function TBGRAFace3D.GetViewNormal: TPoint3D; 788 begin 789 result := Point3D(FViewNormal); 790 end; 791 792 function TBGRAFace3D.GetViewNormal_128: TPoint3D_128; 793 begin 794 result := FViewNormal; 795 end; 796 797 function TBGRAFace3D.GetViewCenter: TPoint3D; 798 begin 799 result := Point3D(FViewCenter); 800 end; 801 802 function TBGRAFace3D.GetViewCenter_128: TPoint3D_128; 803 begin 804 result := FViewCenter; 805 end; 806 807 function TBGRAFace3D.GetViewCenterZ: single; 808 begin 809 result := FViewCenter.Z; 810 end; 811 812 function TBGRAFace3D.GetBiface: boolean; 813 begin 814 result := FBiface; 815 end; 816 817 procedure TBGRAFace3D.SetBiface(const AValue: boolean); 818 begin 819 FBiface := AValue; 820 end; 821 822 function TBGRAFace3D.GetLightThroughFactor: single; 823 begin 824 result := FLightThroughFactor; 825 end; 826 827 function TBGRAFace3D.GetLightThroughFactorOverride: boolean; 828 begin 829 result := FLightThroughFactorOverride; 830 end; 831 832 procedure TBGRAFace3D.SetLightThroughFactor(const AValue: single); 833 begin 834 if AValue < 0 then 835 FLightThroughFactor := 0 836 else 837 FLightThroughFactor:= AValue; 838 FLightThroughFactorOverride := true; 839 end; 840 841 procedure TBGRAFace3D.SetLightThroughFactorOverride(const AValue: boolean); 842 begin 843 FLightThroughFactorOverride := AValue; 844 end; 845 846 procedure TBGRAFace3D.ComputeViewNormalAndCenter; 847 var v1,v2: TPoint3D_128; 848 i: Integer; 849 p0,p1,p2: IBGRAVertex3D; 850 begin 851 if FVertexCount < 3 then 852 ClearPoint3D_128(FViewNormal) 853 else 854 begin 855 p0 := FVertices[0].Vertex; 856 p1 := FVertices[1].Vertex; 857 p2 := FVertices[2].Vertex; 858 v1 := p1.ViewCoord_128 - p0.ViewCoord_128; 859 v2 := p2.ViewCoord_128 - p1.ViewCoord_128; 860 VectProduct3D_128(v2,v1,FViewNormal); 861 Normalize3D_128(FViewNormal); 862 for i := 0 to FVertexCount-1 do 863 FVertices[i].Vertex.AddViewNormal(FViewNormal); 864 end; 865 ClearPoint3D_128(FViewCenter); 866 if FVertexCount > 0 then 867 begin 868 for i := 0 to FVertexCount-1 do 869 FViewCenter += FVertices[i].Vertex.ViewCoord_128; 870 FViewCenter *= 1/FVertexCount; 871 end; 872 end; 873 874 procedure TBGRAFace3D.SetMaterial(const AValue: IBGRAMaterial3D); 875 begin 876 FMaterial := AValue; 877 end; 878 879 procedure TBGRAFace3D.SetMaterialName(const AValue: string); 880 begin 881 if AValue <> FMaterialName then 882 begin 883 FMaterialName := AValue; 884 FObject3D.Scene.UseMaterial(FMaterialName, self); 885 end; 886 end; 887 888 function TBGRAFace3D.GetAsObject: TObject; 889 begin 890 result := self; 891 end; 892 893 { TBGRAPart3D } 894 895 procedure TBGRAPart3D.LookAt(ALookWhere,ATopDir: TPoint3D); 896 var ZDir, XDir, YDir: TPoint3D_128; 897 ViewPoint: TPoint3D_128; 898 CurPart: IBGRAPart3D; 899 ComposedMatrix: TMatrix3D; 900 begin 901 YDir := -Point3D_128(ATopDir); 902 if IsPoint3D_128_Zero(YDir) then exit; 903 Normalize3D_128(YDir); 904 905 ComposedMatrix := FMatrix; 906 CurPart := self.FContainer; 907 while CurPart <> nil do 908 begin 909 ComposedMatrix := CurPart.Matrix*ComposedMatrix; 910 CurPart := CurPart.Container; 911 end; 912 ViewPoint := ComposedMatrix*Point3D_128_Zero; 913 914 ZDir := Point3D_128(ALookWhere)-ViewPoint; 915 if IsPoint3D_128_Zero(ZDir) then exit; 916 Normalize3D_128(ZDir); 917 918 VectProduct3D_128(YDir,ZDir,XDir); 919 VectProduct3D_128(ZDir,XDir,YDir); //correct Y dir 920 921 FMatrix := Matrix3D(XDir,YDir,ZDir,ViewPoint); 922 ComposedMatrix := MatrixIdentity3D; 923 CurPart := self.FContainer; 924 while CurPart <> nil do 925 begin 926 ComposedMatrix := CurPart.Matrix*ComposedMatrix; 927 CurPart := CurPart.Container; 928 end; 929 FMatrix := MatrixInverse3D(ComposedMatrix)*FMatrix; 930 end; 931 932 procedure TBGRAPart3D.RemoveUnusedVertices; 933 var 934 i: Integer; 935 begin 936 for i := FVertexCount-1 downto 0 do 937 if FVertices[i].Usage <= 2 then RemoveVertex(i); 938 for i := 0 to FPartCount-1 do 939 FParts[i].RemoveUnusedVertices; 940 end; 941 942 function TBGRAPart3D.IndexOf(AVertex: IBGRAVertex3D): integer; 943 var i: integer; 944 begin 945 for i := 0 to FVertexCount-1 do 946 if FVertices[i] = AVertex then 947 begin 948 result := i; 949 exit; 950 end; 951 result := -1; 952 end; 953 954 procedure TBGRAPart3D.Add(AVertex: IBGRAVertex3D); 955 begin 956 if FVertexCount = length(FVertices) then 957 setlength(FVertices, FVertexCount*2+3); 958 FVertices[FVertexCount] := AVertex; 959 inc(FVertexCount); 960 end; 961 962 procedure TBGRAPart3D.RemoveVertex(Index: integer); 963 var i: integer; 964 begin 965 if (Index >= 0) and (Index < FVertexCount) then 966 begin 967 for i := Index to FVertexCount-2 do 968 FVertices[i] := FVertices[i+1]; 969 FVertices[FVertexCount-1] := nil; 970 dec(FVertexCount); 971 end; 972 end; 973 974 function TBGRAPart3D.GetRadius: single; 975 var i: integer; 976 pt: TPoint3D_128; 977 d: single; 978 begin 979 result := 0; 980 for i := 0 to GetVertexCount-1 do 981 begin 982 pt := GetVertex(i).SceneCoord_128; 983 d:= sqrt(DotProduct3D_128(pt,pt)); 984 if d > result then result := d; 985 end; 986 end; 987 988 constructor TBGRAPart3D.Create(AContainer: IBGRAPart3D); 989 begin 990 FContainer := AContainer; 991 FMatrix := MatrixIdentity3D; 992 FCoordPool := TBGRACoordPool3D.Create(4); 993 end; 994 995 destructor TBGRAPart3D.Destroy; 996 begin 997 FCoordPool.Free; 998 inherited Destroy; 999 end; 1000 1001 procedure TBGRAPart3D.Clear(ARecursive: boolean); 1002 var i: integer; 1003 begin 1004 FVertices := nil; 1005 FVertexCount := 0; 1006 if ARecursive then 1007 begin 1008 for i := 0 to FPartCount-1 do 1009 FParts[i].Clear(ARecursive); 1010 FParts := nil; 1011 FPartCount := 0; 1012 end; 1013 end; 1014 1015 function TBGRAPart3D.Add(x, y, z: single): IBGRAVertex3D; 1016 begin 1017 result := TBGRAVertex3D.Create(FCoordPool,Point3D(x,y,z)); 1018 Add(result); 1019 end; 1020 1021 function TBGRAPart3D.Add(pt: TPoint3D): IBGRAVertex3D; 1022 begin 1023 result := TBGRAVertex3D.Create(FCoordPool,pt); 1024 Add(result); 1025 end; 1026 1027 function TBGRAPart3D.Add(pt: TPoint3D_128): IBGRAVertex3D; 1028 begin 1029 result := TBGRAVertex3D.Create(FCoordPool,pt); 1030 Add(result); 1031 end; 1032 1033 function TBGRAPart3D.Add(const coords: array of single 1034 ): arrayOfIBGRAVertex3D; 1035 var pts: array of TPoint3D; 1036 CoordsIdx: integer; 1037 i: Integer; 1038 begin 1039 if length(coords) mod 3 <> 0 then 1040 raise exception.Create('Array size must be a multiple of 3'); 1041 setlength(pts, length(coords) div 3); 1042 coordsIdx := 0; 1043 for i := 0 to high(pts) do 1044 begin 1045 pts[i] := Point3D(coords[CoordsIdx],coords[CoordsIdx+1],coords[CoordsIdx+2]); 1046 inc(coordsIdx,3); 1047 end; 1048 result := Add(pts); 1049 end; 1050 1051 function TBGRAPart3D.Add(const pts: array of TPoint3D): arrayOfIBGRAVertex3D; 1052 var 1053 i: Integer; 1054 begin 1055 setlength(result, length(pts)); 1056 for i := 0 to high(pts) do 1057 result[i] := TBGRAVertex3D.Create(FCoordPool,pts[i]); 1058 Add(result); 1059 end; 1060 1061 function TBGRAPart3D.Add(const pts: array of TPoint3D_128 1062 ): arrayOfIBGRAVertex3D; 1063 var 1064 i: Integer; 1065 begin 1066 setlength(result, length(pts)); 1067 for i := 0 to high(pts) do 1068 result[i] := TBGRAVertex3D.Create(FCoordPool,pts[i]); 1069 Add(result); 1070 end; 1071 1072 procedure TBGRAPart3D.Add(const pts: array of IBGRAVertex3D); 1073 var 1074 i: Integer; 1075 begin 1076 if FVertexCount + length(pts) > length(FVertices) then 1077 setlength(FVertices, (FVertexCount*2 + length(pts))+1); 1078 for i := 0 to high(pts) do 1079 begin 1080 FVertices[FVertexCount] := pts[i]; 1081 inc(FVertexCount); 1082 end; 1083 end; 1084 1085 function TBGRAPart3D.GetBoundingBox: TBox3D; 1086 var i: integer; 1087 pt: TPoint3D_128; 1088 begin 1089 if GetVertexCount > 0 then 1090 begin 1091 result.min := GetVertex(0).SceneCoord; 1092 result.max := result.min; 1093 end else 1094 begin 1095 result.min := Point3D(0,0,0); 1096 result.max := Point3D(0,0,0); 1097 exit; 1098 end; 1099 for i := 1 to GetVertexCount-1 do 1100 begin 1101 pt := GetVertex(i).SceneCoord_128; 1102 if pt.x < result.min.x then result.min.x := pt.x else 1103 if pt.x > result.max.x then result.max.x := pt.x; 1104 if pt.y < result.min.y then result.min.y := pt.y else 1105 if pt.y > result.max.y then result.max.y := pt.y; 1106 if pt.z < result.min.z then result.min.z := pt.z else 1107 if pt.z > result.max.z then result.max.z := pt.z; 1108 end; 1109 end; 1110 1111 function TBGRAPart3D.GetMatrix: TMatrix3D; 1112 begin 1113 result := FMatrix; 1114 end; 1115 1116 function TBGRAPart3D.GetPart(AIndex: Integer): IBGRAPart3D; 1117 begin 1118 if (AIndex < 0) or (AIndex >= FPartCount) then 1119 raise exception.Create('Index of out bounds'); 1120 result := FParts[AIndex]; 1121 end; 1122 1123 function TBGRAPart3D.GetPartCount: integer; 1124 begin 1125 result := FPartCount; 1126 end; 1127 1128 function TBGRAPart3D.GetVertex(AIndex: Integer): IBGRAVertex3D; 1129 begin 1130 if (AIndex < 0) or (AIndex >= FVertexCount) then 1131 raise exception.Create('Index of out bounds'); 1132 result := FVertices[AIndex]; 1133 end; 1134 1135 function TBGRAPart3D.GetVertexCount: integer; 1136 begin 1137 result := FVertexCount; 1138 end; 1139 1140 function TBGRAPart3D.GetTotalVertexCount: integer; 1141 var i: integer; 1142 begin 1143 result := GetVertexCount; 1144 for i := 0 to GetPartCount-1 do 1145 result += GetPart(i).GetTotalVertexCount; 1146 end; 1147 1148 procedure TBGRAPart3D.ResetTransform; 1149 begin 1150 FMatrix := MatrixIdentity3D; 1151 end; 1152 1153 procedure TBGRAPart3D.Scale(size: single; Before: boolean = true); 1154 begin 1155 Scale(size,size,size,Before); 1156 end; 1157 1158 procedure TBGRAPart3D.Scale(x, y, z: single; Before: boolean = true); 1159 begin 1160 Scale(Point3D(x,y,z),Before); 1161 end; 1162 1163 procedure TBGRAPart3D.Scale(size: TPoint3D; Before: boolean = true); 1164 begin 1165 if Before then 1166 FMatrix *= MatrixScale3D(size) 1167 else 1168 FMatrix := MatrixScale3D(size)*FMatrix; 1169 end; 1170 1171 procedure TBGRAPart3D.RotateXDeg(angle: single; Before: boolean = true); 1172 begin 1173 RotateXRad(-angle*Pi/180, Before); 1174 end; 1175 1176 procedure TBGRAPart3D.RotateYDeg(angle: single; Before: boolean = true); 1177 begin 1178 RotateYRad(-angle*Pi/180, Before); 1179 end; 1180 1181 procedure TBGRAPart3D.RotateZDeg(angle: single; Before: boolean = true); 1182 begin 1183 RotateZRad(-angle*Pi/180, Before); 1184 end; 1185 1186 procedure TBGRAPart3D.RotateXRad(angle: single; Before: boolean = true); 1187 begin 1188 if Before then 1189 FMatrix *= MatrixRotateX(angle) 1190 else 1191 FMatrix := MatrixRotateX(angle) * FMatrix; 1192 end; 1193 1194 procedure TBGRAPart3D.RotateYRad(angle: single; Before: boolean = true); 1195 begin 1196 if Before then 1197 FMatrix *= MatrixRotateY(angle) 1198 else 1199 FMatrix := MatrixRotateY(angle) * FMatrix; 1200 end; 1201 1202 procedure TBGRAPart3D.RotateZRad(angle: single; Before: boolean = true); 1203 begin 1204 if Before then 1205 FMatrix *= MatrixRotateZ(angle) 1206 else 1207 FMatrix := MatrixRotateZ(angle) * FMatrix; 1208 end; 1209 1210 procedure TBGRAPart3D.SetMatrix(const AValue: TMatrix3D); 1211 begin 1212 FMatrix := AValue; 1213 end; 1214 1215 procedure TBGRAPart3D.ComputeWithMatrix(const AMatrix: TMatrix3D; const AProjection: TProjection3D); 1216 var 1217 i: Integer; 1218 Composed: TMatrix3D; 1219 P: PBGRACoordData3D; 1220 begin 1221 Composed := AMatrix* self.FMatrix; 1222 {$IFDEF CPUI386} 1223 if UseSSE then 1224 begin 1225 Matrix3D_SSE_Load(Composed); 1226 asm 1227 mov eax,[AProjection] 1228 movups xmm4,[eax] 1229 xorps xmm1,xmm1 1230 end; 1231 P := FCoordPool.CoordData[0]; 1232 i := FCoordPool.UsedCapacity; 1233 if UseSSE3 then 1234 begin 1235 while i > 0 do 1236 with P^ do 1237 begin 1238 MatrixMultiplyVect3D_SSE3_Aligned(sceneCoord,viewCoord); 1239 if viewCoord.z > 0 then 1240 begin 1241 asm 1242 mov eax, P 1243 movaps xmm3, [eax+16] //viewCoord 1244 movaps xmm2,xmm3 1245 shufps xmm2,xmm3,2+8+32+128 1246 rcpps xmm2,xmm2 //xmm2 = InvZ 1247 movss [eax+40],xmm2 //-> InvZ 1248 1249 mulps xmm3,xmm4 //xmm3 *= Projection.Zoom 1250 mulps xmm3,xmm2 //xmm3 *= InvZ 1251 1252 movhlps xmm0,xmm4 //xmm2 = Projection.Center 1253 addps xmm3,xmm0 //xmm3 += Projection.Center 1254 1255 movlps [eax+32],xmm3 //->projectedCoord 1256 movaps [eax+48],xmm1 //->normal 1257 end; 1258 end else 1259 asm 1260 mov eax, P 1261 movlps [eax+32],xmm1 //0 ->projectedCoord 1262 movaps [eax+48],xmm1 //->normal 1263 end; 1264 dec(i); 1265 inc(p); 1266 end; 1267 end else 1268 begin 1269 while i > 0 do 1270 with P^ do 1271 begin 1272 MatrixMultiplyVect3D_SSE_Aligned(sceneCoord,viewCoord); 1273 if viewCoord.z > 0 then 1274 begin 1275 asm 1276 mov eax, P 1277 movaps xmm3, [eax+16] //viewCoord 1278 movaps xmm2,xmm3 1279 shufps xmm2,xmm3,2+8+32+128 1280 rcpps xmm2,xmm2 //xmm2 = InvZ 1281 movss [eax+40],xmm2 //-> InvZ 1282 1283 mulps xmm3,xmm4 //xmm3 *= Projection.Zoom 1284 mulps xmm3,xmm2 //xmm3 *= InvZ 1285 1286 movhlps xmm0,xmm4 //xmm2 = Projection.Center 1287 addps xmm3,xmm0 //xmm3 += Projection.Center 1288 1289 movlps [eax+32],xmm3 //->projectedCoord 1290 movaps [eax+48],xmm1 //->normal 1291 end; 1292 end else 1293 asm 1294 mov eax, P 1295 movlps [eax+32],xmm1 //0 ->projectedCoord 1296 movaps [eax+48],xmm1 //->normal 1297 end; 1298 dec(i); 1299 inc(p); 1300 end; 1301 end; 1302 end 1303 else 1304 {$ENDIF} 1305 begin 1306 P := FCoordPool.CoordData[0]; 1307 i := FCoordPool.UsedCapacity; 1308 while i > 0 do 1309 with P^ do 1310 begin 1311 viewCoord := Composed*sceneCoord; 1312 ClearPoint3D_128(viewNormal); 1313 if viewCoord.z > 0 then 1314 begin 1315 InvZ := 1/viewCoord.z; 1316 projectedCoord := PointF(viewCoord.x*InvZ*AProjection.Zoom.x + AProjection.Center.x, 1317 viewCoord.y*InvZ*AProjection.Zoom.Y + AProjection.Center.y); 1318 end else 1319 projectedCoord := PointF(0,0); 1320 dec(i); 1321 inc(p); 1322 end; 1323 end; 1324 for i := 0 to FPartCount-1 do 1325 FParts[i].ComputeWithMatrix(Composed,AProjection); 1326 end; 1327 1328 function TBGRAPart3D.ComputeCoordinate(var ASceneCoord: TPoint3D_128; const AProjection: TProjection3D): TPointF; 1329 var part: IBGRAPart3D; 1330 newViewCoord: TPoint3D_128; 1331 InvZ: single; 1332 begin 1333 newViewCoord := FMatrix * ASceneCoord; 1334 part := FContainer; 1335 while part <> nil do 1336 begin 1337 newViewCoord := part.Matrix * newViewCoord; 1338 part := part.Container; 1339 end; 1340 if NewViewCoord.z > 0 then 1341 begin 1342 InvZ := 1/NewViewCoord.z; 1343 result := PointF(NewViewCoord.x*InvZ*AProjection.Zoom.x + AProjection.Center.x, 1344 NewViewCoord.y*InvZ*AProjection.Zoom.Y + AProjection.Center.y); 1345 end else 1346 result := PointF(0,0); 1347 end; 1348 1349 procedure TBGRAPart3D.NormalizeViewNormal; 1350 var 1351 i: Integer; 1352 begin 1353 for i := 0 to FVertexCount-1 do 1354 FVertices[i].NormalizeViewNormal; 1355 for i := 0 to FPartCount-1 do 1356 FParts[i].NormalizeViewNormal; 1357 end; 1358 1359 procedure TBGRAPart3D.Translate(x, y, z: single; Before: boolean = true); 1360 begin 1361 Translate(Point3D(x,y,z),Before); 1362 end; 1363 1364 procedure TBGRAPart3D.Translate(ofs: TPoint3D; Before: boolean = true); 1365 begin 1366 if Before then 1367 FMatrix *= MatrixTranslation3D(ofs) 1368 else 1369 FMatrix := MatrixTranslation3D(ofs)*FMatrix; 1370 end; 1371 1372 function TBGRAPart3D.CreatePart: IBGRAPart3D; 1373 begin 1374 if FPartCount = length(FParts) then 1375 setlength(FParts, FPartCount*2+1); 1376 result := TBGRAPart3D.Create(self); 1377 FParts[FPartCount] := result; 1378 inc(FPartCount); 1379 end; 1380 1381 function TBGRAPart3D.GetContainer: IBGRAPart3D; 1382 begin 1383 result := FContainer; 1384 end; 1385 1386 procedure TBGRAPart3D.SetVertex(AIndex: Integer; const AValue: IBGRAVertex3D); 1387 begin 1388 if (AIndex < 0) or (AIndex >= FVertexCount) then 1389 raise exception.Create('Index of out bounds'); 1390 FVertices[AIndex] := AValue; 1391 end; 1392 1393 { TBGRAObject3D } 1394 1395 procedure TBGRAObject3D.AddFace(AFace: IBGRAFace3D); 1396 begin 1397 if FFaceCount = length(FFaces) then 1398 setlength(FFaces,FFaceCount*2+3); 1399 FFaces[FFaceCount] := AFace; 1400 inc(FFaceCount); 1401 end; 1402 1403 constructor TBGRAObject3D.Create(AScene: TBGRAScene3D); 1404 begin 1405 FColor := BGRAWhite; 1406 FLight := 1; 1407 FTexture := nil; 1408 FMainPart := TBGRAPart3D.Create(nil); 1409 FLightingNormal:= AScene.DefaultLightingNormal; 1410 FParentLighting:= True; 1411 FScene := AScene; 1412 end; 1413 1414 destructor TBGRAObject3D.Destroy; 1415 begin 1416 fillchar(FTexture,sizeof(FTexture),0); 1417 inherited Destroy; 1418 end; 1419 1420 procedure TBGRAObject3D.Clear; 1421 begin 1422 FFaces := nil; 1423 FFaceCount := 0; 1424 FMainPart.Clear(True); 1425 end; 1426 1427 function TBGRAObject3D.GetColor: TBGRAPixel; 1428 begin 1429 result := FColor; 1430 end; 1431 1432 function TBGRAObject3D.GetLight: Single; 1433 begin 1434 result := FLight; 1435 end; 1436 1437 function TBGRAObject3D.GetTexture: IBGRAScanner; 1438 begin 1439 result := FTexture; 1440 end; 1441 1442 function TBGRAObject3D.GetMainPart: IBGRAPart3D; 1443 begin 1444 result := FMainPart; 1445 end; 1446 1447 procedure TBGRAObject3D.SetColor(const AValue: TBGRAPixel); 1448 begin 1449 FColor := AValue; 1450 FTexture := nil; 1451 end; 1452 1453 procedure TBGRAObject3D.SetLight(const AValue: Single); 1454 begin 1455 FLight := AValue; 1456 end; 1457 1458 procedure TBGRAObject3D.SetTexture(const AValue: IBGRAScanner); 1459 begin 1460 FTexture := AValue; 1461 end; 1462 1463 procedure TBGRAObject3D.SetMaterial(const AValue: IBGRAMaterial3D); 1464 begin 1465 FMaterial := AValue; 1466 end; 1467 1468 procedure TBGRAObject3D.RemoveUnusedVertices; 1469 begin 1470 GetMainPart.RemoveUnusedVertices; 1471 end; 1472 1473 procedure TBGRAObject3D.SeparatePart(APart: IBGRAPart3D); 1474 var 1475 vertexInfo: array of record 1476 orig,dup: IBGRAVertex3D; 1477 end; 1478 1479 i,j: integer; 1480 inPart,outPart: boolean; 1481 idxV: integer; 1482 begin 1483 setlength(vertexInfo, APart.VertexCount); 1484 for i := 0 to high(vertexInfo) do 1485 with vertexInfo[i] do 1486 begin 1487 orig := APart.Vertex[i]; 1488 dup := APart.Add(orig.SceneCoord_128); 1489 end; 1490 1491 for i := 0 to GetFaceCount-1 do 1492 with GetFace(i) do 1493 begin 1494 inPart := false; 1495 outPart := false; 1496 for j := 0 to VertexCount-1 do 1497 if (APart.IndexOf(Vertex[j]) <> -1) then 1498 inPart := true 1499 else 1500 outPart := true; 1501 1502 if inPart and not outPart then 1503 begin 1504 for j := 0 to VertexCount-1 do 1505 begin 1506 idxV := APart.IndexOf(Vertex[j]); 1507 if idxV <> -1 then 1508 Vertex[j] := vertexInfo[idxV].dup; 1509 end; 1510 end; 1511 end; 1512 1513 for i := APart.VertexCount-1 downto 0 do 1514 APart.RemoveVertex(i); 1515 end; 1516 1517 function TBGRAObject3D.GetScene: TBGRAScene3D; 1518 begin 1519 result := FScene; 1520 end; 1521 1522 function TBGRAObject3D.GetRefCount: integer; 1523 begin 1524 result := RefCount; 1525 end; 1526 1527 procedure TBGRAObject3D.SetBiface(AValue: boolean); 1528 var i: integer; 1529 begin 1530 for i := 0 to GetFaceCount-1 do 1531 GetFace(i).Biface := AValue; 1532 end; 1533 1534 function TBGRAObject3D.GetLightingNormal: TLightingNormal3D; 1535 begin 1536 result := FLightingNormal; 1537 end; 1538 1539 function TBGRAObject3D.GetParentLighting: boolean; 1540 begin 1541 result := FParentLighting; 1542 end; 1543 1544 procedure TBGRAObject3D.SetLightingNormal(const AValue: TLightingNormal3D); 1545 begin 1546 FLightingNormal := AValue; 1547 FParentLighting:= False; 1548 end; 1549 1550 procedure TBGRAObject3D.SetParentLighting(const AValue: boolean); 1551 begin 1552 FParentLighting:= AValue; 1553 end; 1554 1555 procedure TBGRAObject3D.ComputeWithMatrix(const AMatrix: TMatrix3D; const AProjection: TProjection3D); 1556 var 1557 i: Integer; 1558 begin 1559 FMainPart.ComputeWithMatrix(AMatrix,AProjection); 1560 for i := 0 to FFaceCount-1 do 1561 FFaces[i].ComputeViewNormalAndCenter; 1562 FMainPart.NormalizeViewNormal; 1563 end; 1564 1565 function TBGRAObject3D.AddFaceReversed(const AVertices: array of IBGRAVertex3D 1566 ): IBGRAFace3D; 1567 var 1568 tempVertices: array of IBGRAVertex3D; 1569 i: Integer; 1570 begin 1571 setlength(tempVertices,length(AVertices)); 1572 for i := 0 to high(tempVertices) do 1573 tempVertices[i] := AVertices[high(AVertices)-i]; 1574 result := AddFace(tempVertices); 1575 end; 1576 1577 function TBGRAObject3D.AddFace(const AVertices: array of IBGRAVertex3D): IBGRAFace3D; 1578 begin 1579 result := TBGRAFace3D.Create(self,AVertices); 1580 AddFace(result); 1581 end; 1582 1583 function TBGRAObject3D.AddFace(const AVertices: array of IBGRAVertex3D; 1584 ABiface: boolean): IBGRAFace3D; 1585 begin 1586 result := TBGRAFace3D.Create(self,AVertices); 1587 result.Biface := ABiface; 1588 AddFace(result); 1589 end; 1590 1591 function TBGRAObject3D.AddFace(const AVertices: array of IBGRAVertex3D; ATexture: IBGRAScanner): IBGRAFace3D; 1592 var Face: IBGRAFace3D; 1593 begin 1594 Face := TBGRAFace3D.Create(self,AVertices); 1595 Face.Texture := ATexture; 1596 AddFace(Face); 1597 result := face; 1598 end; 1599 1600 function TBGRAObject3D.AddFace(const AVertices: array of IBGRAVertex3D; 1601 AColor: TBGRAPixel): IBGRAFace3D; 1602 var Face: IBGRAFace3D; 1603 begin 1604 Face := TBGRAFace3D.Create(self,AVertices); 1605 Face.SetColor(AColor); 1606 Face.Texture := nil; 1607 AddFace(Face); 1608 result := face; 1609 end; 1610 1611 function TBGRAObject3D.AddFace(const AVertices: array of IBGRAVertex3D; 1612 AColors: array of TBGRAPixel): IBGRAFace3D; 1613 var 1614 i: Integer; 1615 begin 1616 if length(AColors) <> length(AVertices) then 1617 raise Exception.Create('Dimension mismatch'); 1618 result := TBGRAFace3D.Create(self,AVertices); 1619 for i := 0 to high(AColors) do 1620 result.VertexColor[i] := AColors[i]; 1621 AddFace(result); 1622 end; 1623 1624 function TBGRAObject3D.GetFace(AIndex: integer): IBGRAFace3D; 1625 begin 1626 if (AIndex < 0) or (AIndex >= FFaceCount) then 1627 raise Exception.Create('Index out of bounds'); 1628 result := FFaces[AIndex]; 1629 end; 1630 1631 function TBGRAObject3D.GetFaceCount: integer; 1632 begin 1633 result := FFaceCount; 1634 end; 1635 1636 function TBGRAObject3D.GetTotalVertexCount: integer; 1637 begin 1638 result := GetMainPart.TotalVertexCount; 1639 end; 1640 1641 function TBGRAObject3D.GetMaterial: IBGRAMaterial3D; 1642 begin 1643 result := FMaterial; 1644 end; 236 procedure ForEachVertex(ACallback: TVertex3DCallback); 237 procedure ForEachFace(ACallback: TFace3DCallback); 238 end; 239 240 {$i part3d.inc} 241 {$i object3d.inc} 242 {$i shapes3d.inc} 1645 243 1646 244 { TBGRAScene3D } … … 1746 344 end; 1747 345 346 function TBGRAScene3D.GetNormalCount: integer; 347 var i: integer; 348 begin 349 result := 0; 350 for i := 0 to Object3DCount-1 do 351 result += Object3D[i].TotalNormalCount; 352 end; 353 1748 354 function TBGRAScene3D.GetAmbiantLightness: single; 1749 355 begin … … 1822 428 procedure TBGRAScene3D.Init; 1823 429 begin 430 UnknownColor := BGRA(0,128,255); 1824 431 FAutoZoom := True; 1825 432 FAutoViewCenter := True; … … 1866 473 var i: integer; 1867 474 begin 475 for i := 0 to FLights.Count-1 do 476 TBGRALight3D(FLights[i])._Release; 477 FLights.Clear; 478 1868 479 for i := 0 to FObjectCount-1 do 1869 480 FObjects[i].Clear; 1870 481 FObjects := nil; 1871 482 FObjectCount := 0; 1872 for i := 0 to FLights.Count-1 do 1873 IBGRALight3D(TBGRALight3D(FLights[i]))._Release;1874 F Lights.Clear;1875 end;1876 1877 {$hints off} 483 484 FMaterials := nil; 485 FMaterialCount := 0; 486 DefaultMaterial := CreateMaterial; 487 end; 488 1878 489 procedure TBGRAScene3D.UseMaterial(AMaterialName: string; AFace: IBGRAFace3D); 1879 var color: TBGRAPixel; 1880 begin 1881 color := BGRA(0,128,255); 1882 AFace.SetColor(color); 1883 end; 1884 {$hints on} 490 491 function ParseColor(text: string): TBGRAPixel; 492 var 493 color,tempColor: TBGRAPixel; 494 begin 495 color := UnknownColor; 496 497 if copy(text,1,2) = 'dk' then 498 begin 499 tempcolor := ParseColor(copy(text,3,length(text)-2)); 500 tempcolor := MergeBGRA(tempcolor,3,BGRABlack,1); 501 color := StrToBGRA('dark'+copy(text,3,length(text)-2),tempcolor); 502 end; 503 if copy(text,1,2) = 'lt' then 504 begin 505 tempcolor := ParseColor(copy(text,3,length(text)-2)); 506 tempcolor := MergeBGRA(tempcolor,3,BGRAWhite,1); 507 color := StrToBGRA('light'+copy(text,3,length(text)-2),tempcolor); 508 end; 509 Color := StrToBGRA(StringReplace(text,'deep','dark',[]),Color); 510 Color := StrToBGRA(StringReplace(text,'dark','deep',[]),Color); 511 Color := StrToBGRA(text,Color); 512 result := color; 513 end; 514 515 var 516 mat: IBGRAMaterial3D; 517 c: TBGRAPixel; 518 begin 519 mat := GetMaterialByName(AMaterialName); 520 if mat = nil then 521 begin 522 mat := CreateMaterial; 523 mat.Name := AMaterialName; 524 c := ParseColor(AMaterialName); 525 mat.AmbiantColor := c; 526 mat.DiffuseColor := c; 527 end; 528 AFace.Material := mat; 529 end; 530 531 function TBGRAScene3D.FetchTexture(AName: string; out texSize: TPointF): IBGRAScanner; 532 begin 533 result := nil; 534 texSize := PointF(1,1); 535 end; 1885 536 1886 537 function TBGRAScene3D.LoadObjectFromFile(AFilename: string; SwapFacesOrientation: boolean): IBGRAObject3D; 1887 var t: textfile; 1888 s: string; 538 var source: TFileStream; 539 begin 540 source := TFileStream.Create(AFilename,fmOpenRead,fmShareDenyWrite); 541 try 542 result := LoadObjectFromStream(source,SwapFacesOrientation); 543 finally 544 source.free; 545 end; 546 end; 547 548 function TBGRAScene3D.LoadObjectFromFileUTF8(AFilename: string; 549 SwapFacesOrientation: boolean): IBGRAObject3D; 550 var source: TFileStreamUTF8; 551 begin 552 source := TFileStreamUTF8.Create(AFilename,fmOpenRead,fmShareDenyWrite); 553 try 554 result := LoadObjectFromStream(source,SwapFacesOrientation); 555 finally 556 source.free; 557 end; 558 end; 559 560 function TBGRAScene3D.LoadObjectFromStream(AStream: TStream; 561 SwapFacesOrientation: boolean): IBGRAObject3D; 562 var s: string; 563 secondValue,thirdValue: string; 1889 564 1890 565 function GetNextToken: string; 1891 var idxStart,idxEnd : integer;566 var idxStart,idxEnd,idxSlash: integer; 1892 567 begin 1893 568 idxStart := 1; 1894 while (idxStart <= length(s)) and (s[idxStart] =' ') do inc(idxStart);569 while (idxStart <= length(s)) and (s[idxStart]in[' ',#9]) do inc(idxStart); 1895 570 if idxStart > length(s) then 1896 571 begin … … 1899 574 end; 1900 575 idxEnd := idxStart; 1901 while (idxEnd < length(s)) and (s[idxEnd+1]<> ' ') do inc(idxEnd);576 while (idxEnd < length(s)) and not (s[idxEnd+1]in[' ',#9]) do inc(idxEnd); 1902 577 result := copy(s,idxStart, idxEnd-idxStart+1); 1903 578 delete(s,1,idxEnd); 1904 if pos('/',result) <> 0 then result := copy(result,1,pos('/',result)-1); 579 idxSlash := pos('/',result); 580 if idxSlash <> 0 then 581 begin 582 secondValue:= copy(result,idxSlash+1,length(result)-idxSlash); 583 result := copy(result,1,idxSlash-1); 584 idxSlash:= pos('/',secondValue); 585 if idxSlash <> 0 then 586 begin 587 thirdValue:= copy(secondValue,idxSlash+1,length(secondValue)-idxSlash); 588 secondValue:= copy(secondValue,1,idxSlash-1); 589 end else 590 thirdValue:= ''; 591 end else 592 begin 593 secondValue:= ''; 594 thirdValue:= ''; 595 end; 596 end; 597 598 type 599 TFaceVertexExtra = record 600 normal: IBGRANormal3D; 601 texCoord: TPointF; 1905 602 end; 1906 603 … … 1908 605 x,y,z : single; 1909 606 code : integer; 1910 vertices: array of IBGRAVertex3D; 1911 NbVertices,v,i: integer; 607 faceVertices: array of IBGRAVertex3D; 608 faceExtra: array of TFaceVertexExtra; 609 NbFaceVertices,v,v2,v3,i: integer; 1912 610 tempV: IBGRAVertex3D; 611 tempN: TFaceVertexExtra; 1913 612 materialname: string; 1914 613 face: IBGRAFace3D; 1915 1916 begin 614 lines: TStringList; 615 lineIndex: integer; 616 texCoords: array of TPointF; 617 nbTexCoords: integer; 618 619 begin 620 lines := TStringList.Create; 621 lines.LoadFromStream(AStream); 1917 622 result := CreateObject; 1918 assignfile(t,AFilename); 1919 reset(t); 1920 vertices := nil; 1921 NbVertices:= 0; 623 faceVertices := nil; 624 faceExtra := nil; 625 NbFaceVertices:= 0; 1922 626 materialname := 'default'; 1923 while not eof(t) do 1924 begin 1925 readln(t,s); 627 lineIndex := 0; 628 texCoords := nil; 629 nbTexCoords:= 0; 630 while lineIndex < lines.Count do 631 begin 632 s := lines[lineIndex]; 633 if pos('#',s) <> 0 then 634 s := copy(s,1,pos('#',s)-1); 635 inc(lineIndex); 1926 636 lineType := GetNextToken; 1927 637 if lineType = 'v' then … … 1932 642 result.MainPart.Add(x,y,z); 1933 643 end else 644 if lineType = 'vt' then 645 begin 646 val(GetNextToken,x,code); 647 val(GetNextToken,y,code); 648 if nbTexCoords >= length(texCoords) then 649 setlength(texCoords, length(texCoords)*2+1); 650 texCoords[nbTexCoords] := PointF(x,y); 651 inc(nbTexCoords); 652 end else 653 if lineType = 'vn' then 654 begin 655 val(GetNextToken,x,code); 656 val(GetNextToken,y,code); 657 val(GetNextToken,z,code); 658 result.MainPart.AddNormal(x,y,z); 659 result.LightingNormal := lnVertex; 660 end else 1934 661 if lineType = 'usemtl' then 1935 662 materialname := trim(s) … … 1937 664 if lineType = 'f' then 1938 665 begin 1939 Nb Vertices:= 0;666 NbFaceVertices:= 0; 1940 667 repeat 1941 668 val(GetNextToken,v,code); 669 if (code = 0) and (v < 0) then v := result.MainPart.VertexCount+1+v; 1942 670 if (code = 0) and (v >= 1) and (v <= result.MainPart.VertexCount) then 1943 671 begin 1944 if length(vertices) = nbvertices then 1945 setlength(vertices, length(vertices)*2+1); 1946 vertices[NbVertices] := result.MainPart.Vertex[v-1]; 1947 inc(NbVertices); 672 if length(faceVertices) = NbFaceVertices then 673 begin 674 setlength(faceVertices, length(faceVertices)*2+1); 675 setlength(faceExtra, length(faceExtra)*2+1); 676 end; 677 faceVertices[NbFaceVertices] := result.MainPart.Vertex[v-1]; 678 val(secondValue,v2,code); 679 if (code = 0) and (v2 < 0) then v2 := nbTexCoords+1+v2; 680 if (code = 0) and (v2 >= 1) and (v2-1 < nbTexCoords) then 681 faceExtra[NbFaceVertices].texCoord := texCoords[v2-1] 682 else if nbTexCoords > v-1 then 683 faceExtra[NbFaceVertices].texCoord := texCoords[v-1] 684 else 685 faceExtra[NbFaceVertices].texCoord := PointF(0,0); 686 val(thirdValue,v3,code); 687 if (code = 0) and (v3 < 0) then v3 := result.MainPart.NormalCount+1+v3; 688 if code = 0 then 689 faceExtra[NbFaceVertices].normal := result.MainPart.Normal[v3-1] 690 else if result.MainPart.NormalCount > v-1 then 691 faceExtra[NbFaceVertices].normal := result.MainPart.Normal[v-1] 692 else 693 faceExtra[NbFaceVertices].normal := nil; 694 inc(NbFaceVertices); 1948 695 end else break; 1949 696 until false; 1950 if Nb Vertices > 2 then697 if NbFaceVertices > 2 then 1951 698 begin 1952 699 if SwapFacesOrientation then 1953 for i := 0 to Nb Vertices div 2-1 do700 for i := 0 to NbFaceVertices div 2-1 do 1954 701 begin 1955 tempV := vertices[i]; 1956 vertices[i] := vertices[NbVertices-1-i]; 1957 vertices[NbVertices-1-i] := tempV; 702 tempV := faceVertices[i]; 703 faceVertices[i] := faceVertices[NbFaceVertices-1-i]; 704 faceVertices[NbFaceVertices-1-i] := tempV; 705 tempN := faceExtra[i]; 706 faceExtra[i] := faceExtra[NbFaceVertices-1-i]; 707 faceExtra[NbFaceVertices-1-i] := tempN; 1958 708 end; 1959 face := result.AddFace(slice(vertices,NbVertices)); 709 face := result.AddFace(slice(faceVertices,NbFaceVertices)); 710 for i := 0 to NbFaceVertices-1 do 711 begin 712 face.SetNormal(i, faceExtra[i].normal); 713 face.SetTexCoord(i, faceExtra[i].texCoord); 714 end; 1960 715 face.MaterialName := materialname; 1961 716 end; 1962 717 end; 1963 718 end; 1964 closefile(t); 719 lines.Free; 720 end; 721 722 procedure TBGRAScene3D.LoadMaterialsFromFile(AFilename: string); 723 var source: TFileStream; 724 begin 725 source := TFileStream.Create(AFilename,fmOpenRead,fmShareDenyWrite); 726 try 727 LoadMaterialsFromStream(source); 728 finally 729 source.free; 730 end; 731 end; 732 733 procedure TBGRAScene3D.LoadMaterialsFromFileUTF8(AFilename: string); 734 var source: TFileStreamUTF8; 735 begin 736 source := TFileStreamUTF8.Create(AFilename,fmOpenRead,fmShareDenyWrite); 737 try 738 LoadMaterialsFromStream(source); 739 finally 740 source.free; 741 end; 742 end; 743 744 procedure TBGRAScene3D.LoadMaterialsFromStream(AStream: TStream); 745 var 746 s: String; 747 748 function GetNextToken: string; 749 var idxStart,idxEnd: integer; 750 begin 751 idxStart := 1; 752 while (idxStart <= length(s)) and (s[idxStart]in[#9,' ']) do inc(idxStart); 753 if idxStart > length(s) then 754 begin 755 result := ''; 756 exit; 757 end; 758 idxEnd := idxStart; 759 while (idxEnd < length(s)) and not (s[idxEnd+1]in[#9,' ']) do inc(idxEnd); 760 result := copy(s,idxStart, idxEnd-idxStart+1); 761 delete(s,1,idxEnd); 762 end; 763 764 function GetSingle: single; 765 var code: integer; 766 begin 767 val(GetNextToken,result,code); 768 end; 769 770 function GetColorF: TColorF; 771 var r,g,b: single; 772 code: integer; 773 begin 774 val(GetNextToken,r,code); 775 val(GetNextToken,g,code); 776 val(GetNextToken,b,code); 777 result := ColorF(r,g,b,1); 778 end; 779 780 var 781 lines: TStringList; 782 lineIndex: integer; 783 lineType: String; 784 currentMaterial: IBGRAMaterial3D; 785 materialName: string; 786 texZoom: TPointF; 787 v: single; 788 789 begin 790 lines := TStringList.Create; 791 lines.LoadFromStream(AStream); 792 lineIndex := 0; 793 while lineIndex < lines.Count do 794 begin 795 s := lines[lineIndex]; 796 if pos('#',s) <> 0 then 797 s := copy(s,1,pos('#',s)-1); 798 inc(lineIndex); 799 lineType := GetNextToken; 800 if lineType = 'newmtl' then 801 begin 802 materialName := trim(s); 803 currentMaterial := GetMaterialByName(materialName); 804 if currentMaterial = nil then 805 begin 806 currentMaterial := CreateMaterial; 807 currentMaterial.Name := materialName; 808 end; 809 end else 810 if currentMaterial <> nil then 811 begin 812 if lineType = 'Ka' then currentMaterial.AmbiantColorF := GetColorF else 813 if lineType = 'Kd' then currentMaterial.DiffuseColorF := GetColorF else 814 if lineType = 'Ks' then currentMaterial.SpecularColorF := GetColorF else 815 if (lineType = 'map_Ka') or (lineType = 'map_Kd') then 816 begin 817 currentMaterial.Texture := FetchTexture(trim(s),texZoom); 818 texZoom.y := -texZoom.y; 819 currentMaterial.TextureZoom := texZoom; 820 end else 821 if lineType = 'Ns' then currentMaterial.SpecularIndex := round(GetSingle) else 822 if lineType = 'd' then 823 begin 824 v := GetSingle; 825 if v > 1 then 826 currentMaterial.SimpleAlpha := 255 827 else if v < 0 then 828 currentMaterial.SimpleAlpha := 0 829 else 830 currentMaterial.SimpleAlpha := round(v*255); 831 end; 832 end; 833 end; 834 lines.Free; 1965 835 end; 1966 836 … … 2358 1228 LColors[idxL] := BGRA(128,128,128) 2359 1229 else 1230 begin 2360 1231 if ColorOverride then 2361 1232 LColors[idxL] := Color … … 2367 1238 LColors[idxL] := tempV.Color; 2368 1239 end; 1240 end; 2369 1241 2370 1242 if TexCoordOverride then … … 2372 1244 else 2373 1245 LTexCoord[idxL] := tempV.TexCoord; 1246 with LMaterial.GetTextureZoom do 1247 begin 1248 LTexCoord[idxL].x *= x; 1249 LTexCoord[idxL].y *= y; 1250 end; 2374 1251 2375 1252 with tempV.CoordData^ do … … 2380 1257 LZ[idxL] := viewCoord.Z; 2381 1258 end; 1259 if Normal <> nil then 1260 LNormal3D[idxL] := Normal.ViewNormal_128; 2382 1261 end; 2383 1262 end; … … 2389 1268 VCount := VertexCount; 2390 1269 if VCount < 3 then exit; 2391 2392 if ParentTexture then2393 LTexture := Object3D.Texture2394 else2395 LTexture := Texture;2396 1270 2397 1271 if Material <> nil then … … 2403 1277 else 2404 1278 exit; 1279 1280 if ParentTexture then 1281 begin 1282 if LMaterial.GetTexture <> nil then 1283 LTexture := LMaterial.GetTexture 1284 else 1285 LTexture := Object3D.Texture 1286 end 1287 else 1288 LTexture := Texture; 2405 1289 2406 1290 LLightNormal := Object3D.LightingNormal; … … 2635 1519 procedure DrawWithResample; 2636 1520 var 2637 tempSurface ,resampledTempSurface: TBGRACustomBitmap;1521 tempSurface: TBGRACustomBitmap; 2638 1522 begin 2639 1523 tempSurface := ASurface.NewBitmap(ASurface.Width*RenderingOptions.AntialiasingResampleLevel,ASurface.Height*RenderingOptions.AntialiasingResampleLevel); 2640 1524 InternalRender(tempSurface, am3dNone, RenderingOptions.AntialiasingResampleLevel); 2641 resampledTempSurface := tempSurface.Resample(ASurface.Width,ASurface.Height,rmSimpleStretch); 1525 BGRAResample.DownSamplePutImage(tempSurface,RenderingOptions.AntialiasingResampleLevel,RenderingOptions.AntialiasingResampleLevel, 1526 ASurface, 0,0, dmDrawWithTransparency); 2642 1527 tempSurface.Free; 2643 ASurface.PutImage(0,0,resampledTempSurface,dmDrawWithTransparency);2644 resampledTempSurface.Free;2645 1528 end; 2646 1529 … … 2739 1622 Color: TBGRAPixel): TBGRAPixel; 2740 1623 var i: Integer; 2741 begin 1624 m: TBGRAMaterial3D; 1625 begin 1626 m := TBGRAMaterial3D(Context^.material); 1627 if not m.GetAutoSimpleColor then Color := ColorIntToBGRA(BGRAToColorIntMultiply(Color, m.GetSimpleColorInt)); 1628 2742 1629 Context^.lightness := FAmbiantLightness; 2743 1630 … … 2767 1654 Color: TBGRAPixel): TBGRAPixel; 2768 1655 var i: Integer; 2769 begin 2770 Context^.diffuseColor := FAmbiantLightColor; 1656 m: TBGRAMaterial3D; 1657 begin 1658 m := TBGRAMaterial3D(Context^.material); 1659 1660 if m.GetAutoAmbiantColor then 1661 Context^.diffuseColor := FAmbiantLightColor 1662 else 1663 Context^.diffuseColor := FAmbiantLightColor*m.GetAmbiantColorInt; 2771 1664 2772 1665 i := FLights.Count-1; … … 2784 1677 Color: TBGRAPixel): TBGRAPixel; 2785 1678 var i: Integer; 2786 begin 2787 Context^.diffuseColor := FAmbiantLightColor; 1679 m: TBGRAMaterial3D; 1680 begin 1681 m := TBGRAMaterial3D(Context^.material); 1682 1683 if m.GetAutoAmbiantColor then 1684 Context^.diffuseColor := FAmbiantLightColor 1685 else 1686 Context^.diffuseColor := FAmbiantLightColor*m.GetAmbiantColorInt; 2788 1687 Context^.specularColor := ColorInt65536(0,0,0,0); 2789 1688 … … 2802 1701 end; 2803 1702 2804 {$hints off}2805 1703 function TBGRAScene3D.ApplyNoLighting(Context: PSceneLightingContext; 2806 1704 Color: TBGRAPixel): TBGRAPixel; 2807 begin 2808 result := Color; 1705 var 1706 m: TBGRAMaterial3D; 1707 begin 1708 m := TBGRAMaterial3D(Context^.material); 1709 1710 if not m.GetAutoAmbiantColor then 1711 result := ColorIntToBGRA(BGRAToColorIntMultiply(Color, m.GetAmbiantColorInt)) 1712 else 1713 result := Color; 2809 1714 end; 2810 1715 2811 1716 function TBGRAScene3D.ApplyLightingWithAmbiantLightnessOnly( 2812 1717 Context: PSceneLightingContext; Color: TBGRAPixel): TBGRAPixel; 2813 begin 1718 var 1719 m: TBGRAMaterial3D; 1720 begin 1721 m := TBGRAMaterial3D(Context^.material); 1722 1723 if not m.GetAutoAmbiantColor then 1724 Color := ColorIntToBGRA(BGRAToColorIntMultiply(Color, m.GetAmbiantColorInt)); 1725 2814 1726 if FAmbiantLightness <= 0 then 2815 1727 result := BGRA(0,0,0,color.alpha) … … 2817 1729 result := ApplyIntensityFast(Color, FAmbiantLightness); 2818 1730 end; 2819 2820 {$hints on}2821 1731 2822 1732 function TBGRAScene3D.CreateObject: IBGRAObject3D; … … 2963 1873 end; 2964 1874 1875 function TBGRAScene3D.GetMaterialByName(AName: string): IBGRAMaterial3D; 1876 var i: integer; 1877 begin 1878 for i := 0 to MaterialCount-1 do 1879 if AName = Material[i].Name then 1880 begin 1881 result := Material[i]; 1882 exit; 1883 end; 1884 result := nil; 1885 end; 1886 2965 1887 procedure TBGRAScene3D.UpdateMaterials; 2966 1888 var i,j: integer; … … 2997 1919 end; 2998 1920 1921 procedure TBGRAScene3D.ForEachVertex(ACallback: TVertex3DCallback); 1922 var i: integer; 1923 begin 1924 for i := 0 to Object3DCount-1 do 1925 Object3D[i].ForEachVertex(ACallback); 1926 end; 1927 1928 procedure TBGRAScene3D.ForEachFace(ACallback: TFace3DCallback); 1929 var i: integer; 1930 begin 1931 for i := 0 to Object3DCount-1 do 1932 Object3D[i].ForEachFace(ACallback); 1933 end; 1934 1935 initialization 1936 1937 Randomize; 1938 2999 1939 end. 3000 1940
Note:
See TracChangeset
for help on using the changeset viewer.