After googling I found information about 3ds format and proved that it is so simple.
// OGLObject.h
#pragma once
#define MAX_VERTEXES 80000
#define MAX_POLYGONS 80000
#define MAX_NAME_SIZE 20
typedef struct VertextTypeStruct {
float x;
float y;
float z;
} VertexType;
typedef struct PolygonTypeStruct {
int a;
int b;
int c;
} PolygonType;
typedef struct MapCoordinatesStruct {
float u;
float v;
} MapCoordinates;
//
// Create for one 3ds file
//
class OGLObject
{
public:
OGLObject();
~OGLObject();
char * name() const;
int id() const;
VertexType * vertexes( ) const;
PolygonType * polygons( ) const;
public:
int load3DS( char * filename );
int loadTexture( char * filename );
private:
char * m_name;
int m_countOfVertex;
int m_countOfPolygons;
VertexType * m_vertexes;
PolygonType * m_polygons;
MapCoordinates * m_mapCoordinates;
int m_idTexture;
};
// OGLObject.cpp
int OGLObject::load3DS(char *filename)
{
int i;
FILE * l_file = fopen( filename, "rb" );
if (l_file == NULL)
{
return 0;
} // File could't be found
unsigned short l_chunkId;
unsigned int l_chunkLength;
unsigned char l_char;
unsigned short l_quantity;
unsigned short l_faceFlags;
while( ftell( l_file ) < filelength( fileno( l_file ) ) )
{
fread( &l_chunkId, 2, 1, l_file );
fread( &l_chunkLength, 4, 1, l_file );
switch( l_chunkId )
{
case 0x4d4d: // MAIN CHUNK
break;
case 0x3d3d: // 3D EDITOR CHUNK
break;
case 0x4000: // OBJECT BLOCK
// Parse name of object
i = 0;
do
{
fread( &l_char, 1, 1, l_file );
m_name[i] = l_char;
i++;
} while (l_char != '\0' && i < 20);
break;
case 0x4100: // EMPTY chunk
break;
case 0x4110: // VERTICES LIST
fread( &l_quantity, sizeof( unsigned short ), 1, l_file );
m_countOfVertex = l_quantity;
for(i = 0; i < l_quantity; i++)
{
fread( &m_vertexes[i].x, sizeof( float ), 1, l_file );
fread( &m_vertexes[i].y, sizeof( float ), 1, l_file );
fread( &m_vertexes[i].z, sizeof( float ), 1, l_file );
}
break;
case 0x4120:
fread( &l_quantity, sizeof( unsigned short ), 1, l_file );
m_countOfPolygons = l_quantity;
for(i = 0; i < l_quantity; i++)
{
fread( &m_polygons[i].a, sizeof( unsigned short ), 1, l_file );
fread( &m_polygons[i].b, sizeof( unsigned short ), 1, l_file );
fread( &m_polygons[i].c, sizeof( unsigned short ), 1, l_file );
fread( &l_faceFlags, sizeof( float ), 1, l_file );
}
break;
case 0x4140:
fread ( &l_quantity, sizeof (unsigned short), 1, l_file);
for (i = 0; i < l_quantity; i++)
{
fread (&m_mapCoordinates[i].u, sizeof (float), 1, l_file);
fread (&m_mapCoordinates[i].v, sizeof (float), 1, l_file);
}
break;
default:
fseek( l_file, l_chunkLength - 6, SEEK_CUR );
}
}
fclose( l_file );
return 1;
}
четверг, 22 мая 2008 г.
3ds
Today I will start to write tool for rendering 3ds model using OpenGL(glut library) to the screen. But I have some questions that's requring to google)
Format diskette
Not so long ago I have to write program for formating diskette without using BIOS interrupt. How do you see in the near future is not so simple it was do)
Source:))
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
#include
#include
#include
#include
#define SEC_SIZE 2
typedef struct _DPT_
{
unsigned char srt_hut;
unsigned char dma_hlt;
unsigned char motor_w;
unsigned char sec_size;
unsigned char eot;
unsigned char gap_rw;
unsigned char dtl;
unsigned char gap_f;
unsigned char fill_char;
unsigned char hst;
unsigned char mot_start;
} DPT;
DPT far *get_dpt (void);
void fdc_out (unsigned char byte);
int fdc_inp (void);
void int_wait (void);
void dma_init (void far *);
void tdelay (int cnt);
void interrupt IRQ6 (__CPPARGS);
void interrupt (*oldIRQ6) (__CPPARGS);
char buffer[512];
static int IRQ=0;
void main (void)
{
unsigned iter, side = 0, sector = 0, track = 0;
unsigned old_sec_size, old_fill_char, old_eot;
unsigned char fill_char;
int i, j;
long l;
char status[7], main_status;
DPT _far *fdpt;
FILE * config;
oldIRQ6 = _dos_getvect (8+6);
_dos_setvect (8+6, IRQ6);
// We're opening a file in order to store in it
// the very first sector of the diskette
config = fopen ("flopic.cfg", "r");
fscanf(config, "%d", &track);
fscanf(config, "%c", &fill_char); // read one space
fscanf(config, "%c", &fill_char);
fclose(config);
// Getting Diskette Parameter Table pointer
fdpt = get_dpt();
old_sec_size = fdpt->sec_size;
old_fill_char = fdpt->fill_char;
old_eot = fdpt->eot;
fdpt->sec_size = SEC_SIZE;
fdpt->fill_char = 0xf8; // default byte for filling TODO: set to your sym
fdpt->eot = 15;
// Turning on the motor in the "A:" drive
// Enabling interrupts before actual turning on
_enable();
outp (0x3F2, 0x1C);
// Waiting while motor speeds up
tdelay (18);
// Displaying contents of the controller state register
printf ("Motor is on.\t\t");
printf ("State: %02.2X\n", inp(0x3F4));
// recalibrate
fdc_out (7);
fdc_out (0);
int_wait();
// We need to move drive head to the CYL track
// "Seek" command
fdc_out (0xf);
// The "Seek" command needs 2 parameters:
// a Head/Drive number and a Track number.
// Since we're working with "A:" drive and 0 head,
// first parameter is 0, second parameter is CYL
fdc_out (0);
fdc_out (track);
// Displaying contents of the controller state register
printf ("\n<<>> \t\t");
printf ("State: %02.2X\n", inp(0x3F4));
// Interrupt notifies us about operation end
int_wait();
// Delay for head positioning
tdelay (5);
// In order to check the result of the "Seek" command
// we're sending "Read Interrupt State" command
// Displaying ST0 register and number of a track after
// "Seek" command execution PCN
fdc_out (0x8);
printf ("Interrupt state:\t");
printf ("ST0: %02.2X, \t", fdc_inp());
printf ("PCN: %02.2X\n", fdc_inp());
// For more detailed info of FDC state
// we're sending "Read Media/Drive State" command,
// displaying ST3 register
fdc_out (4);
fdc_out (0);
printf ("Media/Drive state:\t ST3: %02.2X\n", fdc_inp());
// Setting speed of data transfer to 500 KB/sec
outp (0x3F7, 0);
// Setting buffer for DMA
for(iter = 1, i = 0; iter < 16; iter++, i += 4)
{
buffer[i] = track;
buffer[i + 1] = 0; // Side [0, 1]
buffer[i + 2] = iter; // Sector
buffer[i + 3] = 2; // SEC_SIZE - 512
}
// DMA initialization
dma_init ((void far *)buffer);
fdc_out(0x4d); // format CYL or track
// Sending some technical info to FDC.
// This info may be obtained form the Diskette Parameter Table.
// Parameters are:
// - sector size;
// - last sector on a track;
// - gap length;
// - number of bytes to be read/write
fdc_out (0); // format A:
fdc_out (fdpt->sec_size);
fdc_out (fdpt->eot);
fdc_out (fdpt->gap_rw);
fdc_out (fdpt->fill_char);
// Waiting for interrupt (end of operation)
int_wait();
fdpt->sec_size = old_sec_size;
fdpt->eot = old_eot;
fdpt->fill_char = old_fill_char;
outp (0x3F2, 0xC);
lll:
_dos_setvect (8+6, oldIRQ6);
}
// Writes a byte to FDC
void fdc_out (unsigned char parm)
{
asm mov dx,3F4h
loop_fdc_out:
asm in al,dx
asm test al,80h // Is controller ready?
asm jz loop_fdc_out // No, waiting...
asm inc dx
asm mov al, parm // Writing the byte
asm out dx, al
}
// Reads a byte from FDC
int fdc_inp (void)
{
asm mov dx,3F4h
loop_fdc_inp:
asm in al,dx
asm test al,80h // Is controller ready?
asm jz loop_fdc_inp // No, waiting...
asm inc dx
asm in al, dx // Reading a byte
return _AL;
}
// Waits for an interrupt generated by FDC
void int_wait (void) {
_enable();
while (IRQ==0) {};
IRQ = 0;
}
void interrupt IRQ6 (__CPPARGS) {
IRQ = 1;
outportb (0x20, 0x20);
}
// DMA initialization routine
void dma_init (void far *buf)
{
unsigned long f_adr;
unsigned sg, of;
// Computing 24-bit address for the data buffer
f_adr = ((unsigned long)FP_SEG(buf) << 4)
+ (unsigned long)FP_OFF(buf);
// Splitting the address into a page number
// and an offset
sg = (f_adr >> 16) & 0xff;
of = f_adr & 0xffff;
// Disabling ints during DMA programming
_disable();
asm mov al,4ah // FDC read data command
asm out 12,al // We're working with 16-bit ports.
// Next byte sent to 16-bit port is less significiant
asm out 11,al // DMA mode
asm mov ax,of // Buffer offset LSB
asm out 4,al
asm mov al,ah // Buffer offset MSB
asm out 4,al
asm mov ax,sg // Page number
asm out 81h,al
asm mov ax,511 // Data length
asm out 5,al
asm mov al,ah
asm out 5,al
asm mov al,2 // channel 2 enabled
asm out 10,al
// It's now safe to enable ints
_enable();
}
// This routine returns a Diskette Parameter Table address
DPT far *get_dpt(void)
{
void far * far *ptr;
ptr = (void far * far *)MK_FP(0x0, 0x78);
return (DPT far*)(*ptr);
}
// This routine waits for cnt timer ticks.
// Timer frequency is 18.2 Hz
void tdelay (int cnt)
{
asm push bx
asm push dx
asm push si
asm mov si, cnt
asm mov ah, 0
asm int 1ah
asm mov bx, dx
asm add bx, si
delay_loop:
asm int 1ah
asm cmp dx, bx
asm jne delay_loop
asm pop si
asm pop dx
asm pop bx
}
Before using the program, you have to create flopic.cfg file that's contain data("
Source:))
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
#include
#include
#include
#include
#define SEC_SIZE 2
typedef struct _DPT_
{
unsigned char srt_hut;
unsigned char dma_hlt;
unsigned char motor_w;
unsigned char sec_size;
unsigned char eot;
unsigned char gap_rw;
unsigned char dtl;
unsigned char gap_f;
unsigned char fill_char;
unsigned char hst;
unsigned char mot_start;
} DPT;
DPT far *get_dpt (void);
void fdc_out (unsigned char byte);
int fdc_inp (void);
void int_wait (void);
void dma_init (void far *);
void tdelay (int cnt);
void interrupt IRQ6 (__CPPARGS);
void interrupt (*oldIRQ6) (__CPPARGS);
char buffer[512];
static int IRQ=0;
void main (void)
{
unsigned iter, side = 0, sector = 0, track = 0;
unsigned old_sec_size, old_fill_char, old_eot;
unsigned char fill_char;
int i, j;
long l;
char status[7], main_status;
DPT _far *fdpt;
FILE * config;
oldIRQ6 = _dos_getvect (8+6);
_dos_setvect (8+6, IRQ6);
// We're opening a file in order to store in it
// the very first sector of the diskette
config = fopen ("flopic.cfg", "r");
fscanf(config, "%d", &track);
fscanf(config, "%c", &fill_char); // read one space
fscanf(config, "%c", &fill_char);
fclose(config);
// Getting Diskette Parameter Table pointer
fdpt = get_dpt();
old_sec_size = fdpt->sec_size;
old_fill_char = fdpt->fill_char;
old_eot = fdpt->eot;
fdpt->sec_size = SEC_SIZE;
fdpt->fill_char = 0xf8; // default byte for filling TODO: set to your sym
fdpt->eot = 15;
// Turning on the motor in the "A:" drive
// Enabling interrupts before actual turning on
_enable();
outp (0x3F2, 0x1C);
// Waiting while motor speeds up
tdelay (18);
// Displaying contents of the controller state register
printf ("Motor is on.\t\t");
printf ("State: %02.2X\n", inp(0x3F4));
// recalibrate
fdc_out (7);
fdc_out (0);
int_wait();
// We need to move drive head to the CYL track
// "Seek" command
fdc_out (0xf);
// The "Seek" command needs 2 parameters:
// a Head/Drive number and a Track number.
// Since we're working with "A:" drive and 0 head,
// first parameter is 0, second parameter is CYL
fdc_out (0);
fdc_out (track);
// Displaying contents of the controller state register
printf ("\n<<
printf ("State: %02.2X\n", inp(0x3F4));
// Interrupt notifies us about operation end
int_wait();
// Delay for head positioning
tdelay (5);
// In order to check the result of the "Seek" command
// we're sending "Read Interrupt State" command
// Displaying ST0 register and number of a track after
// "Seek" command execution PCN
fdc_out (0x8);
printf ("Interrupt state:\t");
printf ("ST0: %02.2X, \t", fdc_inp());
printf ("PCN: %02.2X\n", fdc_inp());
// For more detailed info of FDC state
// we're sending "Read Media/Drive State" command,
// displaying ST3 register
fdc_out (4);
fdc_out (0);
printf ("Media/Drive state:\t ST3: %02.2X\n", fdc_inp());
// Setting speed of data transfer to 500 KB/sec
outp (0x3F7, 0);
// Setting buffer for DMA
for(iter = 1, i = 0; iter < 16; iter++, i += 4)
{
buffer[i] = track;
buffer[i + 1] = 0; // Side [0, 1]
buffer[i + 2] = iter; // Sector
buffer[i + 3] = 2; // SEC_SIZE - 512
}
// DMA initialization
dma_init ((void far *)buffer);
fdc_out(0x4d); // format CYL or track
// Sending some technical info to FDC.
// This info may be obtained form the Diskette Parameter Table.
// Parameters are:
// - sector size;
// - last sector on a track;
// - gap length;
// - number of bytes to be read/write
fdc_out (0); // format A:
fdc_out (fdpt->sec_size);
fdc_out (fdpt->eot);
fdc_out (fdpt->gap_rw);
fdc_out (fdpt->fill_char);
// Waiting for interrupt (end of operation)
int_wait();
fdpt->sec_size = old_sec_size;
fdpt->eot = old_eot;
fdpt->fill_char = old_fill_char;
outp (0x3F2, 0xC);
lll:
_dos_setvect (8+6, oldIRQ6);
}
// Writes a byte to FDC
void fdc_out (unsigned char parm)
{
asm mov dx,3F4h
loop_fdc_out:
asm in al,dx
asm test al,80h // Is controller ready?
asm jz loop_fdc_out // No, waiting...
asm inc dx
asm mov al, parm // Writing the byte
asm out dx, al
}
// Reads a byte from FDC
int fdc_inp (void)
{
asm mov dx,3F4h
loop_fdc_inp:
asm in al,dx
asm test al,80h // Is controller ready?
asm jz loop_fdc_inp // No, waiting...
asm inc dx
asm in al, dx // Reading a byte
return _AL;
}
// Waits for an interrupt generated by FDC
void int_wait (void) {
_enable();
while (IRQ==0) {};
IRQ = 0;
}
void interrupt IRQ6 (__CPPARGS) {
IRQ = 1;
outportb (0x20, 0x20);
}
// DMA initialization routine
void dma_init (void far *buf)
{
unsigned long f_adr;
unsigned sg, of;
// Computing 24-bit address for the data buffer
f_adr = ((unsigned long)FP_SEG(buf) << 4)
+ (unsigned long)FP_OFF(buf);
// Splitting the address into a page number
// and an offset
sg = (f_adr >> 16) & 0xff;
of = f_adr & 0xffff;
// Disabling ints during DMA programming
_disable();
asm mov al,4ah // FDC read data command
asm out 12,al // We're working with 16-bit ports.
// Next byte sent to 16-bit port is less significiant
asm out 11,al // DMA mode
asm mov ax,of // Buffer offset LSB
asm out 4,al
asm mov al,ah // Buffer offset MSB
asm out 4,al
asm mov ax,sg // Page number
asm out 81h,al
asm mov ax,511 // Data length
asm out 5,al
asm mov al,ah
asm out 5,al
asm mov al,2 // channel 2 enabled
asm out 10,al
// It's now safe to enable ints
_enable();
}
// This routine returns a Diskette Parameter Table address
DPT far *get_dpt(void)
{
void far * far *ptr;
ptr = (void far * far *)MK_FP(0x0, 0x78);
return (DPT far*)(*ptr);
}
// This routine waits for cnt timer ticks.
// Timer frequency is 18.2 Hz
void tdelay (int cnt)
{
asm push bx
asm push dx
asm push si
asm mov si, cnt
asm mov ah, 0
asm int 1ah
asm mov bx, dx
asm add bx, si
delay_loop:
asm int 1ah
asm cmp dx, bx
asm jne delay_loop
asm pop si
asm pop dx
asm pop bx
}
Before using the program, you have to create flopic.cfg file that's contain data("
Подписаться на:
Комментарии (Atom)