3D OpenGL Engine

BlitzPlus Forums/BlitzPlus Programming/3D OpenGL Engine

JoshK(Posted 2003) [#1]
Collision is literally the only Blitz3D routine that I haven't duplicated in OpenGL code. I've got meshes, coordinate transformations, picking, different materials (with like 81 possible blend modes, not 3).

I'm not interested in duplicating Blitz3D in OpenGL. I am interested in an open-source, totally customizable 3D engine. I wouldn't suggest this if it meant a lot of work just to get a 3D engine working, but with all the code I have now, it wouldn't be a big deal, just a few days of work.

Is anyone interested, who has useful routines they are willing to implement? I am interested in things like math-based picking, file format loaders, and collision. All data would be stored in banks, so you could add functions via DLL's and access the memory directly. I use this system for CShop, and when the "Blitz is hacked" post came out, I noticed that Mark does almost the exact same thing.

If we have full control of the system, we don't have to wait around for Mark to add BSP's, vertex weights, or correct bump mapping. THe problem now is that Blitz3D doesn't let us access the low-level routines, so even if you compile a BSP tree, it's useless because you can't hide part of a mesh, and not merging the meshes makes the program even slower.


Skitchy(Posted 2003) [#2]
Are you talking about an OpenGL engine that you code from Blitz, or something that requires C++ / Delphi / [insert language] knowledge? If it's a Blitz thing I'd certainly pay for it. :)
As for stuff to add...hmm. Re. file format loaders - I'd reccommend starting with .x files for loading as they're bloody simple. I've got a static mesh saver function (Blitz3D code) that I did for LightBulb if you're interested. Also if you're interested in adding extended sound support (let's face it, the sound commands are a little limited at present) .wav is dead simple. I actually coded a click-remover for .wavs in DarkBasic(!) ages ago. Obviously, I'd want to get my hands on the engine in return ;)
If you're not interested no hard feelings, but like I said I'd definitely pay $$$ for such code.


JoshK(Posted 2003) [#3]
I didn't ask for money. If you're trying to make money, you do it by working on one good program, not by selling .bb code.

Do you know how to load .wav files that contain attack/loop/decay portions, or do you know how to apply environmental effects to sound without using bass.dll?


Skitchy(Posted 2003) [#4]
I'd imaging that the attack/loop/decay positions are just stored before the start or after the end of the actual sound data. You'd then have to manipulate the amplitude yourself by calculating the various points along the envelope and effectively turn up/down the volume in code (not difficult). No idea about environmental FX, but aren't they specific to SoundBlaster cards anyway? If so, there's probably a Creative .dll for switching them.

Sorry for offering you money. I don't entirely agree that there is no merit to selling code though (I've never done it myself). You're selling time and expertise which are very valuable. Plus, I certainly couldn't code an OpenGL engine ATM, so the only way I could get one is by buying it or getting it for free.
So, if this is to be freeware, will I be able to use it for commercial projects. I know you probably hate this question by now(!), but I only ask because I genuinely want to know - not to start a fight :)


