📄 glfile3ds.pas
字号:
//
// This unit is part of the GLScene Project, http://glscene.org
//
{: GLFile3DS<p>
3DStudio 3DS vector file format implementation.<p>
<b>History :</b><font size=-1><ul>
<li>31/03/07 - DaStr - Added $I GLScene.inc
<li>24/03/07 - DaStr - Added explicit pointer dereferencing
(thanks Burkhard Carstens) (Bugtracker ID = 1678644)
<li>28/01/07 - DaStr - Added transparency and opacity texture support (thanks DIVON)
<li>09/12/04 - LR - Add Integer cast line 94 for Linux
<li>25/10/04 - SG - Added lightmap (3DS IllumMap) support
<li>05/06/03 - SG - Separated from GLVectorFileObjects.pas
</ul></font>
}
unit GLFile3DS;
interface
{$I GLScene.inc}
uses
Classes, SysUtils, GLVectorFileObjects, GLTexture, ApplicationFileIO,
VectorGeometry, File3DS, Types3DS;
type
// TGL3DSVectorFile
//
{: The 3DStudio vector file.<p>
Uses 3DS import library by Mike Lischke (http://www.lishcke-online.de).<p>
A 3DS file may contain material information and require textures when
loading. Only the primary and opacity texture maps are used by GLScene,
bump mapping, etc. are ignored as of now. }
TGL3DSVectorFile = class (TVectorFile)
public
{ Public Declarations }
class function Capabilities : TDataFileCapabilities; override;
procedure LoadFromStream(aStream : TStream); override;
end;
// ------------------------------------------------------------------
// ------------------------------------------------------------------
// ------------------------------------------------------------------
implementation
// ------------------------------------------------------------------
// ------------------------------------------------------------------
// ------------------------------------------------------------------
// ------------------
// ------------------ TGL3DSVectorFile ------------------
// ------------------
// Capabilities
//
class function TGL3DSVectorFile.Capabilities : TDataFileCapabilities;
begin
Result:=[dfcRead,dfcWrite];
end;
// LoadFromStream
//
procedure TGL3DSVectorFile.LoadFromStream(aStream: TStream);
type
TSmoothIndexEntry = array[0..31] of Cardinal;
PSmoothIndexArray = ^TSmoothIndexArray;
TSmoothIndexArray = array[0..MaxInt shr 8] of TSmoothIndexEntry;
var
Marker: PByteArray;
CurrentVertexCount: Integer;
SmoothIndices: PSmoothIndexArray;
mesh : TMeshObject;
hasLightmap : Boolean;
//--------------- local functions -------------------------------------------
function GetOrAllocateMaterial(materials : TMaterialList; const name : String) : String;
var
material : PMaterial3DS;
specColor : TVector;
matLib : TGLMaterialLibrary;
libMat : TGLLibMaterial;
opacMat: TGLLibMaterial;
begin
material:=Materials.MaterialByName[Name];
Assert(Assigned(material));
if GetOwner is TGLBaseMesh then begin
matLib:=TGLBaseMesh(GetOwner).MaterialLibrary;
if Assigned(matLib) then begin
Result:=name;
libMat:=matLib.Materials.GetLibMaterialByName(name);
if not Assigned(libMat) then begin
libMat:=matLib.Materials.Add;
libMat.Name:=name;
with libMat.Material.FrontProperties do begin
Ambient.Color:=VectorMake(material.Ambient.R, material.Ambient.G, material.Ambient.B, 1);
//Yep, material transparency is stored as a negative value :P
Diffuse.Color:=VectorMake(material.Diffuse.R, material.Diffuse.G, material.Diffuse.B,1 - material.Transparency);
specColor:=VectorMake(material.Specular.R, material.Specular.G, material.Specular.B, 1);
ScaleVector(specColor, 1 - material.Shininess);
Specular.Color:=specColor;
Shininess:=MaxInteger(0, Integer(Round((1 - material.ShinStrength) * 128)));
if material.Transparency <> 0 then
libMat.Material.BlendingMode:=bmTransparency;
end;
if Trim(material.Texture.Map.NameStr)<>'' then
try
with libMat.Material.Texture do begin
Image.LoadFromFile(material.Texture.Map.NameStr);
Disabled:=False;
TextureMode:=tmModulate;
end;
except
on E: ETexture do begin
if not Owner.IgnoreMissingTextures then
raise;
end;
end;
if Trim(material.Opacity.Map.NameStr) <> '' then
try
OpacMat:=matLib.Materials.Add;
OpacMat.Material.Texture.Image.LoadFromFile(material.Opacity.Map.NameStr);
OpacMat.Material.Texture.Disabled:=false;
OpacMat.Material.Texture.ImageAlpha:=tiaAlphaFromIntensity;
OpacMat.Material.Texture.TextureMode:=tmModulate;
OpacMat.Name:=material.Opacity.Map.NameStr;
LibMat.Texture2Name:=OpacMat.Name;
LibMat.Material.BlendingMode:=bmTransparency;
except
on E: ETexture do begin
if not Owner.IgnoreMissingTextures then
raise;
end;
end;
end;
end else Result:='';
end else Result:='';
end;
function GetOrAllocateLightMap(materials : TMaterialList; const name : String) : Integer;
var
material : PMaterial3DS;
matLib : TGLMaterialLibrary;
libMat : TGLLibMaterial;
begin
Result:=-1;
material:=Materials.MaterialByName[Name];
Assert(Assigned(material));
if GetOwner is TGLBaseMesh then begin
matLib:=TGLBaseMesh(GetOwner).LightmapLibrary;
if Assigned(matLib) then begin
if Trim(material.IllumMap.Map.NameStr)<>'' then begin
libMat:=matLib.Materials.GetLibMaterialByName(material.IllumMap.Map.NameStr);
if not Assigned(libMat) then begin
libMat:=matLib.Materials.Add;
libMat.Name:=material.IllumMap.Map.NameStr;
try
with libMat.Material.Texture do begin
Image.LoadFromFile(material.IllumMap.Map.NameStr);
Disabled:=False;
TextureMode:=tmModulate;
end;
except
on E: ETexture do begin
if not Owner.IgnoreMissingTextures then
raise;
end;
end;
end;
Result:=libmat.Index;
hasLightMap:=True;
end;
end;
end;
end;
//----------------------------------------------------------------------
function IsVertexMarked(P: Pointer; Index: Integer): Boolean; assembler;
// tests the Index-th bit, returns True if set else False
asm
BT [EAX], EDX
SETC AL
end;
//---------------------------------------------------------------------------
function MarkVertex(P: Pointer; Index: Integer): Boolean; assembler;
// sets the Index-th bit and return True if it was already set else False
asm
BTS [EAX], EDX
SETC AL
end;
//---------------------------------------------------------------------------
procedure StoreSmoothIndex(ThisIndex, SmoothingGroup, NewIndex: Cardinal; P: Pointer);
// Stores new vertex index (NewIndex) into the smooth index array of vertex ThisIndex
// using field SmoothingGroup, which must not be 0.
// For each vertex in the vertex array (also for duplicated vertices) an array of 32 cardinals
// is maintained (each for one possible smoothing group. If a vertex must be duplicated because
// it has no smoothing group or a different one then the index of the newly created vertex is
// stored in the SmoothIndices to avoid loosing the conjunction between not yet processed vertices
// and duplicated vertices.
// Note: Only one smoothing must be assigned per vertex. Some available models break this rule and
// have more than one group assigned to a face. To make the code fail safe the group ID
// is scanned for the lowest bit set.
asm
PUSH EBX
BSF EBX, EDX // determine smoothing group index (convert flag into an index)
MOV EDX, [P] // get address of index array
SHL EAX, 7 // ThisIndex * SizeOf(TSmoothIndexEntry)
ADD EAX, EDX
LEA EDX, [4 * EBX + EAX] // Address of array + vertex index + smoothing group index
MOV [EDX], ECX
POP EBX
end;
//---------------------------------------------------------------------------
function GetSmoothIndex(ThisIndex, SmoothingGroup: Cardinal; P: Pointer): Integer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -