Piter_B |
Отправлено: 06.08.2004, 08:44 |
|
Не зарегистрирован
|
Очень нужно знать, как можно подгрузить объекты из 3DSMAX 5 в C++ Builder и как их правильно использовать в нем... Если можно, то дайте исходник или ссылку на ресурсы — как использовать 3D объекты из других программ в C++ Builder.
Буду очень благодарен. |
|
Shura |
Отправлено: 06.08.2004, 10:29 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 45
|
формат 3DS -
www.wotsit.org
исходник загрузки
www.gametutorials.com |
|
Piter_B |
Отправлено: 06.08.2004, 10:52 |
|
Не зарегистрирован
|
Спасибо! Открыл для себя много ценного...
Кстати, я помоему только-что нарыл тоже много ценного на:
http://www.3dborland.com/downloads.asp
кому надо заходите, мне не жалко!
Если есть еще, что-то интересное по этой теме, пишите. |
|
Piter_B |
Отправлено: 07.08.2004, 10:38 |
|
Не зарегистрирован
|
Упс...
Найти то нашел, но оно на Паскале... Как сие чудо заставить работать в Билдере?
Файл gl3ds.pas:
CODE |
//TODO:
// save skeleton msa and bin
// save skeleton animations msa and bin
// load skeleton (with animations) bin
// clean up code...
// example load save example (converter)
// example vertex picking (selection of face)... And assign bone to it...
// selected propertie for mesh, face, vertex and bone
//02.08.2004 by Noeska Software (now uses glbitmap.pas instead of textures.pas)
//01.08.2004 by Noeska Software (bump mapping)
//27.06.2004 by Noeska Software (do not calculate bounding boxes for non mesh objects)
//20.06.2004 by Noeska Software (bounding boxes per submesh)
//15.06.2004 by Noeska Software (bugfixed: cw to ccw, color loading in msa, transparency)
//14.06.2004 by Noeska Software (changed rendering from cw to ccw, transparency with msa and bin)
//14.06.2004 by SOS (two sided materials)
//15.04.2004 by Noeska Software (bin save and load)
//14.04.2004 by Noeska Software (allow saving of milkshape ascii files)
//12.04.2004 by Noeska Software (seperated bones from mesh using a skeleton class, allows ussage of multiple different bone animations per mesh)
//??.03.2004 by Noeska Software (fixed milkshape ascii support, now works again)
//14.02.2004 by Noeska Software (allow adding faces and assign material to a mesh, not yet optimized)
//08.02.2004 by Noeska Software (allow adding materials and meshes...)
//26.01.2004 by Noeska Software (improved transparency mesh order, corrected skipping light and camera chunks)
//25.01.2004 by Noeska Software (transparency added)
//15.01.2004 by Noeska Software (rewrote (some) source to borland standard, added displaylist renderer)
//06.10.2003 by Noeska Software (ms3d ascii bone animation, thanks to Maarten "McCLaw" Kronberger)
//05.10.2003 by Noeska Software (3ds meshes with no material and no texture coordinates)
//02.10.2003 by Noeska Software (ms3d ascii loader)
//01.10.2003 by Noeska Software (textures are back, added some more properties, SwitchAxesP is not used anymore)
//30.09.2003 by Noeska Software (converted to classes, optimized setting matarial on rendering)
//24.09.2003 by Noeska Software (uses pivot points to draw meshes when needed, removed matrix)
//21.09.2003 by Noeska Software (more then 1 material per submesh, smoothed normals, dummy submeshes)
//18.09.2003 by Noeska Software (rewrite to 1 chunk parser) now it also reads non-standard 3ds files.
//16.09.2003 by Noeska Software
//08.09.2002 by Noeska Software
//01.05.2002 by Jan Michalowsky
//Thx a lot Prometheus,Poetikus
//Version 2.4a
unit gl3ds;
interface
uses Windows, Classes, SysUtils, DGLOpenGL, GLMath, Math, glBitmap, glMatrix{, logger};
const
//numbering may change so use names instead of numbers
MeshBin = 64; //own bin format...
MeshMs3d = 16; //bin milkshape mesh and/or animation
MeshMsa = 8; //ascii milkshape mesh and/or animation
Mesh3dsBvh = 4; //3ds with bvh animation (does not work yet)
Mesh3dsa = 2; //3ds with keyframe animation
Mesh3ds = 1; //3ds
//channel types for milkshape bone animation
ChanneltypeNone = 0; //no channel applied
ChanneltypeScaleRotateTranslate = 1; //scale rotation and translation (bva)
ChanneltypeTranslate = 2; //translation x y z
ChanneltypeRxyz = 4; //rotation x y z order
ChanneltypeRzxy = 8; //rotation z x y order
ChanneltypeRyzx = 16; //rotation y z x order
ChanneltypeRzyx = 32; //rotation z y x order
ChanneltypeRxzy = 64; //rotation x z y order
ChanneltypeRyxz = 128; //rotation y x z order
ChanneltypeScale = 256; //scale only
ChanneltypeTranslateXyz = 512; //translate x y z only
channeltypeInterleaved = 1024; //multiple channels?
type
//texturemapping coords
TMap = packed record
tu: single;
tv: single;
end;
//keyframe data
TKeyFrame = packed record
time: integer;
Value: T3dPoint;
bvh_value: T3dPoint;
end;
//bone data
T3dsBone = class(TComponent)
private
FName: string;
FParentName: string;
FParent: T3dsBone; //direct access to the parent bone
FTranslate: T3dPoint;
FRotate: T3dPoint;
FBvhChanneltype: integer;
FMatrix: ClsMatrix; //absolute in accordance to animation
FNumTranslateFrames: integer;
FNumRotateFrames: integer;
FTranslateFrame: array of TKeyFrame;
FRotateFrame: array of TKeyFrame;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Init;
procedure Render;
procedure AdvanceAnimation;
property Name: string read FName;
property ParentName: string read FParentName;
property Translate: T3DPoint read FTranslate;
property Rotate: T3DPoint read FRotate;
//TODO: add access to keyframes data
end;
T3dsMesh = class(TComponent)
private
Fname: string; //meshname
Fid: integer; //id for picking...
Fmatname: array of string; //array of material names.
Fnumvertex: integer; //number of vertexes
Fnumindices: integer; //number of faces
Fpivot: T3DPoint; //where to draw submesh (also for anim?)
Fvertex: array of T3dpoint; //vertexes
Fboneid: array of integer; //boneid for a vertex
Fvnormal: array of T3dPoint; //vertex normals for smoother meshes
Fmapping: array of TMap; //uvmapping
Fmatid: array of word; //material for a face
Findices: array of word; //faces
Fnormalindices: array of word; //normal index
FDisplaylist: integer; //displaylist id
FMinimum: T3dPoint; //min pos
FMaximum: T3dPoint; //max pos
function GetVertex(Index: integer): T3dPoint;
function GetNormal(Index: integer): T3dPoint;
function GetMapping(Index: integer): TMap;
procedure SetMapping(Index: integer; Value: TMap);
function GetMatID(Index: integer): word;
function GetFace(Index: integer): word;
public
destructor Destroy; override;
procedure Render;
procedure RenderBoundBox;
procedure CalculateSize;
procedure BuildDisplayList;
procedure AddFace(v1, v2, v3: T3DPoint; matname: string);
property Name: string read FName write FName;
property Id: integer read FId write FId;
property NumVertex: integer read FNumVertex;
property NumFaces: integer read FNumIndices;
property Vertex[Index: integer]: T3dPoint read GetVertex;
property Normal[Index: integer]: T3dPoint read GetNormal;
property Mapping[Index: integer]: TMap read GetMapping write SetMapping;
property MatID[Index: integer]: word read GetMatID;
property Face[Index: integer]: word read GetFace;
property Maximum: T3dPoint read FMaximum;
property Minimum: T3dPoint read FMinimum;
end;
T3dsMaterial = class(TComponent)
private
FHastexturemap: boolean;
FHasbumpmap: boolean;
FHasmaterial: boolean;
FIsAmbient: boolean;
FIsDiffuse: boolean;
FIsSpecular: boolean;
FTwoSided: boolean;
FName: string;
FFileName: string;
FBumpMapFileName: string;
FUs: single;
FVs: single;
FUoff: single;
FVoff: single;
FRot: single;
FAmbR: single;
FAmbG: single;
FAmbB: single;
FDifR: single;
FDifG: single;
FDifB: single;
FSpcR: single;
FSpcG: single;
FSpcB: single;
FTransparency: single;
FBumpMapStrength: single;
FTexId: integer;
FTexture: TglBitmap2D;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Apply;
procedure Updatetexture;
property Name: string read FName write FName;
property HasMaterial: boolean read FHasMaterial write FHasMaterial;
property IsAmbient: boolean read FIsambient write FIsambient;
property IsDiffuse: boolean read FIsdiffuse write FIsdiffuse;
property IsSpecular: boolean read FIsSpecular write FIsSpecular;
property TwoSided: boolean read FTwoSided write FTwoSided;
property HasTexturemap: boolean read FHasTexturemap write FHasTexturemap;
property HasBumpmap: boolean read FHasBumpmap write FHasBumpmap;
property TextureFilename: string read FFileName write FFileName;
property BumpMapFilename: string read FBumpMapFileName write FBumpMapFileName;
property TextureID: integer read FTexId;
property Us: single read FUs write FUs;
property Vs: single read FVs write FVs;
property Uoff: single read FUoff write FUoff;
property Voff: single read FVoff write FVoff;
property Rotate: single read FRot write FRot;
property AmbientRed: single read FAmbr write FAmbr;
property AmbientGreen: single read FAmbg write FAmbg;
property AmbientBlue: single read FAmbb write FAmbb;
property DiffuseRed: single read FDifr write FDifr;
property DiffuseGreen: single read FDifg write FDifg;
property DiffuseBlue: single read FDifb write FDifb;
property SpecularRed: single read FSpcr write FSpcr;
property SpecularGreen: single read FSpcg write FSpcg;
property SpecularBlue: single read FSpcb write FSpcb;
property Transparency: single read FTransparency write FTransparency;
property Bumpmapstrength: single read FBumpmapstrength write FBumpMapStrength;
property TexID: integer read FTexId write FTexID;
end;
TSkeleton = class(TComponent)
private
FName: string;
FBone: array of T3dsBone;
FNumBones: integer;
FNumFrames: integer;
FCurrentFrame: integer;
function GetBone(Index: integer): T3dsBone;
procedure LoadBvhFromFile(Filename: string);
procedure LoadBvhFromStream(Stream: TStream);
procedure LoadMsaFromFile(filename: string);
procedure LoadMsaFromStream(stream: Tstream);
public
destructor Destroy; override;
property Name: string read FName write FName;
property NumBones: integer read FNumBones;
property NumFrames: integer read FNumFrames;
property CurrentFrame: integer read FCurrentFrame write FCurrentFrame;
property Bone[Index: integer]: T3dsBone read GetBone;
function GetBoneByName(s: string): T3dsBone;
procedure AdvanceAnimation;
procedure LoadFromFile(Filename: string);
procedure LoadFromStream(Stream: TStream);
end;
TAll3dsMesh = class(TComponent)
private
FName: string;
FType: integer;
FMasterScale: single;
FDisplayList: TGlInt;
FMesh: array of T3dsMesh;
FRenderOrder: array of integer;
FMaterial: array of T3dsMaterial;
FSkeleton: array of TSkeleton;
FNumSkeletons: integer;
FCurrentSkeleton: integer;
FLoadSkeleton: boolean;
FMinimum: T3dPoint;
FMaximum: T3dPoint;
FVersion: integer;
FSubVersion: integer;
FNumMeshes: integer;
FNumMaterials: integer;
FTexturePath: string;
function GetMesh(Index: integer): T3dsMesh;
function GetMaterial(Index: integer): T3dsMaterial;
function GetMaterialIdByName(s: string): integer;
function GetSkeleton(Index: integer): TSkeleton;
procedure MoveToPivot;
procedure CalculateScale;
procedure CalculateRenderOrder;
procedure LoadMsaFromFile(filename: string);
procedure LoadMsaFromStream(stream: Tstream);
procedure Load3dsFromFile(filename: string);
procedure Load3dsFromStream(stream: Tstream);
procedure LoadBinFromFile(filename: string);
procedure LoadBinFromStream(stream: Tstream);
procedure SaveMsaToFile(filename: string);
procedure SaveMsaToStream(stream: Tstream);
procedure SaveBinToFile(filename: string);
procedure SaveBinToStream(stream: Tstream);
public
destructor Destroy; override;
property Name: string read FName write FName;
property FileType: integer read FType write FType;
property MasterScale: single read FMasterScale write FMasterScale;
property Version: integer read FVersion;
property SubVersion: integer read FSubVersion;
property NumMeshes: integer read FNumMeshes;
property NumMaterials: integer read FNumMaterials;
property Maximum: T3dPoint read FMaximum;
property Minimum: T3dPoint read FMinimum;
property TexturePath: string read FTexturePath write FTexturePath;
property Mesh[Index: integer]: T3dsMesh read GetMesh;
property Material[Index: integer]: T3dsMaterial read GetMaterial;
property Skeleton[Index: integer]: TSkeleton read GetSkeleton;
property NumSkeletons: integer read FNumSkeletons;
property CurrentSkeleton: integer read FCurrentSkeleton write FCurrentSkeleton;
procedure Render;
procedure RenderBoundBox;
procedure CalculateSize;
procedure BuildDisplayList;
procedure LoadFromFile(Filename: string);
procedure LoadFromStream(Stream: TStream);
procedure SaveToFile(Filename: string);
procedure SaveToStream(Stream: TStream);
function GetMeshByName(s: string): T3dsMesh;
function GetMaterialByName(s: string): T3dsMaterial;
procedure InitSkin;
procedure CalcVnormals;
procedure AddMesh;
procedure AddMaterial;
procedure AddSkeleton;
end;
procedure preloadtextures(mesh: Tall3dsMesh);
procedure startpickmode;
procedure endpickmode;
var
pickmode: boolean;
pickmesh: boolean;
pickface: boolean;
pickvertex: boolean;
//TODO: also read lights form 3ds file
//TODO: also make light class...
objlightpos: T3dPoint; //lightpos needed for bumpmap calculations
implementation
const
OVersion = 3; //expects 3ds version 3 files
//Chunk ID's
// INT_PERCENTAGE = $0030; //hm transparency always has this subchunck
MAIN3DS = $4D4D;
VERS3DS = $0002;
EDIT3DS = $3D3D;
KEYF3DS = $B000;
EDIT_OBJECT = $4000;
MASTER_SCALE = $0100;
OBJ_HIDDEN = $4010;
OBJ_VERINFO = $3D3E;
OBJ_TRIMESH = $4100;
OBJ_LIGHT = $4600;
OBJ_CAMERA = $4700;
TRI_VERTEXL = $4110;
TRI_FACEL1 = $4120;
TRI_MATERIAL = $4130;
TRI_MAPPINGCOORDS = $4140;
TRI_MATRIX = $4160;
MAT_MATRIAL = $AFFF;
MAT_MATNAME = $A000;
MAT_AMBIENT = $A010;
MAT_DIFFUSE = $A020;
MAT_SPECULAR = $A030;
MAT_TRANSPARENCY = $A050; // Transparency Material
MAT_TEXTURE = $A200; //texmap
MAT_BUMPMAP = $A230;
MAT_MAPFILE = $A300;
MAT_VSCALE = $A354;
MAT_USCALE = $A356;
MAT_VOFF = $A35A;
MAT_UOFF = $A358;
MAT_TEXROT = $A35C;
MAT_COLOR = $0010;
MAT_COLOR24 = $0011;
MAT_TWO_SIDE = $A081; //thanks sos
KEYF_OBJDES = $B002;
KEYF_OBJHIERARCH = $B010;
KEYF_OBJPIVOT = $B013;
type
T3DSColor = packed record
r, g, b: single;
end;
rgb = packed record
r, g, b: byte
end;
TChunkHdr = packed record
chunkID: word;
chunkLE: longword;
end;
procedure startpickmode;
begin
pickmode:=true;
glDisable(GL_LIGHTING);
glDisable(GL_DITHER);
end;
procedure endpickmode;
begin
pickmode:=false;
glEnable(GL_LIGHTING);
glEnable(GL_DITHER);
end;
//T3DSBone routines ...
constructor T3DSBone.Create(AOwner: TComponent);
begin
inherited Create(AOWner);
FMatrix := clsMatrix.Create;
end;
destructor T3DSBone.Destroy;
begin
FMatrix.Free;
SetLength(FTranslateFrame, 0);
SetLength(FRotateFrame, 0);
//free parent also?
inherited Destroy;
end;
procedure T3DSBone.init;
var
m_rel: clsMatrix;
tempm: array [0..15] of single;
tempv: array [0..2] of single;
begin
glpushmatrix();
//init parent bone direct access
FParent := nil;
if FParentName > '' then
FParent := TSkeleton(owner).GetBoneByName(FParentName);
//calculate the matrix for the bone
m_rel := clsMatrix.Create;
//m_rel.loadIdentity;
// Create a transformation matrix from the position and rotation
tempv[0] := FRotate.x;
tempv[1] := FRotate.y;
tempv[2] := FRotate.z;
m_rel.setRotationRadians(tempv);
tempv[0] := FTranslate.x;
tempv[1] := FTranslate.y;
tempv[2] := FTranslate.z;
m_rel.setTranslation(tempv);
// Each bone's final matrix is its relative matrix concatenated onto its
// parent's final matrix (which in turn is ....)
if (FParent = nil) then
begin
m_rel.getMatrix(tempm);
FMatrix.setMatrixValues(tempm);
end
else
begin
FParent.FMatrix.getMatrix(tempm);
FMatrix.setMatrixValues(tempm);
FMatrix.postMultiply(m_rel);
end;
m_rel.Free;
glpopmatrix();
end;
procedure T3DSBone.render;
var
parentvertex, vertex: T3DPoint;
begin
vertex.x := 0;
vertex.y := 0;
vertex.z := 0;
vertex := MatrixTransform(FMatrix, Vertex);
if FParent <> nil then
begin
parentvertex.x := 0;
parentvertex.y := 0;
parentvertex.z := 0;
parentvertex := MatrixTransform(FParent.FMatrix, ParentVertex);
end;
glPointSize(4.0);
glBegin(GL_POINTS);
glvertex3fv(@vertex);
glend;
if FParent <> nil then
begin
glBegin(GL_LINES);
glvertex3fv(@vertex);
glvertex3fv(@parentvertex);
glend;
glPointSize(4.0);
glBegin(GL_POINTS);
glvertex3fv(@parentvertex);
glend;
end;
end;
procedure T3DSBone.AdvanceAnimation;
var
i: integer;
deltaTime: single;
fraction: single;
Position: array [0..2] of single;
Rotation: array [0..2] of single;
m_rel, m_frame: clsMatrix;
tempm: array [0..15] of single;
tvec: array [0..2] of single;
begin
// Position
// Find appropriate position key frame
i := 0;
while ((i < FNumTranslateFrames — 1) and (FTranslateFrame[i].Time <
TSkeleton(owner).FCurrentFrame)) do
i := i + 1;
if (i > 0) then
begin
// Interpolate between 2 key frames
// time between the 2 key frames
deltaTime := FTranslateFrame[i].Time — FTransLateFrame[i — 1].Time;
// relative position of interpolation point to the keyframes [0..1]
fraction := (TSkeleton(owner).FCurrentFrame — FTransLateFrame[i — 1].Time) / deltaTime;
Position[0] := FTransLateFrame[i — 1].Value.x + fraction *
(FTransLateFrame[i].Value.x — FTransLateFrame[i — 1].Value.x);
Position[1] := FTransLateFrame[i — 1].Value.y + fraction *
(FTransLateFrame[i].Value.y — FTransLateFrame[i — 1].Value.y);
Position[2] := FTransLateFrame[i — 1].Value.z + fraction *
(FTransLateFrame[i].Value.z — FTransLateFrame[i — 1].Value.z);
end
else
begin
Position[0] := FTransLateFrame[i].Value.x;
Position[1] := FTransLateFrame[i].Value.y;
Position[2] := FTransLateFrame[i].Value.z;
end;
// Rotation
// Find appropriate rotation key frame
i := 0;
while ((i < FNumRotateFrames — 1) and (FRotateFrame[i].Time <
TSkeleton(owner).CurrentFrame)) do
i := i + 1;
if (i > 0) then
begin
// Interpolate between 2 key frames
// time between the 2 key frames
deltaTime := FRotateFrame[i].Time — FRotateFrame[i — 1].Time;
// relative position of interpolation point to the keyframes [0..1]
fraction := ({TAll3DSMesh}TSkeleton(Owner).CurrentFrame — FRotateFrame[i — 1].Time) / deltaTime;
Rotation[0] := FRotateFrame[i — 1].Value.x + fraction *
(FRotateFrame[i].Value.x — FRotateFrame[i — 1].Value.x);
Rotation[1] := FRotateFrame[i — 1].Value.y + fraction *
(FRotateFrame[i].Value.y — FRotateFrame[i — 1].Value.y);
Rotation[2] := FRotateFrame[i — 1].Value.z + fraction *
(FRotateFrame[i].Value.z — FRotateFrame[i — 1].Value.z);
end
else
begin
Rotation[0] := FRotateFrame[i].Value.x;
Rotation[1] := FRotateFrame[i].Value.y;
Rotation[2] := FRotateFrame[i].Value.z;
end;
// Now we know the position and rotation for this animation frame.
// Let's calculate the transformation matrix (_matrix) for this bone...
m_rel := clsMatrix.Create;
m_frame := clsMatrix.Create;
// Create a transformation matrix from the position and rotation of this
// joint in the rest position
tvec[0] := FRotate.x;
tvec[1] := FRotate.y;
tvec[2] := FRotate.z;
m_rel.setRotationRadians(tvec);
tvec[0] := FTranslate.x;
tvec[1] := FTranslate.y;
tvec[2] := FTranslate.z;
m_rel.setTranslation(tvec);
// Create a transformation matrix from the position and rotation
// m_frame: additional transformation for this frame of the animation
m_frame.setRotationRadians(Rotation);
m_frame.setTranslation(Position);
// Add the animation state to the rest position
m_rel.postMultiply(m_frame);
if (FParent = nil) then // this is the root node
begin
m_rel.getMatrix(tempm);
FMatrix.setMatrixValues(tempm); // _matrix := m_rel
end
else // not the root node
begin
// _matrix := parent's _matrix * m_rel (matrix concatenation)
FParent.FMatrix.getMatrix(tempm);
FMatrix.setMatrixValues(tempm);
FMatrix.postMultiply(m_rel);
end;
m_frame.Free;
m_rel.Free;
end;
//TSkeleton routines ...
procedure TSkeleton.LoadFromFile(filename: string);
begin
fname:=filename;
if LowerCase(copy(filename, length(filename) — 3, 4)) = '.bvh' then
LoadBVHFromFile(Filename);
if LowerCase(copy(filename, length(filename) — 3, 4)) = '.txt' then
LoadMSAFromFile(Filename);
end;
procedure TSkeleton.LoadFromStream(stream: Tstream);
begin
if TAll3dsMesh(owner).FType = Mesh3dsBVH then
LoadBVHFromStream(stream);
if TAll3dsMesh(owner).FType = MeshMsa then
LoadMSAFromStream(stream);
end;
destructor TSkeleton.Destroy;
begin
inherited Destroy; //this will automaticaly free the meshes, materials, bones...
//however do free the dynamic arrays used
SetLength(FBone, 0);
end;
function TSkeleton.GetBoneByName(s: string): T3DSBone;
var
i: word;
begin
Result := nil;
for i := 0 to High(FBone) do
if uppercase(FBone[i].FName) = uppercase(s) then
begin
Result := FBone[i];
break;
end;
end;
procedure TSkeleton.AdvanceAnimation;
var
m: integer;
begin
//increase the currentframe
FCurrentFrame := FCurrentFrame + 1;
if FCurrentFrame > FNumFrames then FCurrentFrame := 1; //reset when needed
//set the bones to their new positions
if FNumBones > 0 then
for m := 0 to FNumBones — 1 do
begin
FBone[m].AdvanceAnimation;
end;
end;
function TSkeleton.GetBone(Index: integer): T3DSBone;
begin
Result := FBone[index];
end;
procedure TSkeleton.LoadBvhFromFile(filename: string);
var
stream: TFileStream;
begin
TAll3dsMesh(owner).FType := Mesh3dsBvh;
stream := TFilestream.Create(Filename, fmOpenRead);
LoadBvhFromStream(stream);
stream.Free;
end;
procedure TSkeleton.LoadBvhFromStream(stream: Tstream);
var
mem: TStringList;
parseline: TStringList;
loop, parselineloop: integer;
line: string;
tbld, tempbonelevel, bonelevel, maxbonelevel, childparentbone,
parentbone, channelcount, framecount: integer;
endsite: boolean;
tempparentname: string;
m: integer;
downlevel: boolean;
nbl: integer;
First: boolean;
mybone: integer;
begin
TAll3dsMesh(owner).FType := Mesh3dsBvh;
// Create a StringList and load in BVH file
mem := TStringList.Create;
mem.loadfromstream(stream);
channelcount := 0;
bonelevel := 0;
tempbonelevel := 0;
maxbonelevel := 0;
nbl := 0;
endsite := False;
// Parse through the whole BVH file
for loop := 0 to mem.Count — 1 do
begin
line := mem.Strings[loop];
if Line <> '' then
begin
//Set bone hierarchie level up
if Pos('{', lowercase(line)) > 0 then
begin
bonelevel := bonelevel + 1; //points to parent bone id
//downlevel:=false;
end;
//Set bone hierarchie level down
if Pos('}', lowercase(line)) > 0 then
begin
bonelevel := bonelevel — 1;
downlevel := True;
end;
//Find End Site joint
if Pos('end site', lowercase(line)) > 0 then
begin
endsite := True;
//ignore it for the time being (later make it a bone?)
//treat it like a bone with no anim data put with a position?
end;
//Find root bone
if Pos('root', lowercase(line)) > 0 then
begin
maxbonelevel := maxbonelevel + 1;
FNumBones := maxbonelevel;
setlength(FBone, maxbonelevel);
FBone[maxbonelevel — 1] := t3dsbone.Create(self);
FBone[maxbonelevel — 1].FName :=
trim(copy(line, Pos('root', lowercase(line)) + 5,Length(line) — Pos('root',
lowercase(line)) + 5));
FBone[maxbonelevel — 1].FParentname := ''; //no parent;
tempparentname := FBone[maxbonelevel — 1].FName;
end;
//Find child bone
if Pos('joint', lowercase(line)) > 0 then
begin
maxbonelevel := maxbonelevel + 1;
FNumBones := maxbonelevel;
setlength(FBone, maxbonelevel);
FBone[maxbonelevel — 1] := t3dsbone.Create(self);
FBone[maxbonelevel — 1].FName :=
trim(copy(line, Pos('joint', lowercase(line)) + 5,Length(line) — Pos('root',
lowercase(line)) + 5));
FBone[maxbonelevel — 1].FParentname := tempparentname;
tempparentname := FBone[maxbonelevel — 1].FName;
if downlevel then
begin
FBone[maxbonelevel — 1].FParentname :=
FBone[bonelevel — 1].FName;
downlevel := False;
end;
end;
//Find the offset (translate) for the current bone
if Pos('offset', lowercase(line)) > 0 then
begin
if endsite = False then
begin
//create a stringlist for current frame values
parseline := TStringList.Create;
//sepperate the values frim line in a list
parseline.CommaText :=
trim(copy(line, Pos('offset', lowercase(line)) + 7,Length(line) — Pos('offset',
lowercase(line)) + 7));;
FBone[maxbonelevel — 1].FTranslate.x :=
StrToFloat(ParseLine.Strings[0]);
FBone[maxbonelevel — 1].FTranslate.y :=
StrToFloat(ParseLine.Strings[1]);
FBone[maxbonelevel — 1].FTranslate.z :=
StrToFloat(ParseLine.Strings[2]);
//no rotation in the skeleton definition of bvh
FBone[maxbonelevel — 1].FRotate.x := 0.0;
FBone[maxbonelevel — 1].FRotate.y := 0.0;
FBone[maxbonelevel — 1].FRotate.z := 0.0;
//destroy the stringlist for parsing the currentframe
parseline.Clear;
parseline.Free;
end
else
begin
endsite := False;
end;
end;
//Find the channels (like xrot, xpos, yrot ...)
if Pos('channels', lowercase(line)) > 0 then
begin
if endsite = False then
begin
//create a stringlist for current frame values
parseline := TStringList.Create;
//sepperate the values frim line in a list
parseline.CommaText :=
trim(copy(lowercase(line), Pos('channels', lowercase(line)) + 9,Length(line)
- Pos('channels', lowercase(line)) + 9));
//read in the frametypes
if bonelevel > 1 then
begin
//for child bones
channelcount := channelcount + StrToInt(ParseLine.Strings[0]);
//find rotatation order...
if ParseLine.Strings[1] = 'xposition' then
begin
FBone[maxbonelevel — 1].FBvhChanneltype :=
ChanneltypeTranslate;
if (ParseLine.Strings[4] = 'xrotation') and
(ParseLine.Strings[5] = 'yrotation') and (ParseLine.Strings[6] = 'zrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := Channeltypetranslate + ChanneltypeRxyz;
if (ParseLine.Strings[4] = 'zrotation') and
(ParseLine.Strings[5] = 'xrotation') and (ParseLine.Strings[6] = 'yrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate + ChanneltypeRzxy;
if (ParseLine.Strings[4] = 'yrotation') and
(ParseLine.Strings[5] = 'zrotation') and (ParseLine.Strings[6] = 'xrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate + ChanneltypeRyzx;
if (ParseLine.Strings[4] = 'zrotation') and
(ParseLine.Strings[5] = 'yrotation') and (ParseLine.Strings[6] = 'xrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate + ChanneltypeRzyx;
if (ParseLine.Strings[4] = 'xrotation') and
(ParseLine.Strings[5] = 'zrotation') and (ParseLine.Strings[6] = 'yrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate + ChanneltypeRxzy;
if (ParseLine.Strings[4] = 'yrotation') and
(ParseLine.Strings[5] = 'xrotation') and (ParseLine.Strings[6] = 'zrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := channeltypeTranslate + ChanneltypeRyxz;
end;
if (ParseLine.Strings[1] = 'xrotation') and
(ParseLine.Strings[2] = 'yrotation') and (ParseLine.Strings[3] = 'zrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRxyz;
if (ParseLine.Strings[1] = 'zrotation') and
(ParseLine.Strings[2] = 'xrotation') and (ParseLine.Strings[3] = 'yrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRzxy;
if (ParseLine.Strings[1] = 'yrotation') and
(ParseLine.Strings[2] = 'zrotation') and (ParseLine.Strings[3] = 'xrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRyzx;
if (ParseLine.Strings[1] = 'zrotation') and
(ParseLine.Strings[2] = 'yrotation') and (ParseLine.Strings[3] = 'xrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRzyx;
if (ParseLine.Strings[1] = 'xrotation') and
(ParseLine.Strings[2] = 'zrotation') and (ParseLine.Strings[3] = 'yrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRxzy;
if (ParseLine.Strings[1] = 'yrotation') and
(ParseLine.Strings[2] = 'xrotation') and (ParseLine.Strings[3] = 'zrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRyxz;
end
else
begin
// for the root bone
channelcount := channelcount + StrToInt(ParseLine.Strings[0]);
//find rotatation order...
if ParseLine.Strings[1] = 'xposition' then
begin
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate;
if (ParseLine.Strings[4] = 'xrotation') and
(ParseLine.Strings[5] = 'yrotation') and (ParseLine.Strings[6] = 'zrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate + ChanneltypeRxyz;
if (ParseLine.Strings[4] = 'zrotation') and
(ParseLine.Strings[5] = 'xrotation') and (ParseLine.Strings[6] = 'yrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate + ChanneltypeRzxy;
if (ParseLine.Strings[4] = 'yrotation') and
(ParseLine.Strings[5] = 'zrotation') and (ParseLine.Strings[6] = 'xrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate + ChanneltypeRyzx;
if (ParseLine.Strings[4] = 'zrotation') and
(ParseLine.Strings[5] = 'yrotation') and (ParseLine.Strings[6] = 'xrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate + ChanneltypeRzyx;
if (ParseLine.Strings[4] = 'xrotation') and
(ParseLine.Strings[5] = 'zrotation') and (ParseLine.Strings[6] = 'yrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate + ChanneltypeRxzy;
if (ParseLine.Strings[4] = 'yrotation') and
(ParseLine.Strings[5] = 'xrotation') and (ParseLine.Strings[6] = 'zrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeTranslate + ChanneltypeRyxz;
end;
if (ParseLine.Strings[1] = 'xrotation') and
(ParseLine.Strings[2] = 'yrotation') and (ParseLine.Strings[3] = 'zrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRxyz;
if (ParseLine.Strings[1] = 'zrotation') and
(ParseLine.Strings[2] = 'xrotation') and (ParseLine.Strings[3] = 'yrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRzxy;
if (ParseLine.Strings[1] = 'yrotation') and
(ParseLine.Strings[2] = 'zrotation') and (ParseLine.Strings[3] = 'xrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRyzx;
if (ParseLine.Strings[1] = 'zrotation') and
(ParseLine.Strings[2] = 'yrotation') and (ParseLine.Strings[3] = 'xrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRzyx;
if (ParseLine.Strings[1] = 'xrotation') and
(ParseLine.Strings[2] = 'zrotation') and (ParseLine.Strings[3] = 'yrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRxzy;
if (ParseLine.Strings[1] = 'yrotation') and
(ParseLine.Strings[2] = 'xrotation') and (ParseLine.Strings[3] = 'zrotation') then
FBone[maxbonelevel — 1].FBvhChanneltype := ChanneltypeRyxz;
end;
//destroy the stringlist for parsing the current bone frametypes
parseline.Clear;
parseline.Free;
end
else
begin
endsite := False;
end;
end;
//Find number of Frames
if Pos('frames', lowercase(line)) > 0 then
begin
FNumFrames := StrToInt(trim(copy(line,
Pos(':', lowercase(line)) + 1,Length(line) — Pos(':', lowercase(line)) + 1)));
FCurrentFrame := 0; //reset currentframe!
end;
//read in animation
if (Pos('end site', lowercase(line)) = 0) and
(Pos('{', lowercase(line)) = 0) and (Pos('}', lowercase(line)) = 0) and
(Pos('root', lowercase(line)) = 0) and (Pos('joint', lowercase(line)) = 0) and
(Pos('offset', lowercase(line)) = 0) and (Pos('hierarchy', lowercase(line)) = 0) and
(Pos('motion', lowercase(line)) = 0) and (Pos('frame time', lowercase(line)) = 0) and
(Pos('frames', lowercase(line)) = 0) and (Pos('channels', lowercase(line)) = 0) then
begin
FCurrentFrame := FCurrentFrame + 1;
//create a stringlist for current frame values
parseline := TStringList.Create;
//sepperate the values frim line in a list
parseline.CommaText := line;
parselineloop := 0;
mybone := 0;
for m := 0 to FNumBones — 1 do
begin
if mybone <> m then
begin
mybone := m;
//parselineloop:=0;
end;
FBone[m].FNumTranslateFrames := FNumFrames;
FBone[m].FNumRotateFrames := FNumFrames;
SetLength(FBone[m].FTranslateFrame, FNumframes);
SetLength(FBone[m].FRotateFrame, FNumframes);
if FBone[m].FBvhChanneltype = ChanneltypeTranslate + ChanneltypeRxzy then
begin
FBone[m].FTranslateframe[FCurrentFrame — 1].time := FCurrentFrame;
FBone[m].FRotateframe[FCurrentFrame — 1].time := FCurrentFrame;
FBone[m].FTranslateframe[FCurrentFrame — 1].bvh_value.x :=
StrToFloat(parseline.strings[parselineloop + 0]);
FBone[m].FTranslateframe[FCurrentFrame — 1].bvh_value.y :=
StrToFloat(parseline.strings[parselineloop + 1]);
FBone[m].FTranslateframe[FCurrentFrame — 1].bvh_value.z :=
StrToFloat(parseline.strings[parselineloop + 2]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.x :=
StrToFloat(parseline.strings[parselineloop + 3]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.y :=
StrToFloat(parseline.strings[parselineloop + 4]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.z :=
StrToFloat(parseline.strings[parselineloop + 5]);
parselineloop := parselineloop + 6;
end;
if FBone[m].FBvhChanneltype = ChanneltypeRxzy then
begin
FBone[m].FRotateframe[FCurrentFrame — 1].time := FCurrentFrame;
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.x :=
StrToFloat(parseline.strings[parselineloop + 0]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.z :=
StrToFloat(parseline.strings[parselineloop + 1]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.y :=
StrToFloat(parseline.strings[parselineloop + 2]);
parselineloop := parselineloop + 3;
end;
if FBone[m].FBvhChanneltype = ChanneltypeRxyz then
begin
FBone[m].FRotateframe[FCurrentFrame — 1].time := FCurrentFrame;
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.x :=
StrToFloat(parseline.strings[parselineloop + 0]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.y :=
StrToFloat(parseline.strings[parselineloop + 1]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.z :=
StrToFloat(parseline.strings[parselineloop + 2]);
parselineloop := parselineloop + 3;
end;
if FBone[m].FBvhChanneltype = ChanneltypeRzxy then
begin
FBone[m].FRotateframe[FCurrentFrame — 1].time := FCurrentFrame;
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.z :=
StrToFloat(parseline.strings[parselineloop + 0]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.x :=
StrToFloat(parseline.strings[parselineloop + 1]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.y :=
StrToFloat(parseline.strings[parselineloop + 2]);
parselineloop := parselineloop + 3;
end;
if FBone[m].FBvhChanneltype = ChanneltypeRyzx then
begin
FBone[m].FRotateframe[FCurrentFrame — 1].time := FCurrentFrame;
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.y :=
StrToFloat(parseline.strings[parselineloop + 0]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.z :=
StrToFloat(parseline.strings[parselineloop + 1]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.x :=
StrToFloat(parseline.strings[parselineloop + 2]);
parselineloop := parselineloop + 3;
end;
if FBone[m].FBvhChanneltype = ChanneltypeRzyx then
begin
FBone[m].FRotateframe[FCurrentFrame — 1].time := CurrentFrame;
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.z :=
StrToFloat(parseline.strings[parselineloop + 0]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.y :=
StrToFloat(parseline.strings[parselineloop + 1]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.x :=
StrToFloat(parseline.strings[parselineloop + 2]);
parselineloop := parselineloop + 3;
end;
if FBone[m].FBvhChanneltype = ChanneltypeRyxz then
begin
FBone[m].FRotateframe[FCurrentFrame — 1].time := FCurrentFrame;
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.y :=
StrToFloat(parseline.strings[parselineloop + 0]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.x :=
StrToFloat(parseline.strings[parselineloop + 1]);
FBone[m].FRotateframe[FCurrentFrame — 1].bvh_value.z :=
StrToFloat(parseline.strings[parselineloop + 2]);
parselineloop := parselineloop + 3;
end;
FBone[m].FRotateframe[FCurrentFrame — 1].Value.x :=
degtorad(FBone[m]. | |
|
Gedeon |
Отправлено: 09.08.2004, 11:52 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
Подключить к проекту pas файл и работать с ним.
|
|
Dima |
Отправлено: 09.08.2004, 12:07 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 61
|
OpenGL |
|
|