![]() |
|
|
|
#1 (permalink) |
|
unit Model;
interface uses OpenGL, Matrix, Windows, Textures, SysUtils; const MS_MAX_NAME = 32; MS_MAX_PATH = 256; type clsVec = class public x,y,z : single; w : single; u,v : single; bone : integer; procedure transform( m : clsMatrix ); procedure transform3( m : clsMatrix ); end; type pclsVec = ^clsVec; type clsTri = class public v : array [0..2] of integer; n : array [0..2] of integer; end; type pclsTri = ^clsTri; type clsNormal = class public x,y,z : single; end; type pclsNormal = ^clsNormal; type clsShape = class public num_vertices : integer; vertices : array of clsVec; num_triangles : integer; triangles : array of clsTri; num_normals : integer; normals : array of clsNormal; constructor create(); function loadFromFile( filename : string ) : boolean; function loadFromMs3dAsciiSegment(var ifile : TextFile) : boolean; function saveToFile( filename : string ) : boolean; procedure render(); end; type pclsShape = ^clsShape; type clsMaterial = class public constructor create(); function loadFromMs3dAsciiSegment(var ifile : TextFile ) : boolean; procedure activate(); procedure reloadTexture(); private Name : string; Ambient : array [0..3] of single; Diffuse : array [0..3] of single; Specular : array [0..3] of single; Emissive : array [0..3] of single; Shininess : single; Transparency : single; DiffuseTexture : string; AlphaTexture : string; textexture : GLuint; end; type pclsMaterial = ^clsMaterial; type clsKeyFrame = class public Time : single; Value : array [0..2] of single; end; type pclsKeyFrame = ^clsKeyFrame; type clsBone = class public Name : string; ParentName : string; Parent : ^clsBone; startPosition : array [0..2] of single; startRotation : array [0..2] of single; m_relative : clsMatrix; m_final : clsMatrix; NumPositionKeys : integer; PositionKeyFrames : array of clsKeyFrame; NumRotationKeys : integer; RotationKeyFrames : array of clsKeyFrame; constructor create(); function loadFromMs3dAsciiSegment(var ifile : TextFile ) : boolean; procedure render(); procedure fixup(); procedure advanceTo( CurrentTime : single ); procedure initialize(); end; type pclsBone = ^clsBone; type clsModel = class public MaxTime : single; CurrentTime : single; num_shapes : integer; shapes : array of clsShape; material_indices : array of integer; num_materials : integer; materials : array of clsMaterial; num_bones : integer; bones : array of clsBone; constructor create(); function loadFromMs3dAsciiFile( filename : string ) : boolean; procedure reloadTextures(); procedure render(); procedure renderBones(); function linkBones() : boolean; procedure initializeBones(); procedure advanceAnimation( deltaTime : single ); procedure attachSkin(); end; implementation procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external opengl32; procedure clsVec.transform(m: clsMatrix); var matrix : array [0..15] of single; vector : array [0..3] of single; begin m.getMatrix(matrix); vector[0] := x*matrix[0]+y*matrix[4]+z*matrix[8]+matrix[12]; vector[1] := x*matrix[1]+y*matrix[5]+z*matrix[9]+matrix[13]; vector[2] := x*matrix[2]+y*matrix[6]+z*matrix[10]+matrix[14]; vector[3] := x*matrix[3]+y*matrix[7]+z*matrix[11]+matrix[15]; x := vector[0]; y := vector[1]; z := vector[2]; w := vector[3]; end; procedure clsVec.transform3(m: clsMatrix); var matrix : array [0..15] of single; vec : array [0..2] of single; begin m.getMatrix(matrix); vec[0] := x*matrix[0]+y*matrix[4]+z*matrix[8]; vec[1] := x*matrix[1]+y*matrix[5]+z*matrix[9]; vec[2] := x*matrix[2]+y*matrix[6]+z*matrix[10]; x := vec[0]; y := vec[1]; z := vec[2]; end; constructor clsShape.create; begin num_vertices := 0; vertices := Nil; num_triangles := 0; triangles := Nil; num_normals := 0; normals := Nil; end; procedure clsShape.render; var i,j : integer; tri : clsTri; vec : clsVec; N : clsNormal; begin glBegin(GL_TRIANGLES); for i := 0 to num_triangles - 1 do begin tri := triangles[i]; for j := 0 to 2 do begin N := normals[tri.n[j]]; glNormal3f(N.x, N.y, N.z); vec := vertices[tri.v[j]]; glTexCoord2f (vec.u, vec.v); glVertex3f( vec.x, vec.y, vec.z ); end; end; glEnd(); end; function clsShape.saveToFile(filename: string): boolean; begin end; function clsShape.loadFromFile(filename: string): boolean; begin end; function clsShape.loadFromMs3dAsciiSegment(var ifile: TextFile): boolean; var nFlags, nIndex, j : integer; begin Readln(ifile,num_vertices); if eof(ifile) then begin result := false; exit; end; SetLength(vertices,num_vertices); if (num_vertices > 0)then begin for j := 0 to num_vertices - 1 do begin vertices[j] := clsVec.Create; Readln(ifile,nFlags,vertices[j].x, vertices[j].y, vertices[j].z,vertices[j].u, vertices[j].v,vertices[j].bone); if eof(ifile) then begin result := false; exit; end; vertices[j].v := 1.0 - vertices[j].v; end; end; Readln(ifile,num_normals); if eof(ifile) then begin result := false; exit; end; SetLength(normals,num_normals); if num_normals > 0 then begin for j := 0 to num_normals - 1 do begin normals[j] := clsNormal.Create; Readln(ifile,normals[j].x, normals[j].y, normals[j].z); if eof(ifile) then begin result := false; exit; end; end; end; Readln(ifile,num_triangles); if eof(ifile) then begin result := false; exit; end; SetLength (triangles,num_triangles); for j := 0 to num_triangles - 1 do begin triangles[j] := clsTri.Create; ReadLn(ifile,nFlags,triangles[j].v[0], triangles[j].v[1], triangles[j].v[2],triangles[j].n[0], triangles[j].n[1], triangles[j].n[2],nIndex); if eof(ifile) then begin result := false; exit; end; assert(triangles[j].v[0] >= 0); assert(triangles[j].v[0] < num_vertices); assert(triangles[j].v[1] >= 0); assert(triangles[j].v[1] < num_vertices); assert(triangles[j].v[2] >= 0); assert(triangles[j].v[2] < num_vertices); end; result := true; end; procedure clsMaterial.activate; begin glMaterialfv( GL_FRONT, GL_AMBIENT, @Ambient ); glMaterialfv( GL_FRONT, GL_DIFFUSE, @Diffuse ); glMaterialfv( GL_FRONT, GL_SPECULAR, @Specular ); glMaterialfv( GL_FRONT, GL_EMISSION, @Emissive ); glMaterialf( GL_FRONT, GL_SHININESS, Shininess ); if ( textexture > 0 ) then begin glBindTexture( GL_TEXTURE_2D, textexture ); glEnable( GL_TEXTURE_2D ); end else glDisable( GL_TEXTURE_2D ); end; constructor clsMaterial.create; begin end; function clsMaterial.loadFromMs3dAsciiSegment(var ifile: TextFile): boolean; var szLine : string; begin if (eof(ifile)) then begin result := false; exit; end; Readln(ifile,szLine); Name := StringReplace(szLine,'"','',[rfReplaceAll]); if (eof(ifile)) then begin result := false; exit; end; Readln(ifile,Ambient[0], Ambient[1], Ambient[2], Ambient[3]); if (eof(ifile)) then begin result := false; exit; end; Readln(ifile,Diffuse[0], Diffuse[1], Diffuse[2], Diffuse[3]); if (eof(ifile)) then begin result := false; exit; end; Readln(ifile,Specular[0], Specular[1], Specular[2], Specular[3]); if (eof(ifile)) then begin result := false; exit; end; Readln(ifile,Emissive[0], Emissive[1], Emissive[2], Emissive[3]); if (eof(ifile)) then begin result := false; exit; end; Readln(ifile,Shininess); if (eof(ifile)) then begin result := false; exit; end; Readln(ifile,Transparency); if (eof(ifile)) then begin result := false; exit; end; DiffuseTexture := ''; Readln(ifile,DiffuseTexture); DiffuseTexture := StringReplace(DiffuseTexture,'"','',[rfReplaceAll]); if (eof(ifile)) then begin result := false; exit; end; AlphaTexture := ''; Readln(ifile,AlphaTexture); AlphaTexture := StringReplace(AlphaTexture,'"','',[rfReplaceAll]); reloadTexture(); result := true; end; procedure clsMaterial.reloadTexture; begin if( length(DiffuseTexture) > 0 ) then LoadTexture(DiffuseTexture, textexture,false,GL_LINEAR,GL_LINEAR_MIPMAP_NEARES T,0) else textexture := 0; end; constructor clsBone.create; begin m_relative := clsMatrix.create; m_final := clsMatrix.create; end; procedure clsBone.advanceTo(CurrentTime: single); 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; begin i := 0; while ( (i < NumPositionKeys-1) and (PositionKeyFrames[i].Time < CurrentTime) ) do i := i + 1; assert(i < NumPositionKeys); if( i > 0 ) then begin deltaTime := PositionKeyFrames[i].Time - PositionKeyFrames[i-1].Time; assert( deltaTime > 0 ); fraction := (CurrentTime - PositionKeyFrames[i-1].Time) / deltaTime; assert( fraction > 0 ); assert( fraction < 1.0 ); Position[0] := PositionKeyFrames[i-1].Value[0] + fraction * (PositionKeyFrames[i].Value[0] - PositionKeyFrames[i-1].Value[0]); Position[1] := PositionKeyFrames[i-1].Value[1] + fraction * (PositionKeyFrames[i].Value[1] - PositionKeyFrames[i-1].Value[1]); Position[2] := PositionKeyFrames[i-1].Value[2] + fraction * (PositionKeyFrames[i].Value[2] - PositionKeyFrames[i-1].Value[2]); end else begin Position[0] := PositionKeyFrames[i].Value[0]; Position[1] := PositionKeyFrames[i].Value[1]; Position[2] := PositionKeyFrames[i].Value[2]; end; i := 0; while( (i < NumRotationKeys-1) and (RotationKeyFrames[i].Time < CurrentTime) ) do i := i + 1; assert(i < NumRotationKeys); if( i > 0 ) then begin deltaTime := RotationKeyFrames[i].Time - RotationKeyFrames[i-1].Time; assert( deltaTime > 0 ); fraction := (CurrentTime - RotationKeyFrames[i-1].Time) / deltaTime; assert( fraction > 0 ); assert( fraction < 1.0 ); Rotation[0] := RotationKeyFrames[i-1].Value[0] + fraction * (RotationKeyFrames[i].Value[0] - RotationKeyFrames[i-1].Value[0]); Rotation[1] := RotationKeyFrames[i-1].Value[1] + fraction * (RotationKeyFrames[i].Value[1] - RotationKeyFrames[i-1].Value[1]); Rotation[2] := RotationKeyFrames[i-1].Value[2] + fraction * (RotationKeyFrames[i].Value[2] - RotationKeyFrames[i-1].Value[2]); end else begin Rotation[0] := RotationKeyFrames[i].Value[0]; Rotation[1] := RotationKeyFrames[i].Value[1]; Rotation[2] := RotationKeyFrames[i].Value[2]; end; m_rel := clsMatrix.create; m_frame := clsMatrix.create; m_rel.setRotationRadians( startRotation ); m_rel.setTranslation( startPosition ); m_frame.setRotationRadians( Rotation ); m_frame.setTranslation( Position ); m_rel.postMultiply( m_frame ); if ( Parent = nil ) then begin m_rel.getMatrix(tempm); m_final.setMatrixValues(tempm); end else begin Parent.m_final.getMatrix(tempm); m_final.setMatrixValues(tempm); m_final.postMultiply( m_rel ); end; end; procedure clsBone.fixup; begin end; procedure clsBone.initialize; var m_rel : clsMatrix; tempm : array [0..15] of single; begin m_rel := clsMatrix.create; m_rel.setRotationRadians( startRotation ); m_rel.setTranslation( startPosition ); if ( Parent = nil ) then begin m_rel.getMatrix(tempm); m_final.setMatrixValues(tempm); end else begin Parent.m_final.getMatrix(tempm); m_final.setMatrixValues(tempm); m_final.postMultiply( m_rel ); end; end; procedure clsBone.render; var vector , parentvector : clsVec; begin vector := clsVec.Create; parentvector := clsVec.Create; vector.x := 0; vector.y := 0; vector.z := 0; vector.w := 1; vector.transform( m_final ); if( Parent <> nil ) then begin parentvector.x := 0; parentvector.y := 0; parentvector.z := 0; parentvector.w := 1; parentvector.transform( Parent.m_final ); end; glDisable( GL_TEXTURE_2D ); glLineWidth(1.0); glColor3f(1.0, 0, 0); glBegin(GL_LINES); glVertex3f( vector.x, vector.y, vector.z ); if( Parent <> nil ) then glVertex3f( parentvector.x, parentvector.y, parentvector.z ) else glVertex3f( vector.x, vector.y, vector.z ); glEnd(); glPointSize(2.0); glColor3f(1.0, 0, 1.0); glBegin(GL_POINTS); glVertex3f( vector.x, vector.y, vector.z ); if( Parent <> nil ) then glVertex3f( parentvector.x, parentvector.y, parentvector.z ); glEnd(); glColor3f(1.0, 1.0, 1.0); end; function clsBone.loadFromMs3dAsciiSegment(var ifile: TextFile): boolean; var szLine : string; j ,nFlags : integer; begin if (eof(ifile)) then begin result := false; exit; end; Readln(ifile,Name); Name := StringReplace(Name,'"','',[rfReplaceAll]) ; if (eof(ifile)) then begin result := false; exit; end; ParentName := ''; Readln(ifile,ParentName); ParentName := StringReplace(ParentName,'"','',[rfReplaceAll]) ; if (eof(ifile)) then begin result := false; exit; end; ReadLn(ifile,nFlags, startPosition[0], startPosition[1], startPosition[2], startRotation[0], startRotation[1], startRotation[2]); if (eof(ifile)) then begin result := false; exit; end; Readln(ifile,NumPositionKeys); SetLength(PositionKeyFrames,NumPositionKeys); for j := 0 to NumPositionKeys - 1 do begin PositionKeyFrames[j] := clsKeyFrame.Create; if (eof(ifile)) then begin result := false; exit; end; Readln(ifile , PositionKeyFrames[j].Time, PositionKeyFrames[j].Value[0], PositionKeyFrames[j].Value[1], PositionKeyFrames[j].Value[2] ); end; if (eof(ifile)) then begin result := false; exit; end; Readln(ifile,NumRotationKeys); SetLength(RotationKeyFrames,NumRotationKeys); for j := 0 to NumRotationKeys -1 do begin RotationKeyFrames[j] := clsKeyFrame.Create; if (eof(ifile)) then begin result := false; exit; end; Readln(ifile , RotationKeyFrames[j].Time, RotationKeyFrames[j].Value[0], RotationKeyFrames[j].Value[1], RotationKeyFrames[j].Value[2] ); end; result := true; end; procedure clsModel.advanceAnimation(deltaTime: single); var i : integer; begin CurrentTime := CurrentTime + deltaTime; if( CurrentTime > MaxTime ) then CurrentTime := 1.0; for i := 0 to num_bones -1 do bones[i].advanceTo( CurrentTime ); end; procedure clsModel.attachSkin; var i, j : integer; bone : integer; matrix : clsMatrix; v : array [0..2] of single; begin for i := 0 to num_shapes - 1 do begin for j := 0 to shapes[i].num_vertices - 1 do begin bone := shapes[i].vertices[j].bone; if( bone <> -1 ) then begin matrix := bones[bone].m_final; v[0] := shapes[i].vertices[j].x; v[1] := shapes[i].vertices[j].y; v[2] := shapes[i].vertices[j].z; matrix.inverseTranslateVect( v ); matrix.inverseRotateVect( v ); shapes[i].vertices[j].x := v[0]; shapes[i].vertices[j].y := v[1]; shapes[i].vertices[j].z := v[2]; end; end; end; end; constructor clsModel.create; begin num_shapes := 0; shapes := nil; num_materials := 0; materials := nil; end; procedure clsModel.initializeBones; var i : integer; begin for i := 0 to num_bones-1 do bones[i].initialize; end; function clsModel.linkBones: boolean; var i, j : integer; begin for i := 0 to num_bones-1 do begin bones[i].Parent := nil; if( length(bones[i].ParentName) > 0 ) then begin for j := 0 to num_bones -1 do begin if( bones[j].Name = bones[i].ParentName) then begin bones[i].Parent := @bones[j]; break; end; end; if ( bones[i].Parent = nil) then begin result := false; exit; end; end; end; result := true; end; function clsModel.loadFromMs3dAsciiFile(filename: string): boolean; var StartTime : single; bError : bool; szLine , szName , strTemp : string; nFrame, nFlags, nIndex, i : integer; fModel : TextFile; begin bError := false; AssignFile(fModel,filename); Reset(fModel); CurrentTime := 0; while ((not eof(fModel)) and (not bError)) do begin Readln(fmodel,szLine); if ( copy(szLine,0,2) = '//') then continue; if szLine = '' then continue; if (pos('Frames:',szLine) = 1) then begin nFrame := StrToInt(copy(szLine,8,length(szLine))); MaxTime := 1.0 * nFrame; continue; end; if (pos('Frame:',szLine) = 1) then begin nFrame := StrToInt(copy(szLine,7,length(szLine))); StartTime := 1.0 * nFrame; continue; end; if (pos('Meshes: ',szLine) = 1) then begin num_shapes := StrToInt(StringReplace(szLine,'Meshes: ','',[rfReplaceAll])); SetLength(shapes,num_shapes); SetLength(material_indices, num_shapes); for i := 0 to num_shapes - 1 do begin shapes[i] := clsShape.create; material_indices[num_shapes-1] := 0; end; for i := 0 to num_shapes - 1 do begin Readln(fmodel,szName); if (eof(fmodel)) then begin bError := true; break; end; szName := StringReplace(szName,'"','',[rfReplaceAll]); strTemp := szName; strTemp := copy(strTemp,pos(' ',strTemp)+1,length(strTemp)); nFlags := StrToInt(copy(strTemp,0,pos(' ',strTemp)-1)); nIndex := StrToInt(copy(strTemp,pos(' ',strTemp)+1,length(strTemp))); material_indices[i] := nIndex; if( not shapes[i].loadFromMs3dAsciiSegment(fModel) ) then begin bError := true; break; end; end; continue; end; if (pos('Materials: ',szLine) = 1) then begin num_materials := StrToInt(StringReplace(szLine,'Materials: ','',[rfReplaceAll])); SetLength(materials,num_materials); for i := 0 to num_materials -1 do materials[i] := clsMaterial.create; for i := 0 to num_materials -1 do begin if( not materials[i].loadFromMs3dAsciiSegment(fModel) ) then begin bError := true; break; end; end; continue; end; if (pos('Bones: ',szLine) = 1) then begin num_bones := StrToInt(StringReplace(szLine,'Bones: ','',[rfReplaceAll])); SetLength(bones,num_bones); for i := 0 to num_bones -1 do bones[i] := clsBone.create; for i := 0 to num_bones -1 do begin if( not bones[i].loadFromMs3dAsciiSegment(fModel) ) then begin bError := true; break; end; end; continue; end; end; CloseFile(fModel); if( not linkBones() ) then begin result := false; exit; end; initializeBones(); attachSkin(); advanceAnimation( StartTime ); result := true; end; procedure clsModel.reloadTextures; var i : integer; begin for i := 0 to num_materials - 1 do // for each shape materials[i].reloadTexture(); end; procedure clsModel.render; var k,i,j,materialIndex : integer; tri : clsTri; N : clsNormal; vec : clsVec; bone : clsBone; v : array [0..2] of single; matrix : clsMatrix; begin for k := 0 to num_shapes - 1 do begin materialIndex := material_indices[k]; if ( materialIndex >= 0 ) then materials[materialIndex].activate() else begin // Material properties? glDisable( GL_TEXTURE_2D ); end; glBegin(GL_TRIANGLES); for i := 0 to shapes[k].num_triangles - 1 do begin tri := shapes[k].triangles[i]; for j := 0 to 2 do begin N := shapes[k].normals[tri.n[j]]; glNormal3f(N.x, N.y, N.z); vec := shapes[k].vertices[tri.v[j]]; glTexCoord2f (vec.u, vec.v); if( vec.bone = -1 ) then begin glVertex3f( vec.x, vec.y, vec.z ); end else begin bone := bones[vec.bone]; matrix := bone.m_final; v[0] := vec.x; v[1] := vec.y; v[2] := vec.z; matrix.rotateVect( v ); matrix.translateVect( v ); glVertex3fv( @v ); end; end; end; glEnd(); end; end; procedure clsModel.renderBones; var i : integer; begin for i := 0 to num_bones - 1 do bones[i].render(); end; end. Çemberinden geçirirken felek,bizim kulağımıza fısıldamıştır senin kaderin bu diye Sağol Felek Çayın Ziyade Olsun |
|
|
|
|
![]() |
| Şu an bu konuyu görüntüleyen kullanıcı sayısı: 1 (0 üye ve 1 misafir) | |
| Konu Araçları | |
| Görünüm Modları | |
|
|