r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[Core] Discuss core issues

eFishAnt
14-Jan-2005
[149]
when Josh appears, we will scratch each others heads and see if we 
can determine a way to parse this...he has done some work like this 
for his NASA project...and he is working on some crazy computer science 
parsing algorithms...I think he has been chatting with Ladislav too 
long ... ;-)
Ladislav
14-Jan-2005
[150]
SMD2Header: make struct! [
   m_iMagicNum [int] ; Always IDP2 (844121161)
   m_iVersion  [int] ; 8
   m_iSkinWidthPx [int]  
   m_iSkinHeightPx [int] 
   m_iFrameSize [int]
   m_iNumSkins [int]
   m_iNumVertices  [int]
   m_iNumTexCoords [int]
   m_iNumTriangles [int]
   m_iNumGLCommands [int]
   m_iNumFrames [int]
   m_iOffsetSkins [int]
   m_iOffsetTexCoords [int]
   m_iOffsetTriangles [int]
   m_iOffsetFrames [int]
   m_iOffsetGlCommands [int]
   m_iFileSize [int]
] none
shadwolf
14-Jan-2005
[151x2]
oki if I can apport my own head to help finding the better solution 
to handle this just communicate it to me thrue skype or altme. Than 
we can give our reflexions solution to Carl in order for him to include 
it to core
thank you ladislave for single int variable that's easy (like header) 
but for file content it's ver hard and harder I think to attribute 
to a REBOL struct based pointer the content of the file
Ladislav
14-Jan-2005
[153]
SMD2Vert: make struct! [
    m_fVert1 [float]
    m_fVert2 [float]
    m_fVert3 [float]
    m_ucReserved [char]
] none
shadwolf
14-Jan-2005
[154x2]
struct SMD2Frame
{
float m_fScale[3];
float m_fTrans[3];
char m_caName[16];
SMD2Vert * m_pVerts;

//Cleans up after itself
SMD2Frame()
{
m_pVerts = 0;
}

 this hierarchical structure typical in C is very very very hard to 
 adapt easyly to REBOL or maby I'm to idiot to do it ...
>> a: make object! SMD2Header
** Script Error: Invalid argument: make struct! [
    m_iMagicNum [int]
    m_iVersion [int]
    m_iSkinWidthPx [int]
    m_iSkinHeightPx [int]
    m_iFrameSize [int]
    m_iNumSkins [int]
    m_iNumVertices [int]
    m_iNumTexCoords [int]
    m_iNumTriangles [int]
    m_iNumGLCommands [int]
    m_iNumFrames [int]
    m_iOffsetSkins [int]
    m_iOffsetTexCoords [int]
    m_iOffsetTriangles [int]
    m_iOffsetFrames [int]
    m_iOffsetGlCommands [int]
    m_iFileSize [int]
] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
Ladislav
14-Jan-2005
[156]
why do you want to make object? - it is a struct
shadwolf
14-Jan-2005
[157x5]
that's not that way it has to be done sorry I made a mistake. It's 
only a: SMD2Header

but in this case you can't have a declaration like SMD2Header *myheader; 
that is the common way to do it in C SMD2Header struct will became 
a type in C, In rebol you only make a pointer to the struct so with 
vectorials struct based array mofifying one data will modify all 
data in the array
example SMD2Vert struct is use to make an aray of vertex position 
for each frame int SMD2Frame struct SMD2Frame Struct is use as type 
to make an array of frames
so MD2 format encapsulate many  Frame as array and all those frames 
encapsulate many Vert that discribe for this frame each location 
of every point of my 3d Model
the we have the posibility to take a bunch of frame for example from 
0 to 10  to say that's  animation set correspond to run
animation
eFishAnt
14-Jan-2005
[162x3]
aha, you give me so many ideas for my editor...
it is sometimes too mind expanding to write code while chatting. 
 Sometimes I think I need a few more heads, and a couple more arms 
to type and click...maybe I should draw a new model of myself.
but I think I would use REBOL blocks rather than some silly C structs. 
 blocks are such flexible containers.
shadwolf
14-Jan-2005
[165]
in my 3D engine I will make a switch to change the animation that 
are into my model that supose for me to have all my 3D model to get 
the identical set of animation or to make animation switch that could 
be adapted to every 3D Model Type (that's why 3D engeneers not even 
more use this format and prefert bone animation based file format 
like MDL or MD3/MD5)
eFishAnt
14-Jan-2005
[166]
aha...a datatype-sensitive editor...see, I should close down the 
right side of my brain so the left side can type code easier.
shadwolf
14-Jan-2005
[167x11]
for example if I say walk is frame 0 10 for human but for aliens 
in my game I nead to have only frames 0 to 5 for the walk I need 
to make 2 animation list and 2 animation switches to handle human 
(main caracter of my game for example) and alien
If i have alien type 1 alien type 2 alien type 3 etc... and all of 
them with different set of animation it could be very heavy task 
to handle all of them using MD2 but that's not our purpose in fact 
 :)
data-type sensitive editor  but normally rebol is datatype unsensive 
 :)