JoshK(Posted 2003) [#5]
I seriously don't care what you do, if it does happen.


Pepsi(Posted 2003) [#6]
Actaully, this does sound intersting. Josh, are all your "OpenGL" based DLL's made in pure basic? If so, are you interested in having any/all of them converted to C/C++?

As for open source, will it go by GPL or LGPL? I like the idea of if any changes are made to the library itself then you must share the changes of the libray itself, not your whole program idea.

As for sound, check out OpenAL. It does a good job as far as I can tell from how the americasarmy.com FPS game uses it. It might be worthy of checking out.

As for as my library I'm doing, it's basically being programmed with the idea of becoming a "Nuclear Glory" game library for Blitz+ having some blitz like "entity" qualities. Anyways, I'm confident of working with OpenGL now even more so than with all the years I've toyed around with DirectX. Also, being able to work with C/C++ dlls, we dont really need any use of Banks as in to store graphics, 3d models, sounds, music, etc... With C/C++, vector arrays are a god send for easy control over various data and memory.

About the collision, I was going to approach it first by doing sphere-to-poly collision and then add in ellipsoid type method simply by multiplying or dividing the polys that are tested against the sphere. The group of polys that are to be tested would be scaled the same for the x,z plane (ie: ellipsiod width) and scaled along the y plane (ie: ellipsiod height) to give an ellipsiod effect. Ofcoarse, the sphere would be positioned correctly via the ellipsiod width and height scales when testing collision against polys. Basically, the world changes, not the sphere.

Or, I go about the fluid studios way or the varients derieved from it for collision. I'm just spouting ideas here. Doesn't mean I'm "wanting" to do it for this project as you seem to have interest in figuring it out for this project. Ofcoarse, I don't mind helping out with the idealogy behind it and/or doing it myself.

I'm interested in helping out somehow. I can get the dll code in C/C++ form as the Visual Studio 6 Enterprise compiler can optimize it for speed. I can also showcase what I have with my library if there is anything in there that might be of interest to include in this project. I really do want to see this open source project happen. Are you going to have a website for it or keep details here on the forums? I just don't know where to start or what to do to add to the project. I'll get what I have up asap at least for consideration to include anything from it.

Oh, also I use the devIL library for including images/textures. The idea behind that is to make it easier for me to include "Load Media From Memory" or "Load Media From Pack Files DIRECTLY" type of functions when I get around to it. That idea is something I would like to see this open source project include off the bat. Blitz seriously suffers from this directly.

If any ideas I have above sounds useful in anyway, I'll be glad to help out. I just would like to see more in detail whats needs to be done, what's are already done, who's doing what, all that good orginization stuff... before I seriously dive into it.


JoshK(Posted 2003) [#7]
It sounds like people are interested. This might be kind of cool, because we could do whatever we wanted, instead of sitting around bitching at Mark.

I think doing the GPL thing is a good idea, so if someone makes changes, it stays open-source.

Here is the primary question:

1. Do we want to store data in Blitz banks, or memory buffers allocated via a DLL?

Blitz Banks) If we store them in Blitz banks, we should probably write the whole thing in Blitz, because DLL's won't be able to create and destroy banks, just edit them. When you have structures and sub-structure in banks, you need to be able to free and create banks, and DLL's can't do this, I think.

Memory Buffers) This would allow us to create and destroy memory buffer allocations with DLL's. Two additional questions then arise:

I. What do we want to use to allocate memory? I don't like the way PureBasic allocates memory. Is there a way to write memory commands that will return a pointer? We could poke the memory buffer size to the first integer of the pointer. What I want is to be able to call a DLL and create, resize, and free memory buffers, but not do it with a stupid index variable like PB does.

II. How much of this should be written in DLL's? What is the advantage of using DLL's if the engine is open-source? A significant disadvantage is it's more difficult for testing and development. I usually end up writing the code in Blitz first, to make sure it works, and then converting it to PureBasic. Then when I find bugs, I end up rewriting it in Blitz after all.

You might check out this link about using a new kind of Blitz "structure". I came up with these after writing all my structures by hand in the CShop engine.


Pepsi(Posted 2003) [#8]
EDIT Big Time:

Can I see how you do a PureBasic memory allocation? I want to see what you mean about this index variable thing...

I've been sitting here thinking about how to do a "create, resize, and free memory buffers" in C. I'm thinking that Vector Arrays are truely the way to go here. I'll try to knock something up here soon. Also, I would imagine the dll memory management would be faster than poking around with banks. Ofcoarse, I'm just imagining that at the moment.

When it comes down to doing things like BSP's and collision testing, I would rather see it done in C then seeing it written in Blitz. Mabie it's just a case of seeing to believe it in blitz for me to see a good speed performance in operations like that. Ofcoarse here, if something like that gets written in Blitz code, then like I said in my first post, I'll be glad to convert it to C/C++ code to see if it would be worthy that way.

I remmember someone writting a direct blitz userlib for the devIL library. I would take that route for including images/textures or I can knock up a C/C++ dll to manage it better if needed be. I still hadn't checked out OpenAL fully yet as in I don't know if it's possible to write a direct userlib to the OpenAL dll(s). I just want to make sure that either which way it's decided to store data that we can grab data directly from memory or from a pack file for any media. I don't want to see the "write to disk, load it, delete it, and so on.." hack.

I'll go ahead and ponder more on the significants of using a dll for memory manipulation of data.

"How much of this should be written in DLL's?" - I would agree to " as less as possible ". As this project being written for blitz, userlibs are part of the game. Make use of them. Any Dll's that get included into the project should definetly get it's source code included along with it being in compiled form so anybody can use it.

Oh, I'll have a second look at your new blitz "structure" method also to see if I can work the memory dll with it. It's a shame blitz doesn't support C-Style structures, eh?


JoshK(Posted 2003) [#9]
As for the use of libs...

I am inclined to write the whole thing, or as much as possible, in Blitz code. Libs are much harder to test or alter. I usually end up moving my lib code back to Blitz, even with simple commands like RGB(), because I want to test or change something. I think there would be more creative freedom if everything were written in plain old Blitz code, with a few rules to the code. If we're going to write ANY of it in Blitz, we might as well write it all in Blitz, because we won't be able to use the engine with another programming language anyways.


Pepsi(Posted 2003) [#10]
Alright. I guess mabie I am jumping the gun with using dlls even though I can pretty much mimic all of the bank commands in a dll. Your "new structure way" thread somewhere discussed about using "*" with banks in the userlib function parameter. I keep forgetting about that. So I can try that route first for whatever.

Before the memory stuff, have you written blitz code for loading .bmp,.jpg,.tga,.png,.dds,etc... as textured for OpenGL primitives? I'm just curious how interested you are on having simple functions to load various gfx formats by using an external library.

Oh, and have you been able to use gluProject in blitz code? I gave up trying to make it work directly like that and had to go the dll route to write it in C to get it to work nicely. Also stuff like using gl_extensions and the faster methods of rendering using glDrawArrays with gl functions like glVertexPointer, glColorPointer, and glTexCoordPointer is better suited for Dll work. I guess dll suff like that can be an "option" for the open source project use.


JoshK(Posted 2003) [#11]
I can convert any Blitz image to a GLTexture. FreeImage can load and save something like 30 image file formats. Or we could just stick to the BlitzPlus bitmap and JPEG loaders, and a TGA loader I wrote in BLitz code. Are there any other texture formats we should think about?

If you can think of a reason to use DLL's in place of Blitz code, let's hear it. What routines are better as DLL's? Is there any reason we should be looking at that instead?

How do DrawArrays work? I use GLLists, and they are pretty fast.

If you can replace all the Blitz bank commands with a DLL, I am interested in using those instead. The "*" in userlibs tells Blitz to pass the lib the bank pointer I was talking about. If you use a "%" instead, the 12-byte bank handle gets passed.

gluPerspective uses 64-bit floats. I use this all the time in CShop:

Function BLITZ_gluPerspective(fovy#,aspect#,zNear#,zFar#)
dblBank=CreateBank(8)
SngToDbl fovy,dblBank
fovy_l=PeekInt(dblBank,0)
fovy_r=PeekInt(dblBank,4)
SngToDbl aspect,dblBank
aspect_l=PeekInt(dblBank,0)
aspect_r=PeekInt(dblBank,4)
SngToDbl zNear,dblBank
zNear_l=PeekInt(dblBank,0)
zNear_r=PeekInt(dblBank,4)
SngToDbl zFar,dblBank
zFar_l=PeekInt(dblBank,0)
zFar_r=PeekInt(dblBank,4)
FreeBank dblBank
gluPerspective fovy_l,fovy_r,aspect_l,aspect_r,zNear_l,zNear_r,zFar_l,zFar_r
End Function

Function SngToDbl( x#, bank )
Local s, e, m, Lo, Hi, n
PokeFloat bank, 0, x
n=PeekInt( bank, 0 )  ; raw bits of x
s=n And %10000000000000000000000000000000  ; sign bit
e=n And %01111111100000000000000000000000  ; 8-bit exponent
e=(e Shr 3) + %00111000000000000000000000000000  ; 11-bit exponent
m=n And %00000000011111111111111111111111  ; 23-bit mantissa
Lo=m Shl 29  ; final three bits of mantissa
Hi=s Or e Or (m Shr 3 ) ; sign, exponent, first twenty bits of m
PokeInt bank,0,Lo
PokeInt bank,4,Hi
End Function



Pepsi(Posted 2003) [#12]
ok, SngToDbl should solve a bit of problems I had. Man, talk about hacking, well if it works then it works! heh... I'll try looking into converting some of my C code to Blitz and see if that SngToDbl helps me. Any OpenGL commands that deal with Doubles or Pointers had me stomped in Blitz alone. I guess if we need some kind of opengl functionality that can't be done in blitz alone, then we can add optional dlls later.

Well, as for other formats... every now and then I see people talking about .png for using the alpha component with it. But I'm not an alpha freak. I know tga uses the alpha component, so people can use that. If you have it written, why waste it. Use what you have. The external image loaders/savers library can be added later if needed.

DrawArrays are supposely faster then GLLists. But,they involve using vertex,color,texture coordinates and normal structures. As for DrawArrays, you would have to pass the pointer to functions like glVertexPointer, glColorPointer, and glTexCoordPointer. Before you use DrawArrays, you need to use the glEnableClientState function to enable the arrays( the structures arrays ) that DrawArrays will use. Below, is simple C/C++ code that does this:
//	
//	Multiple Vertex Arrays Example
//
struct Vertex
{
	float x, y, z;
};

Vertex g_cubeVertices[] =
{
	{ -1.0f,-1.0f, 1.0f },
	{  1.0f,-1.0f, 1.0f },
	{  1.0f, 1.0f, 1.0f },
	{ -1.0f, 1.0f, 1.0f },

	{ -1.0f,-1.0f,-1.0f },
	{ -1.0f, 1.0f,-1.0f },
	{  1.0f, 1.0f,-1.0f },
	{  1.0f,-1.0f,-1.0f },

	{ -1.0f, 1.0f,-1.0f },
	{ -1.0f, 1.0f, 1.0f },
	{  1.0f, 1.0f, 1.0f },
	{  1.0f, 1.0f,-1.0f },

	{ -1.0f,-1.0f,-1.0f },
	{  1.0f,-1.0f,-1.0f },
	{  1.0f,-1.0f, 1.0f },
	{ -1.0f,-1.0f, 1.0f },

	{  1.0f,-1.0f,-1.0f },
	{  1.0f, 1.0f,-1.0f },
	{  1.0f, 1.0f, 1.0f },
	{  1.0f,-1.0f, 1.0f },

	{ -1.0f,-1.0f,-1.0f },
	{ -1.0f,-1.0f, 1.0f },
	{ -1.0f, 1.0f, 1.0f },
	{ -1.0f, 1.0f,-1.0f }
};

struct Color
{
	float r, g, b;
};

Color g_cubeColors[] =
{
	{ 1.0f, 0.0f, 0.0f },
	{ 1.0f, 0.0f, 0.0f },
	{ 1.0f, 0.0f, 0.0f },
	{ 1.0f, 0.0f, 0.0f },

	{ 0.0f, 1.0f, 0.0f },
	{ 0.0f, 1.0f, 0.0f },
	{ 0.0f, 1.0f, 0.0f },
	{ 0.0f, 1.0f, 0.0f },

	{ 0.0f, 0.0f, 1.0f },
	{ 0.0f, 0.0f, 1.0f },
	{ 0.0f, 0.0f, 1.0f },
	{ 0.0f, 0.0f, 1.0f },

	{ 1.0f, 1.0f, 0.0f },
	{ 1.0f, 1.0f, 0.0f },
	{ 1.0f, 1.0f, 0.0f },
	{ 1.0f, 1.0f, 0.0f },

	{ 1.0f, 0.0f, 1.0f },
	{ 1.0f, 0.0f, 1.0f },
	{ 1.0f, 0.0f, 1.0f },
	{ 1.0f, 0.0f, 1.0f },

	{ 0.0f, 1.0f, 1.0f },
	{ 0.0f, 1.0f, 1.0f },
	{ 0.0f, 1.0f, 1.0f },
	{ 0.0f, 1.0f, 1.0f }
};

struct TexCoord
{
	float tu, tv;
};

TexCoord g_cubeTexCoords[] =
{
	{ 0.0f, 0.0f },
	{ 1.0f, 0.0f },
	{ 1.0f, 1.0f },
	{ 0.0f, 1.0f },

	{ 1.0f, 0.0f },
	{ 1.0f, 1.0f },
	{ 0.0f, 1.0f },
	{ 0.0f, 0.0f },

	{ 0.0f, 1.0f },
	{ 0.0f, 0.0f },
	{ 1.0f, 0.0f },
	{ 1.0f, 1.0f },

	{ 1.0f, 1.0f },
	{ 0.0f, 1.0f },
	{ 0.0f, 0.0f },
	{ 1.0f, 0.0f },

	{ 1.0f, 0.0f },
	{ 1.0f, 1.0f },
	{ 0.0f, 1.0f },
	{ 0.0f, 0.0f },

	{ 0.0f, 0.0f },
	{ 1.0f, 0.0f },
	{ 1.0f, 1.0f },
	{ 0.0f, 1.0f }
};

	glBindTexture( GL_TEXTURE_2D, g_textureID );

	glEnableClientState( GL_VERTEX_ARRAY );
	glEnableClientState( GL_COLOR_ARRAY );
	glEnableClientState( GL_TEXTURE_COORD_ARRAY );
	
	glVertexPointer( 3, GL_FLOAT, 0, g_cubeVertices );
	glColorPointer( 3, GL_FLOAT, 0, g_cubeColors );
	glTexCoordPointer( 2, GL_FLOAT, 0, g_cubeTexCoords );
	
	glDrawArrays( GL_QUADS, 0, 24 );

	glDisableClientState( GL_VERTEX_ARRAY );
	glDisableClientState( GL_COLOR_ARRAY );
	glDisableClientState( GL_TEXTURE_COORD_ARRAY );




But, that stuff can be also be done later for optional rendering ways. I like it because I can change the data of the structure arrays to anything I want at anytime for stuff like vertex animation or just to simply change color.

Ok, if we can use blitz banks and pass pointers around with "*" to directly to opengl dll's, can't we just use blitz banks instead of rewritting blitz commands that do the same thing? Sorry, I guess I'm not to clear on why the dll memory stuff is needed afterall except mabie for a speed increase. I'll be glad to do it though if it's really needed.

[3:00am ZZzzz time...]


JoshK(Posted 2003) [#13]
The only reason to create the memory banks from a DLL is so both Blitz and other DLL's can call the memory DLL and create a bank, or free one. Let's say you had some DLL that loaded a file and created a mesh to pass to Blitz. The DLL would have no way of creating the stacks of memory buffers needed, and would only be able to modify the data in banks that Blitz created. If you needed to delete a structure, or sub-structure, you could only do it in Blitz code. I don't know if we'll NEED it, but freedom never hurts.

Regarding draw arrays, you need a special function for any "shape" you do? These are just for simple primitives, right? You can't use draw arrays for arbitrary meshes?

TGA alpha channels are wonderful. If you are content to stick to bmp, jpg, and tga, so am I. TGA does all the transparency I need. It can do masked texture, or transparencies:



Pepsi(Posted 2003) [#14]
Ok, I'll do the memory DLL thing. The only arguement that I can think of against it now is that if this open source project is geared towards as doing as much as possible in blitz alone then we shouldn't have a dll like this to encourage outside libraries to depend on it. To expand on this... If I were to need a special dll to manipulate a mesh for example, I would create memory inside the dll, copy mesh data to dll, manipulate the mesh data however needed, send it back to blitz and delete the memory used by the dll. I would think having dlls calling other dlls would just get messy.

Anyways, I'll go ahead and do it. I would like to get a license txt file for whatever GPL license we are going to use to include with it. As long as it doesn't require one to show the full scource code to your own project, just only the code changes to the opensource project itself that one made, I'm down with it.

Yes, DrawArrays can allow you to create any mesh you want sort of like one can with Blitz CreateMesh/CreateSurface/AddVertices/Addtriangles combo and maninpulate it in real time. The only draw back with this method that I see so far is that one can't use a second u/v coordinate channel for stuff like lightmaps. Ofcoarse, I could be wrong about that and just haven't seen a proper way to do that with this method.


JoshK(Posted 2003) [#15]
I'm sure there's a way. I'll read up on it.

Once you get the memory DLL working, we'll talk a little more seriously about the engine design.


Drago(Posted 2003) [#16]
Todd: you can use the second uv map for lightmaps with vertex arrays, the easiest way to do it though is by using the multitexture GL extension.
	glNormalPointer(gl_float,0,q3\normals)  ; setup normals
	glVertexPointer(3,GL_float,0,q3\vertices) ; setup verts
	glClientActiveTextureARB(GL_TEXTURE0_ARB); ; Set the client Texture to be the first of the 8 multi textures
	glTexCoordPointer(2,GL_FLOAT,0,q3\uv[0]) ; Setup the texcord pointers for this texture
	glClientActiveTextureARB(GL_TEXTURE1_ARB); ; set the second texture to be the active one.
	glTexCoordPointer(2,GL_FLOAT,0,q3\uv[1]) ; setup the tex cord array for this texture.
	glEnableClientState(GL_TEXTURE_COORD_ARRAY); enable the array
      ; The next few lines were for turning on and off the textures so you could see them with out detail map.
; (ie only lightmap) or turn off the detail map. if they both are '1' then they are both enabled.
	If tex1=1
		glClientActiveTextureARB(GL_TEXTURE0_ARB); 
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	EndIf
	If tex2=1
		glClientActiveTextureARB(GL_TEXTURE1_ARB);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	EndIf
... 
Some Vis stuff to do with quake3 bsps.
...
If tex1=1
			glActiveTextureARB(GL_TEXTURE0_ARB);
			glEnable(GL_texture_2d)
			glBindTexture(GL_TEXTURE_2D,(PeekInt(q3\tex,(texid*8))))
		EndIf
		If tex2=1
			glActiveTextureARB(GL_TEXTURE1_ARB);
			glEnable(GL_texture_2d)
			glBindTexture(GL_TEXTURE_2D,(PeekInt(q3\tex,(Lmap*8)+4)))
		EndIf
		If typ=1
			glDrawArrays(GL_TRIANGLE_FAN,vin,nver)
		Else typ=2
			glDrawArrays(GL_POLYGON,vin,nver)
		EndIf



JoshK(Posted 2003) [#17]
How about if I get meshes working with GLLists, because I am very familiar with those, and then you guys can replace the gllist compilation routine with something for GLArrays?

The mesh refreshing works just like Blitz3D's internal method. There's a flag in the mesh structure that gets activated with any command that changes the mesh. Then when it is time to render, if the flag is activated, the old GLList gets deleted, and a new one is compiled and stored. I imagine Arrays would work the same way.


slenkar(Posted 2003) [#18]
Will this be much faster than Blitz3D?

If so, is there a way to use it with Blitz3D?

For the end-user, what will the complexity of the language be compared to BLtiz3d?


JoshK(Posted 2003) [#19]
1. Yes
2. No
3. Probably more complicated, because it will allow more control. This isn't a "product", so I don't really care about making it nice for beginners to use. It'll just be whatever works best for us.


Pepsi(Posted 2003) [#20]
Still at the Bank DLL. Got pretty much every blitz command mimic'd. Just got to figure out why memmove doesn't work for me.

Drago: Thanks! I assume thats a two pass deal?

Josh: Yeah, the DrawArrays can be added in later. np.


Drago(Posted 2003) [#21]
Todd: it uses the multitexture features of the video card, a 2 pass method would work as well, where you draw it once, then draw the it with the other texture info, with some kind of blend mode setup.


JoshK(Posted 2003) [#22]
I use the multipass method. It's really easy, and it's pretty cool how all the GL blend modes work. I also use it for dynamic weapon flashes.


Pepsi(Posted 2003) [#23]
Coolness :)

Well, I got peek and poke to working for byte, short and int. Mr.Float wants to be an arse and only give me 6 digits.


JoshK(Posted 2003) [#24]
If you just need to peek and poke straight to a pointer, this will do it:
http://www.leadwerks.com/code/userlibs/memory/


Pepsi(Posted 2003) [#25]
The problem I'm having is that it seems that blitz is screwing up my floats when passed back and forth through the uselib function.

I might have to go as far as splitting a float at the decimal into two parts to see if I can keep the same freak'n float value. This is starting to get ridiculas.


Pepsi(Posted 2003) [#26]
Damn, it's like blitz is rounding the float values by itself or somewhat! My C/C++ poke/peek float functions works perfectly. I simply do an immediate test of the float value being passed to from the dll and blitz itself is f**king it up. The hell. The split thing is probably the only thing I can do for passing floats properly now. This is simply ridiculas.

I'll just start a new c/c++ project and f**k around with a float function to see if I'm going insane or not.


JoshK(Posted 2003) [#27]
Are you using 32 or 64-bit floats? Is that a stupid question?


skidracer(Posted 2003) [#28]
6 digits is about right for blitz floats

http://www.blitzbasic.com/Community/posts.php?topic=26011

why are you after exact precision?


Pepsi(Posted 2003) [#29]
Not a stupid question. I'm using 4bytes/32bit floats.

I remmeber that post, but I thought it was to do when you try to print it out. I didn't know it would screw floats up when you simply pass it to a dll function.

Ok I pass the float '1212.122' to my dll. Immediately I get '1212.121948'. '1212.121948' is stored like that in the dll. Then when I peek it back to blitz, '1212.121948' becomes '1212.12'.

Now I ask is that acceptable floating precision tolerance? Ofcoarse the bigger the floating point number, the more the precision flys out the window( yeah, given regular single precision on it's inaccuracies, but this is just plane out there in left field. ).


skidracer(Posted 2003) [#30]
If you are using VisualC the code

float f=1212.122f;

will give you 1212.12 in the watch window (also rounds string conversion to 6 digits) and prints 1212.121948 using printf("f=%f\n",f); so I don't quite see why you are getting so cross.


Pepsi(Posted 2003) [#31]
DLL source is not included until we decide and get a GPL type liscense so I can include it.

http://blitz.idigicon.com/project_detailb.asp?ProjectName=xBank

Pretty straight forward as the regular blitz bank commands. Bug hunt!


Pepsi(Posted 2003) [#32]
Ok... sorry for getting so cross Simon. I just never dealt with actaully watching the actaul results of a float get chewed up like that and got panicy. Thats all. I'll get over it.


JoshK(Posted 2003) [#33]
As long as it's getting rounded, not an inaccuracy that keeps getting magnified, I think it's fine. Pass the value back and forth about 1000 times. If it just rounds, it will stay the same. If there is actually a problem, you'll know it really quick.

num#=1212.121948
Print num
WaitKey
End


Your thoroughness is admirable, but my guess is everything is fine. I'd be perfectly comfortable handling CSG or BSP with 10^6 accuracy.


Pepsi(Posted 2003) [#34]
Ok, I did the 1000 times test and it didn't go crazy. Now, that I got that out of the way, what next? When your ready to talk about the project plans, let me know. If you are including alot of blitz code work that you already done, then I rather start working off of that by adding to it unless you are wanting to start from a clean slate.


Pepsi(Posted 2003) [#35]
I posted the dll link above... I guess it wasn't to clear... here's it is again:
http://blitz.idigicon.com/project_detailb.asp?ProjectName=xBank

/me going back to your last post to finish reading it...


Pepsi(Posted 2003) [#36]
Dang it, hit the enter key by accidents...
Editing:


Pepsi(Posted 2003) [#37]
How is the blitz structure like?

I see you +4 on the base address to poke in the realaddress and +8 to poke in the size... whats poked at the base address?

Your Mesh methods sound interesting and I pretty much agree about the lighting. I'm a vertex color/lighting fan myself.

Also, I just got my C/C++ dll to do a blitz+ app in fullscreen without the need for the blitz graphics() command. Having this done in blitz code would be cool for this project. I'll be glad to take a shot at that too. Get some fullscreen/window mode switching going on and even changing resolutions.


JoshK(Posted 2003) [#38]
What is the advantage of switching screen resolution from a DLL, rather than Blitz?

The Blitz bank structure is simply two memory buffers. The first one is the actual bank variable, and is always size 12. Here is the structure:

0 - C function pointer (don't worry about it, I just make it 0)
4 - pointer to second memory buffer
8 - size of second memory buffer

When a bank is resized, the pointer at position 4 might become a totally different memory buffer, but the bank variable still works because it doesn't change.

Pseudo code:
Procedure BankAddress(bank)
Return PeekL(bank,4)
EndProcedure

Procedure BankSize(bank)
Return PeekL(bank,8)
EndProcedure

Procedure ResizeBank(bank,size)
pointer=PeekL(bank,4)
freememory pointer
newpointer=AllocateMemory(size)
PokeL bank,4,newpointer
PokeL bank,8,size
EndProcedure



Pepsi(Posted 2003) [#39]
Ah... I pass a pointer to an integer array in which stores the physical address location of the buffer. The passed pointer is like so:
	struct BlitzPointer
	{
		int args[8]; // 32 bytes
	};


then I store the integer pointer of what I need in the args sort of like:
BlitzPointer *bptr=NULL;
XBANK *entity = NULL;
.
.
.
bptr->args[0] = (int) entity;
.
.
.


where for this memory dll, XBANK structure is
struct XBANK
{
	vector<void*> buffer;
};



I forget the exact reason why I have to pass pointers like that. That's how skidmark and Mark sibly got around teaching me to do it with c/c++. So I sticked with it.


Pepsi(Posted 2003) [#40]
ok, I'll look into what you said above.

The advantage I can see is that you dont have to go "Find a Window" and keeps blitz graphics commands away from our graphic commands. But, if what you have works... then we can use it and I can just go on and do something else for the project.


Pepsi(Posted 2003) [#41]
I tried every which way, but I can't get it to work in a structure like what your PB version has. I keep getting the 'invalid handle' errors. I'll try again tommorrow... need to go now.


Pepsi(Posted 2003) [#42]
I give up on trying to make it to work with direct blitz bank structures for now. Since the code of this dll will be available, you or someone else may see the light on how to do it with C/C++ and submit code & dll to do exactly what you want or at least tell me how to do it via C/C++. I really cant stand seeing another 'invalid bank handle' message again.


JoshK(Posted 2003) [#43]
I found your problem.

First, your actual data is offset by 10 bytes. If this is can't be changed, then you can get around it by returning the pointer+10.

Second, your Integers are getting poked and peeked wrong. PeekInt bank,3,5 should poke 5 to byte 3. In your case, it pokes 5 to byte (3*4), or 12, plus the 10-byte offset.

In Blitz, you usually use a loop like this for integers:
For n=0 to (BankSize(bank)-1)/4
PeekInt(bank,n*4)
Next

But in your case, that would return values for every 16 bytes.


Allocating a memory buffer of size '8' should give you this:

*pointer
*pointer+1 byte
*pointer+2 byte
*pointer+3 byte
*pointer+4 byte
*pointer+5 byte
*pointer+6 byte
*pointer+7 byte

Now PokeInt(bank,4,69):
*pointer+0
*pointer+1
*pointer+2
*pointer+3
*pointer+4=69 ]
*pointer+5=69 |====This is all one integer,
*pointer+6=69 |====not 69 each byte
*pointer+7=69 ]

PokeInt(bank,1,52) would give:
*pointer+0
*pointer+1=52 ]
*pointer+2=52 |====This is all one integer,
*pointer+3=52 |====not 52 each byte
*pointer+4=52 ]
*pointer+5
*pointer+6
*pointer+7

But your DLL changes it to 1*4 (ignoring the 10-byte offset):
*pointer+0
*pointer+1
*pointer+2
*pointer+3
*pointer+4=52 ]
*pointer+5=52 |====This is all one integer,
*pointer+6=52 |====not 52 each byte
*pointer+7=52 ]


Pepsi(Posted 2003) [#44]
Hrm... ok , I look it over...


JoshK(Posted 2003) [#45]
Take your time. This is pretty tedious stuff.


Pepsi(Posted 2003) [#46]
can you please make me an example of reading the dll created bank like that in blitz. Mabie using the 'RtlMoveMemory2' command or how ever you do it. I need to see this. Thanks.


JoshK(Posted 2003) [#47]
Note: Peek and PokeL act directly on a memory buffer, not like Peek and PokeInt(), which use the Blitz bank structure.

Create a bank:
ProcedureDLL CreateExternalBank(size)
*pointer=AllocateMemory(12)
*address=AllocateMemory(size)
PokeL *pointer,0
PokeL *pointer+4,*address
PokeL *pointer+8,size
Return *pointer
EndProcedure


Get the memory address where a bank's data is actually stored:
ProcedureDLL BankAddress(*pointer)
*address=PeekL(*pointer+4)
Return *address
EndProcedure


Poke a value. First you get the address where tha bank's data is stored, then you add the offset to that to get the memory position to peek from:
ProcedureDLL PeekInt(*pointer,offset)
*address=PeekL(*pointer+4)
Return PeekL(*address+offset)
EndProcedure


Note: When calling user libs, Blitz will pass the bank address to the lib if the variable is like this: variable*. If the variable is an integer, Blitz will pass the 12-byte bank handle. The BankAddress() example will not work unless the decls file looks like this:
BankAddress%(bank%)

You could also do this:
Procedure BankAddress(*pointer)
Return pointer
End Procedure


And the decls file would be:
BankAddress(bank*); Blitz passes the bank address the DLL instead of the handle.

In the case of the abov PeekInt function, the bank variable passed to the DLL should be an integer in the decls file, since the lib checks the bank handle for the address, and then changes that.


Pepsi(Posted 2003) [#48]
I mean in bltiz code. Or did you read my dll banks with your PB source functions?


JoshK(Posted 2003) [#49]
Blitz can't peek directly to memory buffers. It always checks position 8 of the memory address you give it, and then adds that to the offset to get the memory position to use. With the memory lib I posted, you can use PeekL() and PokeL() to peek and poke values directly to a memory position.


Pepsi(Posted 2003) [#50]
Man, I simpy can't see whatever you see. I'll just update the DLL zip with the source code and even post the C code here just in case if you or anybody else can see whatever is wrong, if so. It works good for me.


Pepsi(Posted 2003) [#51]
.


Pepsi(Posted 2003) [#52]
The xBank userlib has been updated with included source code. Also I noticed I wasn't doing the PeekInt/PokeInt corectly in my xbankx_test.bb code. Please, anybody, show me in C/C++ and Blitz code if I'm doing something wrong in storing data in memory if you can please. I simply cannot mimic what Josh is doing to visually see for myself these problems. Thanks.

Click the link below to get the new xBank userlib...
http://blitz.idigicon.com/project_detailb.asp?ProjectName=xBank


skidracer(Posted 2003) [#53]
You are using a vector of char pointers??? A vector of chars might be ok but is not really that suitable IMHO either given you want a statically sized block of memory that doesn't move...

Also your range checking is out, eg in PokeInt the check should be (offset+4 <= entity->buffer.size())...


Pepsi(Posted 2003) [#54]
I luv vector arrays. Yes, your right on about the vector<char*>. I was testing\playing around forgot to delete the '*' from it. :\

Also, I updated the int and floats with the offset+4 bound check... and the short with +2.

Thanks for looking it over.

edit: and +1 for byte


edit: also, I haven't really playd around with Blitz's CopyBank to make sure the my xCopyBank does exactly what blitz does. In my function, if you are copying more then what srcBank has into destBank, then zeros will fill up what can't be copied from srcBank. Also, if destBank gets overfilled with copied data from srcBank, destBank will just add on to the end the rest of the data being copied from srcBank. Stuff like that. I guess I should see how blitz's CopyBank command works in these situations.


JoshK(Posted 2003) [#55]
Thanks, I'll take a look at it later.

How about this:
Because the same Peek and Poke commands will be used regardless of whether or not we get external banks working, we proceed using Blitz banks, and if and when the DLL is working, we can just replace all the Create, Resize, and Free commands with the new ones.


Pepsi(Posted 2003) [#56]
Sounds cool to me. Since the Dll source code is available, anybody, if so desired to, can try to fix it if I can't. It "should" be pretty easy to include if/when it works with the blitz bank structure.


Pepsi(Posted 2003) [#57]
Josh, so whats the plan? Are you waiting for this xBank code to work with blitz bank structures before you get what you have out for us to start from? Not rushing ya, just curious.
-----------
Edit: 'Unknown' ??? hrmmm...


JoshK(Posted 2003) [#58]
Sorry, my computer wouldn't let me login yesterday.

I have been pretty busy with the release of CShop 4, but that's done now, and I am working on this engine.

I have some basic OpenGL stuff set up. I am going to take care of the coordinate system math today. What this involves is performing transformations on Blitz3D entities, and comparing the results to my math code to make sure I am getting the equations right. Once I have the coordinate systems and mesh structures set up, I will post the code.


JoshK(Posted 2003) [#59]
Incidentally, it appears that the Blitz3D and BLitzPlus bank structures are different! Sorry. Let's just write the whole thing in BlitzPlus, at least while we're testing, and we can always convert the code to C/C++ or something else at some later time.


Pepsi(Posted 2003) [#60]
Sounds good to me! np on the bank structure thing. It was still interesting for me to get the blitz-like bank functioanlity done in C. It could come in handy someday.


JoshK(Posted 2003) [#61]
Here ya go:
http://www.leadwerks.com/Deimos.zip

Features
-Entity movement, rotation
-Cameras
-Simple meshes
-Entity parenting
-Quaternion commands
-Vector commands
-GL rendering

Transformation commands are not working yet.

Deimos.bb is the only "official" include you need. The progs folder is just stuff I happened to use in this demo.

All GL and API userlibs are included.


JoshK(Posted 2003) [#62]
[EDIT]

I THINK this works. It's kind of hard to test, but I think it's right. Use VectorX,Y,Z() to return values. This is probably one of the toughest routines to code, because it is so difficult to test.

Function TFormPoint(x#,y#,z#,src_entity,dest_entity)
vectorx=x
vectory=y
vectorz=z
;Transform from source to world
If src_entity
	x=x*EntityScaleX(src_entity)
	y=y*EntityScaleY(src_entity)
	z=z*EntityScaleZ(src_entity)
	parentx#=entityx(src_entity)
	parenty#=entityy(src_entity)
	parentz#=entityz(src_entity)
	qx#=entityqx(src_entity)
	qy#=entityqy(src_entity)
	qz#=entityqz(src_entity)
	qw#=entityqw(src_entity)
	mat00#=(1.0-2.0*qx#*qx#-2.0*qz#*qz#)
	mat01#=-(2.0*qz#*qy#+2.0*qw#*qx#)
	mat02#=2.0*qw#*qz#-2.0*qx#*qy#
	mat10#=-(2.0*qz#*qy#-2.0*qw#*qx#)
	mat11#=1.0-2.0*qy#*qy#-2.0*qx#*qx#
	mat12#=2.0*qx#*qz#+2.0*qw#*qy#
	mat20#=-(2.0*qx#*qy#+2.0*qw#*qz#)
	mat21#=(2.0*qw#*qy#-2.0*qx#*qz#)
	mat22#=1.0-2.0*qz#*qz#-2.0*qy#*qy#
	vectorx#=x#*mat00#+y*mat10#+z*mat20#
	vectory#=x#*mat01#+y*mat11#+z*mat21#
	vectorz#=x#*mat02#+y*mat12#+z*mat22#
	vectorx#=vectorx#+entityx(src_entity)
	vectory#=vectory#+entityy(src_entity)
	vectorz#=vectorz#+entityz(src_entity)
	x#=vectorx#
	y#=vectory#
	z#=vectorz#
	parent=GetParent(src_entity)
	If parent
		tformpoint vectorx,vectory,vectorz,parent,0
		EndIf
	EndIf
;Transform from world to destination
If dest_entity
	parent=GetParent(dest_entity)
	If parent
		tformpoint vectorx,vectory,vectorz,0,parent
		EndIf
	x=x-entityx(dest_entity)
	y=y-entityy(dest_entity)
	z=z-entityz(dest_entity)
	qx#=entityqx(dest_entity)
	qy#=entityqy(dest_entity)
	qz#=entityqz(dest_entity)
	qw#=-entityqw(dest_entity)
	mat00#=(1.0-2.0*qx#*qx#-2.0*qz#*qz#)
	mat01#=-(2.0*qz#*qy#+2.0*qw#*qx#)
	mat02#=2.0*qw#*qz#-2.0*qx#*qy#
	mat10#=-(2.0*qz#*qy#-2.0*qw#*qx#)
	mat11#=1.0-2.0*qy#*qy#-2.0*qx#*qx#
	mat12#=2.0*qx#*qz#+2.0*qw#*qy#
	mat20#=-(2.0*qx#*qy#+2.0*qw#*qz#)
	mat21#=(2.0*qw#*qy#-2.0*qx#*qz#)
	mat22#=1.0-2.0*qz#*qz#-2.0*qy#*qy#
	vectorx#=x#*mat00#+y*mat10#+z*mat20#
	vectory#=x#*mat01#+y*mat11#+z*mat21#
	vectorz#=x#*mat02#+y*mat12#+z*mat22#
	vectorx=vectorx/EntityScaleX(dest_entity)
	vectory=vectory/EntityScaleY(dest_entity)
	vectorz=vectorz/EntityScaleZ(dest_entity)
	EndIf
End Function



JoshK(Posted 2003) [#63]
Obviously, it still needs work:

Include "deimos\deimos.bb"

box=createentity(box)
positionentity box,Rnd(-100,100),Rnd(-100,100),Rnd(-100,100)
rotateentity box,Rnd(-100,100),Rnd(-100,100),Rnd(-100,100)
tformpoint 1,1,1,box,box
RuntimeError vectorx()+", "+vectory()+", "+vectorz()



Pepsi(Posted 2003) [#64]
Just downloaded it and put all the Decls files in the userlib file and tried to run the demo.bb file. It was unable to find the rgb() function in cameras.bb on line 29

PokeInt buffer,DEIMOS_CAMERA_RGB,rgb(0,0,0)

You got this demo to work for you with blitz+, right?

I'll look into more of it here in a moment and try to brain storm areas I can add to.


JoshK(Posted 2003) [#65]
You can comment out that line, or replace it with PokeInt buffer,DEIMOS_CAMERA_RGB,-16722216 or whatever "black" is. The color userlib is also available at http://www.leadwerks.com/code/userlibs/

TFormPoint now works perfectly. That was all fairly easy to put together, in the space of about a day.

I also fixed it so CreateCamera works with an hwnd, not a gadget. This will make it easy to convert the engine straight to a C/C++ DLL, if we want.

I want to talk about two issues.

1) What model file format(s)?
I don't like writing loaders for every file format under the sun, but it is kind of cool when you can load MD3's, SMD, etc. A single unique file format would be easier, but it's kind of hard to deal with when you are developing at the same time. Any thoughts? What modeling packages do you guys use? I can write a 3ds max exporter. We have two extreme options. Ascii, or pure internal format? The first is easy to read. The second actually stores data the same way the engine does, so it is just instantly loaded into memory, but is also more complex and harder to test.

2) What about lighting? I think lights should be an internal engine thing that the user only accesses at the top level. Vertex light calculation is simple enough. Lightmaps from CShop or another program can be displayed with no problem. What about dynamic lights? I hope you saw the volumetric lighting I did in the last Singularity demo. I could repeat that. Any other ideas? How do "real" engines do lights?


Pepsi(Posted 2003) [#66]
Ok, then I'll look into translating your color dll to blitz.

About the file formats, "to me" this almost rides on the notion that you want this open source 3d engine to be totally customizable. So, I would think it would be better to later create add-ons to load/save various 3d file formats if so desired. In this case, people here know blitz. Why not just get something we are more likely all somewhat more familiar with, the .b3d format. That will give us d'em bones to animate. The modelling & animation tools I have are gameSpace( currently does .md2 & md3 well supposely) and the common characterFX, Milkshape, Ulitmate Unwrap tools. But, I lack good experience in this area.

About the lights, vertex lighting is a must in my book. As for glLights, I think the engine should have access to lights & materials just as easy if you were programming with them directly via OpenGL. I haven't seen the volumetric lighting demo you've done. If it can be added to the engine with ease then go for it... or if it's to "customized" to simply put into the engine, then you could share it as a demo example to show how to use the engine to make it work for you.

Those are just my thoughts. I would like to hear more from various other people also.

I'm off... I'll look more into the code provided tommorrow. Thanks for getting this started for us, Josh. This should be fun to be part of.


JoshK(Posted 2003) [#67]
I reuploaded with a version that requires no userlibs except API and GL.


Pepsi(Posted 2003) [#68]
In the demo.bb, the scene is flickering really bad for me. looking into it...


JoshK(Posted 2003) [#69]
Try creating a panel or a canvas and using QueryObject(gadget,1) to get the hwnd.


Pepsi(Posted 2003) [#70]
tried that... does the same...

Trying to compare my opengl/b+ works against yours to see differences...

Gotta luv my visual studio editor "Find in Files" functionality...


Pepsi(Posted 2003) [#71]
In my little ogl tests, I use this drawscene framework...

Function DrawScene()
	UserControl()

	xClear(CLR_COLOR_BUFFER_BIT Or CLR_DEPTH_BUFFER_BIT);// Clear Screen And Depth Buffer
	xMatrixMode(MATRIXMODE_MODELVIEW)	
	xLoadIdentity();// Reset The Current Modelview Matrix
	xEntityLook(mycamera);

...
Render the 3d stoof here
...
	xFlip()
End Function



ahh... trying something now...


JoshK(Posted 2003) [#72]
Deimos\camera.bb contains all the rendering routines, in RenderCamera and FlipCamera. You might change around the order of commands, like put the GLViewport() command before the GLClear().


Pepsi(Posted 2003) [#73]
Yup, thats what I've been doing...

glRenderMode GL_RENDER ... ditch it... or why do we need it?

I've almost have it in the same style I do mine... but still getting mad flickering. Still looking...


JoshK(Posted 2003) [#74]
About lights...

1. I think we should set this up with some built-in lighting methods, eventually a shadow system. Blitz3D is too open-ended. If you want high-end lighting and physics, you have to build it into the system, because the routines are just too complicated to keep separate. If someone really wants to change it, they can edit the engine code.

2. GL lights are terribly complex, and don't work with vertex lights. Because I make extensive use of vertex-lit static meshes in my levels, I did away with DX lights completely, and think the same should be done here. Vertex lighing is good for characters and small meshes. The multi-pass lighting the last Singularity demo used is good for the brush walls of a level. Lightmapping, of course, provides most of the lighting and shadows. Anything beyond these should be done with the proper techniques. I don't know how to do those yet, but they can be added in time.

3. Using fewer normal vertices will result in faster calculation of lights. One of my cubes only needs to make 6 normal calculations to light all vertices, as opposed to the 24 it would take Blitz3D.

I uploaded a new version with some simple vertex lights.


Pepsi(Posted 2003) [#75]
Good arguement, I'll go with that. Me, right now, I wouldn't really need to worry about glLights unless they start chanting for them.


JoshK(Posted 2003) [#76]
Screw 'em if they do!


Pepsi(Posted 2003) [#77]
Ha!

ok, no where was this defined:

Const PFD_DOUBLEBUFFER = $00000001
Const PFD_DRAW_TO_WINDOW = $00000004
Const PFD_SUPPORT_OPENGL = $00000020

I simply added them at the top of the opengl.bb file. I imagine something got misplaced when you zip'd up the diemos.zip file. Anyways, no longer have the flickering from hell problem.


Pepsi(Posted 2003) [#78]
Looks like you did a nice job with keeping things entity based. The mesh.bb file sparks my interest as I have my dll library pretty much complete with mesh/surface building functions. I'll have a play with this mesh file tommorrow...

laters... Zzzz time.


JoshK(Posted 2003) [#79]
Before I continue, I need to know how GL arrays work. With display lists, if I change anything, I have to recompile the list. A simple rotating object will have to get relit and recompiled every frame, and as a result will never be rendered with fast GL lists. Do gl arrays have to be recompiled any time vertex colors change?


JoshK(Posted 2003) [#80]
I added a routine that automatically compiles GLLists, the same kind of thing Blitz3D does. Any command that changes a mesh also pokes a value of 1 to DEIMOS_ENTITY_CHANGED. If the rendering routine finds this value, it recompiles the mesh and pokes a value of 0, so that it doesn't get recompiled again.

From deimos\camera.bb:

Function RenderMesh(entity)
list=PeekInt(entity,DEIMOS_ENTITY_GLLIST)

;If mesh has changed, recompile list
If PeekInt(entity,DEIMOS_ENTITY_CHANGED)

	PokeInt entity,DEIMOS_ENTITY_CHANGED,0

	;delete old list
	If list glDeleteLists list,1

	;start new list
	list=glGenLists(1)
	glNewList list,GL_COMPILE
	bank=CreateBank(4)
	PokeInt bank,0,0
	glGetIntegerv(GL_LIST_INDEX,bank)
	FreeBank bank
	PokeInt entity,DEIMOS_ENTITY_GLLIST,list

	;Add all drawing commands to the list
	glBegin GL_TRIANGLES
	For t=1 To CountTriangles(entity)
		For c=1 To 3
			geometryvertex=TriangleVertex(entity,t,c,0)
			colorvertex=TriangleVertex(entity,t,c,1)
			normalvertex=TriangleVertex(entity,t,c,2)
			x#=VertexX(entity,geometryvertex)
			y#=VertexY(entity,geometryvertex)
			z#=VertexZ(entity,geometryvertex)
			vr#=VertexX(entity,colorvertex,1)/255.0
			vg#=VertexY(entity,colorvertex,1)/255.0
			vb#=VertexZ(entity,colorvertex,1)/255.0
			glColor3f vr,vg,vb
			glVertex3f x,y,z
			Next
		Next
	glEnd
	glEndList
	EndIf

;Call gllist (actual drawing)
glPushMatrix
BuildCoordinateSystem(entity)
glCallList list
glPopMatrix


Now it looks like GL vertex arrays are just pointers to vertex lists stored in order. That's easy, and they can be changed without recompiling the mesh.

What is the difference between GLDrawElements and GLDrawArrays?


Pepsi(Posted 2003) [#81]
Good good...

I had to actaully switch to glDrawElements from glDrawArrays because I was having some kind of issues with accessing the Array Pointers.

Anyways, here's my surface render snippet in C using glDrawElements:
					if(ThisSurface->texID[0]>0)
					{
						glEnable(GL_TEXTURE_2D);
						glBindTexture(GL_TEXTURE_2D,ThisSurface->texID[0]);
					}
					else
					{
						glDisable(GL_TEXTURE_2D);
					}

					//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
					//glEnable(GL_BLEND);			// Turn Blending On
					//glDisable(GL_DEPTH_TEST);	// Turn Depth Testing Off

					glEnableClientState( GL_VERTEX_ARRAY );
					glEnableClientState( GL_NORMAL_ARRAY );
					glEnableClientState( GL_COLOR_ARRAY );
					glEnableClientState( GL_TEXTURE_COORD_ARRAY );

					glVertexPointer( 3, GL_FLOAT, sizeof(SurfaceVertex), &ThisSurface->thisVertex[0]);
					glNormalPointer( GL_FLOAT, sizeof(SurfaceVertexNormal), &ThisSurface->thisVertexNormal[0]);
					glColorPointer( 4, GL_FLOAT, sizeof(SurfaceVertexColor), &ThisSurface->thisVertexColor[0]);
					glTexCoordPointer( 2, GL_FLOAT, sizeof(SurfaceVertexTexCoord0), &ThisSurface->thisVertexTexCoord0[0]);
		
		            glDrawElements ( GL_TRIANGLES, ThisSurface->thisTriIndices.size()*3, GL_UNSIGNED_INT, &ThisSurface->thisTriIndices[0] );
	
					glDisableClientState( GL_TEXTURE_COORD_ARRAY );
					glDisableClientState( GL_COLOR_ARRAY );
					glDisableClientState( GL_NORMAL_ARRAY );
					glDisableClientState( GL_VERTEX_ARRAY );

					//glDisable(GL_BLEND);		// Turn Blending Off
					//glEnable(GL_DEPTH_TEST);	// Turn Depth Testing On

					if(ThisSurface->texID[0]>0)
					{
						glDisable(GL_TEXTURE_2D);
					}


[The code thats rem'd out is actaully a successfull test that I did for doing vertex alpha.]

If I remmeber right, my problem with glDrawArrays is that I had to construct a "sequence" of primitives to use it for mesh building. ie: in blitz-like psuedo code:
v0=addvertex(thisSurface,x#,y#,z#)
v1=addvertex(thisSurface,x#,y#,z#)
v2=addvertex(thisSurface,x#,y#,z#)

v3=addvertex(thisSurface,x#,y#,z#)
v4=addvertex(thisSurface,x#,y#,z#)
v5=addvertex(thisSurface,x#,y#,z#)

addtriangle(v0,v1,v2)
addtriangle(v3,v4,v5)


I wasn't able to just use four vertices and two triangles like I can with glDrawElements. With glDrawElements, I can construct any way I want to just like using the blitz mesh building commands. ie: for a quad:
v0=addvertex(thisSurface,x#,y#,z#)
v1=addvertex(thisSurface,x#,y#,z#)
v2=addvertex(thisSurface,x#,y#,z#)
v3=addvertex(thisSurface,x#,y#,z#)

addtriangle(v2,v0,v1)
addtriangle(v2,v1,v3)




About glLists. I would only use them for static meshs. Rebuilding a glList mesh like that whenever you change it's data, ie: vertex deformation, I would think causes a performance hit( even though I hadn't first handly tested what kind a performance hit it would cause ).

With glDrawElements, you can change any data of your mesh on the fly without "rebuilding" the whole mesh.

--------

About Alpha Polys: We're going to need some kind of "second list of surfaces" for a second render pass for any vertex, surface or whole mesh that contains alpha in them. A common opengl example of rendering alpha polys is to render all solid polys first, disable the zbuffer write, then render all alpha polys. I hadn't yet gotten this far in my dll library, but that's how I'm going to approach it. I can't remmeber off the top of my head if an alpha poly z-sorting routine is needed in this case or not.


Pepsi(Posted 2003) [#82]
Oh, forgot another thing. I haven't yet tested see what kind of coordinate system you are using as in right or left handed coordinate system.

Using a left handed system made it a hell of a lot easier to deal with as I can build meshs, move around, etc... the same as Blitz/DirectX. I highly recommend using this left handed coordinate system just because Blitz3D programmers will be used to it.


Pepsi(Posted 2003) [#83]
And another thing...

As we are using OpenGL, we should not limit ourselfs to GL_TRIANGLES primitive. We need to work in them there GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUAD_STRIP, GL_QUADS, and GL_POLYGON! Da more da betta.

At least include GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN to mimic DirectX capabilities.


JoshK(Posted 2003) [#84]
I am using the same coordinate system DX and Blitz use, because I needed to be able to test my transformation commands again Blitz's. You may notice that I flip the z axis in some routines. Movement should be identical to Blitz.

Z-ordering is something I realize is necessary, but don't expect to get there for a while.

I finished vertex arrays. Let me explain vertex colors.

The engine calculates vertex colors for OpenGL based on the position, normal, and original color of the vertex. Calculating these colors will NOT erase your original vertex colors. If you color a vertex (255,0,0), it will always stay that way. The engine stores a second list of colors that represent what OpenGL actually draws, and are not accessible to the user. The trick here is that the engine only recalculates these vertex lights if the mesh changes or moves, or if a light within a certain range moves. This allows us to use custom vertex lights for real-time flashes. Cartography Shop static meshes are vertex-lit to begin with. A level can be loaded with the vertex colors CShop calculates, and then static meshes can be dynamically lit by gunfire without losing the original shading. This was impossible in Blitz3D.

I have uploaded a new version. Lights and arrays are still calculated every frame in this version, but I am going to optimize it now.

Rendering commands have been moved to render.bb.


Pepsi(Posted 2003) [#85]
Alright, let say I created a level and some algorithm to grab only the polys that I can see( from and in camera view). Will I be able to get the engine to only calculate the vertex colors of that poly group of my choosing?

Lets say a "magical" light is moving through a good size dungeon. Will that light check every polygon vertex of every polygon in that level to see if it's in range to manipulate the vertex color or not?

I like to section off my levels to save on any kind of polygon checking routines where at the first level, I only check the current section's polys the camera is in and any adjacent section's polys. Will I have that kind of control of what polys the engine vertex coloring calculation will check on at any given time?


JoshK(Posted 2003) [#86]
A light would check the distance between itself and the mesh, minus the widest dimension of the mesh, for an approximation of whether the mesh is in range or not. Then it would go through and light each vertex.

Only calculating lights within the camera frustrum is a good idea, and I can add that right now. As for more advanced sectioning of the level, I think this is something that needs to be done all at once. I mean, the same system that optimizes lights should be used to optimize picking and rendering, etc. That system is going to be some kind of BSP tree, but I think it's too soon to implement.


Pepsi(Posted 2003) [#87]
I'm not much of a BSP fan anymore because I know in C/C++, one have to optimize the hell out of it to get AAA game speed performance from it's use. If you can get BSP in there at decent speeds( whenever you decide to) via blitz code, go for it.

Well, if your vertex lighting range is determined by mesh width and range, that should be fine since my "sections" are seperate meshs.


Pepsi(Posted 2003) [#88]
Are you wanting to implement the glDrawElements or not? I can take a stab at it if you would like me to( trying not to get in working on the same code that you are currently working on ). I just don't want to mess with the mesh.bb file if there needs to me a change in structure between glCalllist and glDrawElements methods.


Pepsi(Posted 2003) [#89]
I'm getting an application error now with your new diemos zip download.

You are only testing the diemo code with only the decls files you inlcude in the zip, right? As in, no other decls files in your userlib directory except the needed ones?


JoshK(Posted 2003) [#90]
I already added glDrawElements.

I deleted all userlibs except the ones included in the zip, and don't have a problem. What is the error?


Pepsi(Posted 2003) [#91]
Says, " The instruction at "0x0a8fdbbb" referenced memory at "0x056cfab4". The memory could not be "read". "


Pepsi(Posted 2003) [#92]
k, has something to do how you call glDrawElements... looking into it.


JoshK(Posted 2003) [#93]
I uploaded a new version with actual light entities. No light color or range yet.

Let me know if you find any problem with the rendering. It's all in render.bb.


Pepsi(Posted 2003) [#94]
The glDrawElements still causes this same error for me. Trying to study how your mesh structures are done. It's like it's going "out of bounds" somewhere.


Pepsi(Posted 2003) [#95]
With what you gave me, does it actaully work for you?

I'm suprised that you didn't have something like this:
glEnableClientState( GL_VERTEX_ARRAY );
;glEnableClientState( GL_NORMAL_ARRAY );
;glEnableClientState( GL_COLOR_ARRAY );
;glEnableClientState( GL_TEXTURE_COORD_ARRAY );
;Render vertex arrays
glVertexPointer 3,GL_FLOAT,0,vertexarray
;glColorPointer 3,GL_UNSIGNED_BYTE,0,colorarray
glDrawElements GL_TRIANGLES,vert,GL_UNSIGNED_SHORT,trianglearray

;glDisableClientState( GL_TEXTURE_COORD_ARRAY );
;glDisableClientState( GL_COLOR_ARRAY );
;glDisableClientState( GL_NORMAL_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );


since the gl array pointers such as glVertexPointer and glColorPointer needs the specific array stats enabled via glEnableClientState;

still getting errors because of the glDrawElements function.


Pepsi(Posted 2003) [#96]
.


Pepsi(Posted 2003) [#97]
ok, now I'm getting an error in the TriangleVertex function with "bank offset out of range" for this line:
Return PeekInt(triangles,(t-1)*48+(c-1)*4+class*12)

Please, let me know if you can't get something to work for you before passing new code over so I can have a better understanding to help out. Dont be shy.

I'm was under some wierd impression that you had this code working for you, but mabie my OS was seeing different internal things within blitz on codeing opengl stuff like this.

Please see what you can do about this " Return PeekInt(triangles,(t-1)*48+(c-1)*4+class*12) " out of bounds error.


JoshK(Posted 2003) [#98]
I'll check it out. My machine tends to let Blitz overflow memory without producing errors, so a lot of times I don't get those errors. While we're on it, is there any good way to feedback error data, like a log that records every command if debug mode is on? If you just write a file, Blitz will lose the file when it crashes.

I uploaded a new version, with actual light entities with color and range. I also fixed some coordinate system reversals that were screwing up the normals. I included an .exe in case the code doesn't run.


Pepsi(Posted 2003) [#99]
If you want to make a log file, "append" information to the file. as in psuedo code:

Create New LogFile at beginning (ie: overwrite any old file when restarting program)

(When need to throw info to the log file)
Function file_report( string$)
Open LogFile
Append string$ to LogFile
Close LogFile
End function

So when/if blitz crashes... the logfile will not be open when the crash happens.

I had a logfile include file here somewhere...


Pepsi(Posted 2003) [#100]
Ah... ok, now I see it more clearly how data goes into the DEIMOS_MESH_ARRAY_TRIANGLES part in the RenderMesh(buffer) function.

Interesting how the .exe works, but I can't for the life of me get pass this error on compile.


JoshK(Posted 2003) [#101]
It's kind of weird how I separate out the vertex data into new lists, but that's the way GL wants it.

When hunting these things down, I usually put a bunch of Notify "You made it this far." messages in my code to figure out where the crash is happening.

I got lights to run just as fast as Blitz's DirectX lights. I don't expect to have 100 little cubes being lit dynamically, but I do expect to have to light 4 or 5 fairly high-poly meshes at a time.

Sorry I can't really help you track the error, because I just don't get it. Someone else who tested it reported the same thing.


Pepsi(Posted 2003) [#102]
yeah, I use debuglog "<incremental number here>" before gl or blitz commands and thats how I found out that glDrawElements isn't working for me. When I rem it out, it compiles and runs fine... but obviously I just get a black opengl window with nothing happening.

I'm just going to have to sit down and reprogram exactly what you have and try to see what is going on step by step concentrating on how the structures are being built becasue thats what glDrawElement is complaining about for me. Thats the only thing I can think of doing at this time.

I'll do that tommorrow as it's going to take some time. I got to go now...


JoshK(Posted 2003) [#103]
If the demo works, and the code breaks, I am guessing your userlibs have a % where they should have a *.

Ah-ha...Opengl32.decls

glDrawElements( mode%, count%, ntype%, indices% ):"glDrawElements"

should be
glDrawElements( mode%, count%, ntype%, indices* ):"glDrawElements"


glColorPointer( lsize%, ntype%, stride%, Pointer% ):"glColorPointer"

should be
glColorPointer( lsize%, ntype%, stride%, Pointer* ):"glColorPointer"


glVertexPointer( lsize%, ntype%, stride%, Pointer% ):"glVertexPointer"

should be
glVertexPointer( lsize%, ntype%, stride%, Pointer* ):"glVertexPointer"


Sorry about that. I guess I updated the copy of the userlibs in the BlitzPlus directory, and sent you the old ones.



I uploaded a new version, with the userlibs copied straight out of my userlibs folder, an executable, and a Blitz3D program for speed comparison (test.bb).


Pepsi(Posted 2003) [#104]
Ohhh thats... ok. I like frying me membrains that I have left...

I'll give that a try.

Here's some logfile like functions that I use that appends info to a file. May help ya...
Global this_filename$=""

Function xCreate_Report(filename$,mode=True)
	If FileType(filename$)=1 Then DeleteFile filename$
	fileout = WriteFile(filename$) 
	stringout$="Report File - "+CurrentTime$()+" - "+CurrentDate$()	
	WriteLine( fileout, stringout$ ) 
	CloseFile( fileout ) 
	this_filename$ = filename$
End Function


Function xFile_Report(stringout$)
	If this_filename$<>""
		fileout = OpenFile(this_filename$)
		; append 
		While Not Eof(fileout)
			ReadByte(fileout)
		Wend
		WriteLine( fileout, stringout$) 
		CloseFile( fileout ) 
	EndIf
End Function



Pepsi(Posted 2003) [#105]
Ok, finally it works.

both the deimos demo and the blit3d test averaged around 50-65.

Good job!

Now... gotta go... I'll look again tommorrow about adding functionality somewhere.


JoshK(Posted 2003) [#106]
I loaded a cshop map and had 54,000 triangles rendering at 50 fps. That's about what I would expect for not having any rendering optimization (BSP).

Here's some more technical info:

-Meshes are lit with vertex lights. I've actually added another kind of vertex to the mesh structure a light vertex! It gets blended with the light color to get a result to fill in the final color array with. Meshes will be triangles only, unless someone gives me a good reason to do otherwise. See CSG brushes for my reasoning.

Meshes may also be projection-lit or lightmapped. Projection lights are the shadows and caustics that sometimes appear on a character or weapon in UT2003. All lightmapping is done in an external editor (CShop, etc.)

-CSG brushes are used for collision and picking. CSG brushes are lightmapped or decal-lit (Half-Life). Picking may still be performed with a complex mesh, but an invisible surrounding CSG brush is used to optimize the test. CSG brushes are the only kind of geometry that gets collided with. There is NO collision for meshes. CSG brushes are rendered with GL_POLYGON, as opposed to GL_TRIANGLES. CSG brushes are also useful for volumetric fog, occlusion, BSP, lighting, etc.

-I have no immediate ideas for dynamic shadows, but the stencil buffer is always there waiting for anyone who wants to take a crack at it. An easy way to start would be a shadow that just falls to a uniform height on the ground, regardless of the map geometry.


Any thoughts?


JoshK(Posted 2003) [#107]
hmmmm...

I don't think Real-time vertex lighting will work. I am trying it on a map of 5400 polys, and it crawls.

I didn't want to use GL lights because they can't be combined with vertex lights. But then I realized that we could render the vertex-lit object with lights disabled, then render it a second time with lights enabled for dynamic weapon flashes.

CSG brushes are still best off using decal lights, because brushes tend to be large flat surfaces that would look funny with vertex lights. Also, they tend to have fewer vertices, so the UV calculations will not be time-consuming.


I think next up is going to be textures, because I can't really do lights or lightmaps without seeing it with textures.


JoshK(Posted 2003) [#108]
I am working with textures now...

In Blitz3D, I guess each surface stores its own copy of the brush. This is why getbrush returns a copy of the original, and why altering a brush doesn't change a mesh it has already been applied to.

This engine is going to directly reference the original brush, so if you change the brush, all meshes painted with it change, too. The engine will sort meshes internally by brush, so rendering will always be just as fast as if the whole world was merged into a single mesh.


JoshK(Posted 2003) [#109]
Now with support for materials and multi-texturing. This shows a CShop map loaded in the engine:

Download (4 mb)

"Materials" are like Blitz3D brushes. Use CreateMaterial, LoadMaterial, LoadTexture, AddTexture, CountTextures, GetTexture, and PaintTriangle.

I am playing with blending. There's something like 81 possible blend modes!

Texture effects are just waiting to be added...


Pepsi(Posted 2003) [#110]
Ok we need some kind of source control system. The Download link above just links to your homepage. Aynways, after I downloaded with the link I usually download from, I see that you have everything in the root directory of the deimos.zip in with the deimos sub-directory.

[edit: useless stuff sniped]
-----------------

As with my dll library, I use blitz like surfaces because it organizes renderstates in a pre-calculated like way. Take polys with different textures on them. It's a good idea to render all polys with the same textures before you go on and renderer polys with another different texture. Here, a blitz surface along with it's brush attributes set's the renderstates just one time to render the texture and/or whatever else that is different from other surfaces' polys.
So a surface sets it's renderstates, a whole polygon group gets rendered... next surface, renderstates get set, a whole polygon group gets rendered, and so on. If you keep setting renderstates for each polygon no matter if the brush( or materials ) are same or different, then that will cause a rough perfomance hit because of the state changes. renderstates have to do with enable and disable things like setting textures, setting arraypointers for mesh contruction, set blend modes, etc...

Now if your "non-surface" engine can seperate out likes and dislikes into groups without us programmers having to worry about "surfaces", then coolness! Otherwise, you're gonna have higher peformance hits when there are higher renderstate changes. This could be why your 5400 map came to a crawl. Dunno, don't know your engine inside and out yet.

I don't mind tackling the stencil shadowing stuff, but I need to make sure I have all the updated files that you have so I can get the demo4.bb file to work exactly like your .exe program. Also again, we need a site to allow the files to be downloaded seperately and have an easy way to post updates and news. Something like that... anyways...


JoshK(Posted 2003) [#111]
It's a good idea to render all polys with the same textures before you go on and renderer polys with another different texture.

That's exactly what it does. Every time the mesh is change, it reorganizes the triangles into lists that have the same material, and renders each group.

Try this to download the latest source. I also made some changes to Opengl32.decls!

I am just trying to get vertex lights working for the static meshes and character models. If you uncomment the setuplight command in RenderCamera.bb, just after the GLLoadIdentity() you'll see that a point light can be made to work with vertex lights, but the light moves with the camera!


Pepsi(Posted 2003) [#112]
I like the new link to get the files from.

The demo4.bb works for me now. The setuplight stuff looks interesting. Hope ya get it sorted.

I looked into the stencil shadowing and understand it via a C implementation. So, I will try to convert the example I have over with using your engine commands.

Oh, the 'demo.bb' now just shows 1 box in the center and does nothing else.


JoshK(Posted 2003) [#113]
Whew!

Got lights and lightmaps working, completely. Check this out:

You know how I am allocating like triangles into "surfaces" for grouping the rendering? Well, it turns out the same thing has to be done for lightmaps. So while the user just paints a material or a lightmap on a single triangle, the engine allocates and stores two lists of "surfaces", one sorted by material, a second sorted by lightmap...pretty interesting, but it works great! It's not slow, because it only gets changed if the mesh is altered. This is SOOOOOOO much easier than Blitz3D, where vertes and tris "belong" to a surface.

I am currently adding the final dynamic lighting method, "decal" lights...will post a more official update when I get this done.

See this OpenGL thread:
http://www.opengl.org/discussion_boards/ubb/Forum2/HTML/014915.html


Pepsi(Posted 2003) [#114]
Thats pretty cool looking how you got the vetex lighting working on the objects like that. This will be interesting to see the full results.


JoshK(Posted 2003) [#115]
I have to add some CSG brush stuff to do the last kind of dynamic light. You can create CSGBrushes, kind of like meshes. Here are some example commands:

CreateCSGBrush()
AddCSGBrushFace(nx#,ny#,nz#,d#)
CountCSGBrushFaces()
GetCSGBrushFace()
CompileCSGBrush(); Create a mesh from the plane faces
CountFaceTriangles()
GetFaceTriangle(); accesses the mesh this CSG brush created!

And then...

AddBSPNode()
CompileBSP()
PointBSPNode(x#,y#,z#); what area of the tree is this point in?
LineBSPNode(Ax#,Ay#,Az#,Bx#,By#,Bz#,Cx#,Cy#,Cz#,[radius#]); highest node this line "crosses" up to. Radius can be used for sphere collisions.
BSPNodeVisible(camera)
BSPPointVisible(camera)


Pepsi(Posted 2003) [#116]
Hey man, PositionEntity is broken... it don't work. Please compare what files you are hosting for me to download and the ones you are working with. Thanks. The 'demo.bb' file don't work right because of this as I said above.


JoshK(Posted 2003) [#117]
Oh...check render.bb...I think I added a Return right at the beginning of BuildCoords while I was testing something.

Like I said, a clean update will be posted when I finish the lighting.


Pepsi(Posted 2003) [#118]
[first of all, sorry for my lack of explanation skills]
[All C presented here, ofcoarse needs to be converted to blitz]
Ok, studying up on what needs to be done with what I have ( C/C++ source code from NEHE Lesson 27 ), we need:

- light caster fields built into entity fields
- shadow caster fields built into entity fields

we need to do:
	SetConnectivity(&obj);								// Set Face To Face Connectivity

	for (unsigned int i=0;i<obj.nPlanes;i++)			// Loop Through All Object Planes
		CalcPlane(obj, &(obj.planes[i]));				// Compute Plane Equations For All Faces


for each entity that is a shadow caster. SetConnectivity & CalcPlane functions helps to create the shadow effect in the stencil buffer.

For the light caster entities, they will need to have an inverse matrix by doing all the actions in reverse order and with reverse parameters of all shadow caster entities effected by the specific light caster entity. So we need somehow to store all the movement/rotation actions of an entity that is to be a shadow caster in it's own structure fields. The light caster entities needs to somehow be called after all the shadow caster entites have moved (probably a second pass after everything is moved to see which ones are light casters and start calculating there). The light caster will be able to do the inverse matrix by getting the data directly from the shadow caster type fields.

[Ofcoarse also at the beginning, one would have to set what are light casters and shadow casters. A light caster will know what shadow casters it will deal with and vice versa.]

From each shadow caster, a light caster will do first:
- glLoadIdentity();
- reverse shadow caster rotation movements
- glGetFloatv(GL_MODELVIEW_MATRIX,Minv); Retrieve ModelView Matrix
- get light caster's position and store in a vector4f bank array.
- Multiply light vector with modelview matrix
- translate shadow caster's position
- glGetFloatv(GL_MODELVIEW_MATRIX,Minv); Retrieve new ModelView Matrix
- VMatMult(Minv, wlp); We Store The Position Of The World Origin Relative To The Local Coordinate System In 'wlp' bank Array
lp[0] += wlp[0]; Adding These Two Gives Us The
lp[1] += wlp[1]; Position Of The Light Relative To
lp[2] += wlp[2]; The Local Coordinate System

Then we do a ShadowCasting Function on the specific shadow caster entity with via the relative light positon.

This what the NEHE shadow castion function looks like (still got to sort this code out ):
void  CastShadow(glObject *o, float *lp){
	unsigned int	i, j, k, jj;
	unsigned int	p1, p2;
	sPoint			v1, v2;
	float			side;

	//set visual parameter
	for (i=0;i<o->nPlanes;i++){
		// chech to see if light is in front or behind the plane (face plane)
		side =	o->planes[i].PlaneEq.a*lp[0]+
				o->planes[i].PlaneEq.b*lp[1]+
				o->planes[i].PlaneEq.c*lp[2]+
				o->planes[i].PlaneEq.d*lp[3];
		if (side >0) o->planes[i].visible = TRUE;
				else o->planes[i].visible = FALSE;
	}

 	glDisable(GL_LIGHTING);
	glDepthMask(GL_FALSE);
	glDepthFunc(GL_LEQUAL);

	glEnable(GL_STENCIL_TEST);
	glColorMask(0, 0, 0, 0);
	glStencilFunc(GL_ALWAYS, 1, 0xffffffff);

	// first pass, stencil operation decreases stencil value
	glFrontFace(GL_CCW);
	glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
	for (i=0; i<o->nPlanes;i++){
		if (o->planes[i].visible)
			for (j=0;j<3;j++){
				k = o->planes[i].neigh[j];
				if ((!k) || (!o->planes[k-1].visible)){
					// here we have an edge, we must draw a polygon
					p1 = o->planes[i].p[j];
					jj = (j+1)%3;
					p2 = o->planes[i].p[jj];

					//calculate the length of the vector
					v1.x = (o->points[p1].x - lp[0])*100;
					v1.y = (o->points[p1].y - lp[1])*100;
					v1.z = (o->points[p1].z - lp[2])*100;

					v2.x = (o->points[p2].x - lp[0])*100;
					v2.y = (o->points[p2].y - lp[1])*100;
					v2.z = (o->points[p2].z - lp[2])*100;
					
					//draw the polygon
					glBegin(GL_TRIANGLE_STRIP);
						glVertex3f(o->points[p1].x,
									o->points[p1].y,
									o->points[p1].z);
						glVertex3f(o->points[p1].x + v1.x,
									o->points[p1].y + v1.y,
									o->points[p1].z + v1.z);

						glVertex3f(o->points[p2].x,
									o->points[p2].y,
									o->points[p2].z);
						glVertex3f(o->points[p2].x + v2.x,
									o->points[p2].y + v2.y,
									o->points[p2].z + v2.z);
					glEnd();
				}
			}
	}

	// second pass, stencil operation increases stencil value
	glFrontFace(GL_CW);
	glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
	for (i=0; i<o->nPlanes;i++){
		if (o->planes[i].visible)
			for (j=0;j<3;j++){
				k = o->planes[i].neigh[j];
				if ((!k) || (!o->planes[k-1].visible)){
					// here we have an edge, we must draw a polygon
					p1 = o->planes[i].p[j];
					jj = (j+1)%3;
					p2 = o->planes[i].p[jj];

					//calculate the length of the vector
					v1.x = (o->points[p1].x - lp[0])*100;
					v1.y = (o->points[p1].y - lp[1])*100;
					v1.z = (o->points[p1].z - lp[2])*100;

					v2.x = (o->points[p2].x - lp[0])*100;
					v2.y = (o->points[p2].y - lp[1])*100;
					v2.z = (o->points[p2].z - lp[2])*100;
					
					//draw the polygon
					glBegin(GL_TRIANGLE_STRIP);
						glVertex3f(o->points[p1].x,
									o->points[p1].y,
									o->points[p1].z);
						glVertex3f(o->points[p1].x + v1.x,
									o->points[p1].y + v1.y,
									o->points[p1].z + v1.z);

						glVertex3f(o->points[p2].x,
									o->points[p2].y,
									o->points[p2].z);
						glVertex3f(o->points[p2].x + v2.x,
									o->points[p2].y + v2.y,
									o->points[p2].z + v2.z);
					glEnd();
				}
			}
	}

	glFrontFace(GL_CCW);
	glColorMask(1, 1, 1, 1);

	//draw a shadowing rectangle covering the entire screen
	glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glStencilFunc(GL_NOTEQUAL, 0, 0xffffffff);
	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
	glPushMatrix();
	glLoadIdentity();
	glBegin(GL_TRIANGLE_STRIP);
		glVertex3f(-0.1f, 0.1f,-0.10f);
		glVertex3f(-0.1f,-0.1f,-0.10f);
		glVertex3f( 0.1f, 0.1f,-0.10f);
		glVertex3f( 0.1f,-0.1f,-0.10f);
	glEnd();
	glPopMatrix();
	glDisable(GL_BLEND);

	glDepthFunc(GL_LEQUAL);
	glDepthMask(GL_TRUE);
	glEnable(GL_LIGHTING);
	glDisable(GL_STENCIL_TEST);
	glShadeModel(GL_SMOOTH);
}



So any comments? Lot's to do there. It's gonna take a bit for me to program in because I still have to familuarize myself with the entity structures.


JoshK(Posted 2003) [#119]
I just finished up this demo with lightmaps, vertex lights, GL lights, and decal lights. The same decal technique can be used for blood splatters or burns that wrap around the walls. The code is a mess, but I proved that it can be done:
http://www.leadwerks.com/gldemo.zip

Regarding the stencil buffer stuff: At this point, you are just casting a shadow onto the ground, right? I think that's a great place to start, rather than trying to cast onto the walls.

You can add parameters to the entity structure without breaking it. There are parameters that indicate where other entity data will go. For example, mesh data gets written to a bank stored in the entity structure at position "DEIMOS_ENTITY_MESH". If you need to, just change that const to a larger number and insert your own field. If you add a field to the entity structure, make sure you increase the bank that CreateEntity() creates. I HIGHLY recommend you do ALL programming using constants, rather than PeekInt(bank,64). The structures WILL change, but if you are using constant names, your code won't get screwed up.


I want to work on this CSG/BSP stuff, and that will take a while. If you work on the stencil buffer, we'll both have a pretty sizable task to keep busy with for the next week or so. The way I see it is that BSP needs to be done next, which will then make picking, visibility, occlusion, and lighting much easier.

Source is updated.


Jeroen(Posted 2003) [#120]
Hey Halo and Todd,

Just wanted to say that you're busy with a great project :)


Pepsi(Posted 2003) [#121]
Thanks Jeron for the comment! :)

Josh, that demo is awsome. Nice job.

One note about the stencil buffer. I forget how to describe it exactly, but it effects the whole screen. That's why there needs to be a light point(s) (ie: light casters ) and light obscurer(s) ( shadow casters ) because the shadow effect ( ie: what you see in americasarmy.com or Tom Clancy's Splinter Cell) effects everything. It's totally different than the flexi mesh thing where you would apply the shadow a little bit above the surface of the mesh type of thing. With stencil buffers, you don't have to worry about how to physically apply the shadow itself to a mesh. Yup, It's hard for me to explain it.

Thanks for the tips on the entity structure.


JoshK(Posted 2003) [#122]
Todd, it sounds like what you are saying is that GL will just cast the shadows for us, and we don't have to calculate projection and stuff? That's definitely worth trying! The latest version I posted uses actual light entities. The light position can be gotten by EntityX,Y,Z(). The light range can be gotten by GetLightRange(), and the colors by LightRed(), LightGreen()...

To cycle through entities to find lights, use this loop:
For n=0 to BankSize(DEIMOS_ENTITY_LIST)-1 Step 8
entity=PeekInt(DEIMOS_ENTITY_LIST,n)
If EntityClass(entity)=3
Endif
Next


You might add a flag parameter to the entity flags to specify a shadow caster:
Const DEIMOS_ENTITY_FLAG_CASTSSHADOWS=2


To specify an entity to cast shadows use this:
PokeInt entity,DEIMOS_ENTITY_FLAGS,2^DEIMOS_ENTITY_FLAG_CASTSSHADOWS


To see if an entity casts shadows use this:
If EntityFlag(entity,DEIMOS_ENTITY_FLAG_CASTSSHADOWS)
Endif


Sooner or later I think we will need a DLL written to access GL extensions:
http://blitzbasic.com/Community/posts.php?topic=28532


Pepsi(Posted 2003) [#123]
Thanks for the added tips. I agree, Gl Extensions are easy to do in C/C++, but as skid said, the function pointers are the problem with blitz. That glew library looks interesting.


JoshK(Posted 2003) [#124]
Yeah, it looks like you can just write decls files that work with glew32.dll. I solved the problem without multitexturing, though, so I won't worry about it for a while. Here's the final result of the dynamic light. I fixd it so it doesn't wash out the texture colors. It does blend with the lightmap, and it washes out shadows in the area it is in, so they look kind of dynamic:

http://www.leadwerks.com/demo11.zip




Pepsi(Posted 2003) [#125]
Very nice indeed.


JoshK(Posted 2003) [#126]
It's too soon to cover all our bases, but I am thinking about an ascii file format that kind of follows the entity structures:
Pivot
	{
	0.0, 0.0, 0.0
	1.0, 1.0, 1.0
	0.0, 0.0, 0.0 ,1.0
	Mesh
		{
			{
			0.0, 0.0, 0.0
			1.0, 1.0, 1.0
			0.0, 0.0, 0.0 ,1.0
			}
		GeometryVertices
			{
			0.0, 0.0, 0.0
			1.0, 1.0, 0.0
			0.0, 1.0, 0.0
			}
		
		ColorVertices
			{
			0.0, 255.0, 0.0
			255.0, 0.0, 0.0
			0.0, 0.0, 255.0
			}
		NormalVertices
			{
			0.0, 1.0, 0.0
			1.0, 0.0, 0.0
			0.0, 0.0, 1.0
			1.0, 0.0, 0.0
			}		
		Triangles
			{
			1,2,3,2,4,3,1,8,9,3,1,1,8
			1,2,3,2,4,3,1,8,9,3,1,1,8
			1,2,3,2,4,3,1,8,9,3,1,1,8
			}
		}
	Sprite
		{
			{
			0.0, 0.0, 0.0
			1.0, 1.0, 1.0
			0.0, 0.0, 0.0 ,1.0
			}
			{
			100.0, 100.0
			}
		}
	}
Brush
	{
		{	
		0.0, 1.0, 0.0, 256.0
		"havok\dirtgen_05.tga"
		0.0, 0.0, 1.0, 256.0
		"havok\dirtgen_05.tga"
		-0.1, 0.0, 0.0, 256.0
		"earth\killblock05.tga"
		0.0, 0.1, 0.1, 256.0
		"havok\dirtgen_09.tga"
		}
		{
		"classname"="kill_field"
		"damage"="5"
		}
	}



JoshK(Posted 2003) [#127]
CSG is coming along well. Here is a 300-sided CSG cylinder. This would have absolutely killed my old routines:


That took 16 seconds to build from the plane list. Small CSG objects compile from the plane list instantly. I compiled 100 7-sided polygons in 31 milliseconds, so each one took less than 1 millisecond.

You use CSG objects for the actual walls and most of the line picking. I don't plan on writing any collision for triangles, except for some picking routines. Even then, you use a CSG bounding box around the mesh to optimize the checks.

Brushes are the only thing the player collides with. Collision with static meshes is handled by placing an invisible brush around the static mesh. It doesn't have to be a box. You can get a pretty good fit by using one or more brushes.

I haven't gotten to testing yet, but I expect this system to produce collisions and linepicking several times faster than Blitz3D, even without a BSP tree. For instance, I can calculate sphere-brush intersection, or tell if the sphere is IN the brush (something that is impossible with Blitz's MeshesIntersect()) in less than 1 millisecond:
Function SphereInBrush(brush,x#,y#,z#,radius#)
For f=1 To CountFaces(brush)
	face=getface(brush,f)
	nx#=facenx(face)
	ny#=faceny(face)
	nz#=facenz(face)
	d#=faced(face)	
	If pointplanedistance(x,y,z,nx,ny,nz,d)>radius
		Return False
		EndIf
	Next
Return True
End Function



JoshK(Posted 2003) [#128]
Wooooo!

Blitz3D:
Graphics 400,300,16,2

Include "progs\mouse.bb"

box=CreateCube()

EntityPickMode box,2

start=MilliSecs()
For n=1 To 1000000
	LinePick 10,0,0,-10,0,0
	Next
RuntimeError MilliSecs()-start

Results with 2700 msecs

BlitzPlus+Phobos code:
Include "phobos\phobos.bb"
Include "progs\mouse.bb"
Include "progs\curvevalue.bb"
Include "progs\fps.bb"

brus=createbrush()
d#=-1
addface brus,1,0,0,d
addface brus,-1,0,0,d
addface brus,0,1,0,d
addface brus,0,-1,0,d
addface brus,0,0,1,d
addface brus,0,0,-1,d

compilebrush brus,0

start=MilliSecs()
For n=1 To 1000000
	LineIntersectsBrush brus,10,0,0,-10,0,0
	Next
RuntimeError MilliSecs()-start


Results with 960 msecs.

So Brush-picking is almost 3 times as fast as Blitz3D triangle-picking routines. I tried it with a 16-sided cylinder, to see if the ratio changed with mesh complexity, but it stayed about the same, at 6500 vs. 2300. In both cases, brush picking takes 35% of the time poly-picking did. A BSP tree should push that number down to roughly 5-6%, if we predict a square-root increase in performance.


JoshK(Posted 2003) [#129]
Got BSP trees working! The commands are fairly simple:
;Create a CSG brush
brus=CreateBrush()
AddFace brus,1,0,0,-1
AddFace brus,-1,0,0,-1
AddFace brus,0,1,0,-1
AddFace brus,0,-1,0,-1
AddFace brus,0,0,1,-1
AddFace brus,0,0,-1,-1

;Compile CSG brush into a solid object
CompileBrush brus

;Create a new BSP tree
root=CreateBSPTree()

;Add faces of CSG brush to BSP tree
For f=1 to CountFaces(brus)
face=GetFace(brus,f)
AddBSPNode face,root
Next


The demo clearly shows that the BSP tree is working. Faces that get split along a node are currently deleted, but I can fix that pretty easily. I'm using boxes here, but the routines are written using plane equations, and will work on any CSG brush.




JoshK(Posted 2003) [#130]
It appears that brush:brush collisions are fairly easy, and very fast. This means a solid object can collide with a solid object, without verlets, a.k.a. HL2 physics.


Skitchy(Posted 2003) [#131]
@Halo - just a thought on the file format. Why not just use .b3d? It supports pretty much everything you need, but more importantly there are *already* exporters for the major 3D packages. If you invent your own, then you (or somebody else) will also have to start writing exporters :(


Smurfpuss(Posted 2004) [#132]
well im getting a error on this line QueryObject in the source


ckob(Posted 2004) [#133]
anyone still working on this all the links are dead


xmlspy(Posted 2004) [#134]
halo, if you ever get this 3D OpenGL Engine done, give me a copy, free of charge, thanks.


KimoTech(Posted 2006) [#135]
Leadwerks , where can i get the OpenGL 3D Engine please ?


Andres(Posted 2006) [#136]
You can try bOGL!