so or we allways ue struct! to typify our variables (wich can't be 
reuse). In C if I make SDM2Header *a, *b; a content and b content 
(physical memory localtion) will not be the same
in rebol a: SMD2Header and b: SMD2Header will point to the same memory 
chunk ...
>> a: SMD2Header
>> b: SMD2Header
>> a/m_iMagicNum: 1234234
== 1234234
>> probe b/m_iMagicNum
1234234
== 1234234
>>
and that normal becaus in C to initialise data I will use a malloc 
call witch will attrubute to a and b on the same based type different 
memory location
in my example program that exploite the SMD2Header strucure we can 
see:
//-------------------------------------------------------------
//- Load
//- Loads an MD2 model from file
//-------------------------------------------------------------
bool CMd2::Load(const char * szFilename)
{
	unsigned char * ucpBuffer = 0;
	unsigned char * ucpPtr = 0;
	unsigned char * ucpTmpPtr = 0; 
	int iFileSize = 0;
	FILE * f;
	
	if(!(f = fopen(szFilename, "rb")))
	{
		APP->Log(COLOR_RED, "Could not open MD2 file %s", szFilename);
		return false;
	}

	//check file size and read it all into the buffer
	int iStart = ftell(f);
	fseek(f, 0, SEEK_END);
	int iEnd = ftell(f);
	fseek(f, 0, SEEK_SET);
	iFileSize = iEnd - iStart;

	//Allocate memory for whole file
	ucpBuffer = new unsigned char[iFileSize];
	ucpPtr = ucpBuffer;

	if(!ucpBuffer)
	{

  APP->Log(COLOR_RED, "Could not allocate memory for %s", szFilename);
		return false;
	}

	//Load file into buffer
	if(fread(ucpBuffer, 1, iFileSize, f) != (unsigned)iFileSize)
	{
		APP->Log(COLOR_RED, "Could not read from %s", szFilename);
		delete [] ucpBuffer;
		return false;
	}

	//close the file, we don't need it anymore
	fclose(f);

	//get the header
	memcpy(&m_Head, ucpPtr, sizeof(SMD2Header));

	//make sure it is a valid MD2 file before we get going
	if(m_Head.m_iMagicNum != 844121161 || m_Head.m_iVersion != 8)
	{
		APP->Log(COLOR_RED, "%s is not a valid MD2 file", szFilename);
		delete [] ucpBuffer;
		return false;
	}
	
	ucpTmpPtr = ucpPtr;
	ucpTmpPtr += m_Head.m_iOffsetFrames;

	//read the frames
	m_pFrames = new SMD2Frame[m_Head.m_iNumFrames];
	
	for(int i = 0; i < m_Head.m_iNumFrames; i++)
	{
		float fScale[3];
		float fTrans[3];
		m_pFrames[i].m_pVerts = new SMD2Vert[m_Head.m_iNumVertices];
		//expand the verices
		memcpy(fScale, ucpTmpPtr, 12);
		memcpy(fTrans, ucpTmpPtr + 12, 12);
		memcpy(m_pFrames[i].m_caName, ucpTmpPtr + 24, 16);
		ucpTmpPtr += 40;
		for(int j = 0; j < m_Head.m_iNumVertices; j++)
		{

   //swap y and z coords to convert to the proper orientation on screen

   m_pFrames[i].m_pVerts[j].m_fVert[0] = ucpTmpPtr[0] * fScale[0] + 
   fTrans[0];

   m_pFrames[i].m_pVerts[j].m_fVert[1] = ucpTmpPtr[2] * fScale[2] + 
   fTrans[2];

   m_pFrames[i].m_pVerts[j].m_fVert[2] = ucpTmpPtr[1] * fScale[1] + 
   fTrans[1];
			m_pFrames[i].m_pVerts[j].m_ucReserved = ucpTmpPtr[3];
			ucpTmpPtr += 4;
		}
		
	}

	//Read in the triangles
	ucpTmpPtr = ucpPtr;
	ucpTmpPtr += m_Head.m_iOffsetTriangles;
	m_pTriangles = new SMD2Tri[m_Head.m_iNumTriangles];
	memcpy(m_pTriangles, ucpTmpPtr, 12 * m_Head.m_iNumTriangles);

	//Read the U/V texture coords
	ucpTmpPtr = ucpPtr;
	ucpTmpPtr += m_Head.m_iOffsetTexCoords;
	m_pTexCoords = new SMD2TexCoord[m_Head.m_iNumTexCoords];
	
	short * sTexCoords = new short[m_Head.m_iNumTexCoords * 2];
	memcpy(sTexCoords, ucpTmpPtr, 4 * m_Head.m_iNumTexCoords);

	for(i = 0; i < m_Head.m_iNumTexCoords; i++)
	{

  m_pTexCoords[i].m_fTex[0] = (float)sTexCoords[2*i] / m_Head.m_iSkinWidthPx;

  m_pTexCoords[i].m_fTex[1] = (float)sTexCoords[2*i+1] / m_Head.m_iSkinHeightPx;
	}
	
	delete [] sTexCoords;

	//Read the skin filenames
	ucpTmpPtr = ucpPtr;
	ucpTmpPtr += m_Head.m_iOffsetSkins;
	m_pSkins = new SMD2Skin[m_Head.m_iNumSkins];
	
	//Load textures
	for(i = 0; i < m_Head.m_iNumSkins; i++)
	{
		memcpy(m_pSkins[i].m_caSkin, ucpTmpPtr, 64);
		//hack off the leading parts and just get the filename
		char * szEnd = strrchr(m_pSkins[i].m_caSkin, '/');
		
		if(szEnd)
		{
			szEnd++;
			strcpy(m_pSkins[i].m_caSkin, szEnd);
		}

		m_pSkins[i].m_Image.Load(m_pSkins[i].m_caSkin);
		ucpTmpPtr += 64;
	}
		
	delete [] ucpBuffer;
	return true;
}
countainer class :
class CMd2 : public CModel
{
public:

	//Set skin to one of the files specified in the md2 files itself
	void SetSkin(unsigned int uiSkin);
	//Set skin to a different image
	void SetSkin(CImage& skin);

	//Load the file
	bool Load(const char * szFilename);
	
	//Render file at the initial position
	void Render();
	//Render the file at a certain frame
	void Render(unsigned int uiFrame);


 //Animate the md2 model (start and end frames of 0 and 0 will loop 
 through the WHOLE model

 void Animate(float fSpeed = 30.0f, unsigned int uiStartFrame = 0, 
 unsigned int uiEndFrame = 0, bool bLoop = true);

	//constructors/destructo
	CMd2();
	CMd2(const char * szFile);
	~CMd2();

private:
	
	CTimer m_Timer;
	//file header information
	SMD2Header m_Head; 
	//Frame information
	SMD2Frame * m_pFrames;
	//Triangles
	SMD2Tri * m_pTriangles;
	//Texure coords
	SMD2TexCoord * m_pTexCoords;
	//Skin files
	SMD2Skin * m_pSkins;
	//Interpolated vertices
	SMD2Vert * m_pVerts;
	//Current skin
	unsigned int m_uiSkin;
	//Using a custom skin?
	bool m_bIsCustomSkin;
	//The custom skin
	CImage * m_pCustSkin;

};
eFishAnt
14-Jan-2005
[178]
you go too fast for me...;-)  I have to find some time this weekend 
to play with the first toys...
shadwolf
14-Jan-2005
[179x2]
so you make a SDM2Header *m_Header; to declare your header type from 
structure SMD3Header, then you read the correct emont of data in 
the file  storing it to ucpPtr then you init m_Header it using  memcpy(&m_Head, 
ucpPtr, sizeof(SMD2Header));
if you want to load 3 MD2 files you need only to make other main 
pointer to the information you retrieve from the file
Ladislav
14-Jan-2005
[181]
Shadwolf: "in rebol a: SMD2Header and b: SMD2Header will point to 
the same memory chunk ..."


yes, but you should do it as follows: a: make struct! SMD2Header 
b: make struct! SMD2Header
shadwolf
14-Jan-2005
[182x4]
in rebol you will need to load 3 files to declare SDM2Header_f1 SMD2Header_f3 
and SMD2Header_f3 with for both the stricly identical content tso 
your recoding 3 times or X times the same thing ...
I'm not an expert on struct! far of that (wel in C yes but in REBOL 
no and I think it's because I'm not using load/library capability 
until now) but that's a good discution to point to difficulties on 
this kind of task and I hope help rebol Core to have a bettre handling 
of that
ladyslav on declaration statement REBOL need me to give him the datas 
I ust tryed what you just propose:
>> a: make struct! SMD2Header
** Script Error: Invalid argument: (missing value)
** Near: a: make struct! SMD2Header
Ladislav
14-Jan-2005
[186x2]
a: make struct! SMD2Header none ; or [some values here]
if you supply none, you generate an "empty" struct
Cyphre
14-Jan-2005
[188]
shadwolf: have you read this? http://www.rebol.com/docs/library.html
shadwolf
14-Jan-2005
[189]
yes so I had to read the file first then make my variable content 
basing me on a precut of the rode datas from file to be allowed to 
fill my variable content on inititialisation
Ladislav
14-Jan-2005
[190]
you can create an empty struct using NONE and fill it using the read 
data
shadwolf
14-Jan-2005
[191x2]
yes I read it cyphre long time ago when it was recently published 
but one thing that's apear to me dangerous is for example use:
a-struct: make struct! [
        in-string [string!] "Input string"
        in-int [integer!] "Input integer"
    ] ["This is input" 42]
Cyphre
14-Jan-2005
[193]
what is dangerous on that?
shadwolf
14-Jan-2005
[194x4]
while in C my struct is struct a-struct { char in-string[25]; int 
in-int; }
how can I be certain using string! unlimited REBOL countainer to 
correctly feet with the char 25 strictly sized contained in C
no contained but countainer
the dangerous thing is that with rebal I can over pass easly the 
25 limitation and write every where in the countigous memeryy area 
;)
Cyphre
14-Jan-2005
[198]
If I understand you well you have tu create string! of length 25 
in rebol for your purpose.