Announcement

Collapse
No announcement yet.

Real Flash Quake

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spike
    replied
    Adam, check my sig if you want quake on the web. strip out bits of the uri for more demonstrations, you should be able to work it out.
    I don't expect MG will want to support full quake mods, only maps and maybe models.

    mg, skip the mips. you only really care about the first image. your rendering api should provide a way to generate the entire mipchain automatically anyway, and there's a load of maps with dodgy mips anyway.

    Leave a comment:


  • MadGypsy
    replied
    A browser version could easily be made.

    I finished miptex parse entirely. It parses all of the miptexes and attempts to directly use the bytes wherever possible. It's very fast.

    Images are nicer than copy/paste code boxes. Here is my method.

    Leave a comment:


  • Adam
    replied
    I was wondering if it will work with mods like, for example Hazard?
    It would be great for me to be able to put a demo version on my itch.io page that could be played there & then in a browser.
    Is that sort of thing possible with what you are proposing?

    Leave a comment:


  • MadGypsy
    replied
    I wanted to test my idea of ignoring all structs and parsing the map out of the BSP using math directly on the bytes. In other words, no vars, references, nothing. I rewrote my miptex parser to try this.

    I feel like my code is really clear except for 2 things:
    _lumps is a Vector (compact array) of bytes with each index representing a lump. MIPTEX = 2, which is the index number for the bytes that correspond with the miptex lump. The rest is easy enough to figure out now that you know _lumps[MIPTEX] are all of the original bytes from the miptex lump in the BSP. I'm only getting offset1 right now. I'll get the other mips after I make sure that I like this way.

    Code:
    public function get materials():Vector.<BitmapData> {
    	if (!_mips.length)
    	{	
    		_lumps[MIPTEX].position = 0;
    		
    		var _ofs:Vector.<int> = new Vector.<int>();
    
    		var i:int =_lumps[MIPTEX].readInt();
    		var n:int = 0;
    		
    		while(n < i)
    		{	_ofs[n] = _lumps[MIPTEX].readInt();
    			++n;
    		}
    		
    		n = 0;
    		while (n < _ofs.length)
    		{	_lumps[MIPTEX].position = _ofs[n];
    			_mip_names[n] = readString(_lumps[MIPTEX], 16);
    			_mips[n] = new BitmapData(_lumps[MIPTEX].readUnsignedInt(), _lumps[MIPTEX].readUnsignedInt(), true, 0xff000000);
    			
    			
    			_lumps[MIPTEX].position = _lumps[MIPTEX].readUnsignedInt()+_ofs[n];
    		
    			
    			for (var y:int = 0; y < _mips[n].height; ++y)
    			{
    				for (var x:int = 0; x < _mips[n].width; ++x)
    				{
    					var pal:Array = QuakePalette.rgb[uint(_lumps[MIPTEX].readUnsignedByte())];
    					_mips[n].setPixel(x, y, uint(pal[0] << 16 | pal[1] << 8 | pal[2]));
    				}
    			}
    			++n;
    		}
    		
    	} 
    	return _mips;
    	
    }
    This method works. I have it set to cycle through mips displaying it's contents on every mouse click and the display is perfect. Not one fucked up texture.
    Last edited by MadGypsy; 02-11-2016, 10:41 PM.

    Leave a comment:


  • MadGypsy
    replied
    Actually @spike, I just remembered a question I wanted to ask you.

    When I get to the part of constructing the miptexes, I was considering creating a Worker so parsing the BSP can continue while the images are being made. My concern is mobile devices (my main focus) will just be trading the time to construct images with the overhead of a Worker and recieve no benefit.

    What do you think about this?

    Leave a comment:


  • MadGypsy
    replied
    65536 verts per buffer... just checked but, I found a stress test running 15,000,000 polys at 60fps. The buffer is small but apparently using multiple buffers can still create some amazing results.

    Leave a comment:


  • Spike
    replied
    considering how inefficient flash is, I'd suggest just throwing the entire map into a single trisoup buffer (or at least one buffer per texture) and just using that.
    you might need to be prepared to split it more than that if your api is shitty and doesn't support more than 65k verts, depends on the map...
    hurrah for modern gpus, throw everything at it and see what sticks!

    Leave a comment:


  • MadGypsy
    replied
    I'm letting some thoughts stew so, I'm gonna ramble about what I am actually doing. First of all, this is not going to be a Quake engine. We have like 500 Quake engines, there is no point in me building another one. My engine may see a day where it is Quake capable though.

    I came here like 5 years ago because google told me this is where to go if I want to learn how to build a 3D FPS. I know the quake 1 version of building a game pretty much inside and out. The one thing that has always been a mystery to me is the engine. Aside from user end controls and options, engines have always been a black box, to me. I still want to build a game. I still want to build the same damn game that I wanted to build 5 years ago. Before I build my game, I need to build my engine. I want direct and absolute control and knowledge of my entire "product"... not just the game.

    I have brought that decision even down to NOT using 3rd party engine API's. I could walk these faces right now into subgeometry (incl textures and uvs), push them into geometry and dump that to a mesh that gets sent to the Away3D scene. I know I could do this, right now... with success. That defeats the purpose of knowing every iota of the code. I'm going to go all the way down to the GPU and build my way up.

    One way my engine will differ from a quake engine is, I am not porting a damn thing. I understand the various problems I need to solve and I'm gonna write my own code to solve them. Even the BSP parser I just wrote will probably get rewritten in a far less verbose and far more direct way. Like, probably forget even assigning vars and do the math straight out of the BSP readInt()*readInt() so to speak. That's the great thing about BSP. All I need is a base number (ie the byte offset of a lump) and I can predict every spot the number I need will appear in. I have no idea if performing the math directly from bytes to bytes and only saving the results I need is smart or faster or better but, I'm probably going to find out. Flash expects vertexes in the order they need to be connected as Vector.<Number>[x,y,z,r,g,b,x,y,z,r,g,b,x,y,z,r,g,b,.......]. Maybe I could write a formula that spits the whole world out like that without allocating a bunch of memory on all these vars. You could say instead of parsing the BSP I would be attacking it for the bottom line.

    IDK..it's all dynamic right now. I'm building an engine that supports things I understand which are supported by tools that I understand. I know how to map in radiant and compile with modern tools to BSP. My engine should support BSP.
    Last edited by MadGypsy; 02-11-2016, 12:29 AM.

    Leave a comment:


  • MadGypsy
    replied
    Thinking out loud...
    Code:
    n = 0;
    while(n < leaf.lface_num)
    {	
    	offset = lfaces[leaf.lface_id];
    	currFace = faces[model[0].face_id + offset];	//kinna dumb if face_id is always the same number & it's zero
    	id = currFace.texinfo_id;
    	
    	j = 0;
    	while (j < currFace.ledge_num)
    	{
    		
    		e = ledges[currFace.ledge_id + j];		//surf->surfedge
    		if (e > -1)
    		{
    			edge = edges[e];			//surfedge->edge
    			vert = vertices[edge.vertex0];		//edge->vertices
    		} else {
    			edge = edges[-e];
    			vert = vertices[edge.vertex1];		//reverse if negative
    		}
    	
    		s = dotproduct(vert, texinfo[id].vectorS) + texinfo[id].distS;
    		t = dotproduct(vert, texinfo[id].vectorT) + texinfo[id].distT;
    
    		++j;
    	}
    	++n;
    }
    Storing this here so I can get to it easy from any device. Having a "struct reference" is helping me visualize how this all goes together.
    Code:
    BSP HEADER
    
    BSP version: 29
    -DHeader_T
    {
    	_entities->DEntry_T[0]:
    	{
    		position:4
    		offset:794724,
    		length:26284,
    		index:0
    	},
    	_planes->DEntry_T[1]:
    	{
    		position:12
    		offset:124,
    		length:36200,
    		index:1
    	},
    	_miptex->DEntry_T[2]:
    	{
    		position:20
    		offset:821008,
    		length:544168,
    		index:2
    	},
    	_vertices->DEntry_T[3]:
    	{
    		position:28
    		offset:79192,
    		length:88296,
    		index:3
    	}
    
    
    PLANES LUMP
    
    -PlaneLump_T:{count:1810}
    -Plane_T[0]:
    {	position:124,
    	normal->Vec3_T:{x:0, y:1, z:0},
    	dist:-64,
    	type:1
    }
    -Plane_T[1]:
    {	position:144,
    	normal->Vec3_T:{x:0, y:1, z:0},
    	dist:3064,
    	type:1
    }
    
    
    MIPS LUMP
    
    -MipLump_T:{count:81}
    	offset[0]:328,
    	offset[1]:1728,
    	offset[2]:7208,
    	offset[3]:7588,
    	offset[4]:7968,
    	offset[5]:13448,
    	offset[6]:35248,
    	offset[7]:38008,
    	offset[8]:40768,
    	offset[9]:46248,
    	offset[10]:51728
    
    
    SURFACE LUMP
    
    -SurfaceLump_T{count:489}
    -Surface_T[0]:
    {	position:233488,
    	vectorS->:Vec3_T:{x:0, y:0, z:-1},
    	vectorT->Vec3_T:{x:0, y:1, z:0},
    	distS:0,
    	distT:0,
    	texture_id:0,
    	animated:0
    }
    
    
    VERTEX LUMP
    
    -VertexLump_T:{count:7358}
    Vertex_T[0]:
    {	position:79192,
    	{x:408, y:-64, z:128}
    }
    Vertex_T[1]:
    {	position:79204,
    	{x:408, y:-64, z:192}
    }
    Vertex_T[2]:
    {	position:79216,
    	{x:384, y:-64, z:192}
    }
    
    
    FACES LUMP
    
    -FaceLump_T:{count:5516}
    -Face_T[0]:
    {	position:253048,
    	plane_id:0,
    	side:0,
    	ledge_id:0,
    	ledge_num:6,
    	texinfo_id:13,
    	lightmap_styles:[0,255,255,255],
    	lightmap_offset:152
    }
    
    
    EDGES LUMP
    
    -EdgeLump_T:{count:13497}
    -Edge_T[0]:
    {	position:527588,
    	vertex0:0,
    	vertex1:0
    }
    -Edge_T[1]:
    {	position:527592,
    	vertex0:0,
    	vertex1:1
    }
    -Edge_T[2]:
    {	position:527596,
    	vertex0:1,
    	vertex1:2
    }
    	
    
    
    VIS LUMP
    
    -VisLump_T:{count:40843}
    	vislist[0]:13
    	vislist[1]:48
    	vislist[2]:32
    	vislist[3]:-20
    	vislist[4]:-10
    	vislist[5]:-29
    	vislist[6]:7
    	vislist[7]:-26
    	vislist[8]:-123
    	vislist[9]:0
    	vislist[10]:1
    
    
    NODES LUMP
    
    -NodeLump_T:{count:2750}
    -Node_T[0]:
    {	position:167488,
    	plane_id:0,
    	front:1,
    	back:2301,
    	box:BBoxShort_T:{
    		min:[-632,-456,-632],
    		max:[1544,3096,312]
    	},
    	face_id:0,
    	face_num:6
    }
    
    
    MODELS LUMP
    
    -ModelLump_T:{count:58}
    -Model_T[0]:
    {	position:581576,
    	bounds->:BoundBox_T:{
    		min->:Vec3_T:{x:-607, y:-431, z:-607},
    		max->:Vec3_T:{x:1519, y:3071, z:287}
    	},
    	origin->:Vec3_T:{x:0, y:0, z:0},
    	node_id:[0, 0, 2970, 0],
    	numleafs:1148,
    	face_id:0,
    	face_num:5059
    }
    
    
    CLIPNODES LUMP
    
    -ClipNodesLump_T:{count:5408}
    -ClipNode_T[0]:
    {	position:363368,
    	planenum: 568,
    	children:[1, 1606]
    }
    -ClipNode_T[1]:
    {	position:363376,
    	planenum: 204,
    	children:[2, 615]
    }
    
    
    MARKSURFACE LUMP
    
    -MarkSurfaceLump_T:{count:14146}
    	lface[0]:98
    	lface[1]:99
    	lface[2]:100
    	lface[3]:104
    	lface[4]:103
    	lface[5]:102
    	lface[6]:94
    	lface[7]:93
    	lface[8]:92
    	lface[9]:91
    	lface[10]:6
    
    
    LEAFS LUMP
    
    -LeafLump_T:{count:1531}
    -Leaf_T[0]:
    {	position:36324,
    	type:-2,
    	vislist:0,
    	bound->:BBoxShort_T:{
    		min:[0,0,0],
    		max:[0,0,0]
    	},
    	lface_id:0,
    	lface_num:0,
    	ambient:[0, 0, 0, 0]
    }
    -Leaf_T[1]:
    {	position:36352,
    	type:-1,
    	vislist:0,
    	bound->:BBoxShort_T:{
    		min:[144,3024,-16],
    		max:[176,3064,16]
    	},
    	lface_id:0,
    	lface_num:15,
    	ambient:[4294967295, 4294967295, 0, 0]
    }
    
    
    ENTITIES LUMP
    
    -EntitiesLump_T:{count:26284}
    {
    "worldtype" "2"
    "sounds" "6"
    "classname" "worldspawn"
    "wad" "gfx/base.wad"
    "message" "the Slipgate Complex"
    }
    {
    "classname" "info_player_start"
    "origin" "480 -352 88"
    "angle" "90"
    }
    {
    "classname" "light"
    "origin" "480 96 168"
    "light" "250"
    }
    {
    "classname" "light"
    "origin" "480 288 168"
    "light" "250"
    }
    {
    "classname" "light"
    "origin" "272 96 80"
    }
    {
    "origin" "272 288 80"
    "classname" "light"
    }
    {
    "classname" "light"
    "origin" "272 192 80"
    }
    {
    "origin" "688 192 80"
    "classname" "light_fluorospark"
    "style" "10"
    }
    
    
    SURFEDGES LUMP
    
    -SurfEdgeLump_T:{count:26702}
    	ledge[0]:1
    	ledge[1]:2
    	ledge[2]:3
    	ledge[3]:4
    	ledge[4]:5
    	ledge[5]:6
    	ledge[6]:7
    	ledge[7]:8
    	ledge[8]:-1
    	ledge[9]:9
    	ledge[10]:10
    
    
    LIGHTMAPS LUMP
    
    -LightmapLump_T:{count:168590}
    	light[0]:69
    	light[1]:79
    	light[2]:89
    	light[3]:77
    	light[4]:86
    	light[5]:95
    	light[6]:84
    	light[7]:91
    	light[8]:98
    	light[9]:0
    	light[10]:0
    Last edited by MadGypsy; 02-10-2016, 11:35 PM.

    Leave a comment:


  • Spike
    replied
    you should also have some faces[n].ledge_count variable too, which says how many surfedges there are for that surface, and thus how many verticies you should have.
    otherwise yes, I think you're calculating the right vert[x,y,z], s, and t values for the first vertex of each surface.

    Leave a comment:


  • MadGypsy
    replied
    I can't test my script til I come from the other end in my code and create a renderer to plug the BSP into. That being said I will just ask you if this looks like I understood what you said.

    Code:
    while(n < faces.length)
    {	
    	e = ledges[faces[n].ledge_id];			//surf->surfedge
    	if (e > -1)
    	{
    		edge = edges[e];			//surfedge->edge
    		vert = vertices[edge.vertex0];		//edge->vertices
    	}
    	else
    	{
    		edge = edges[-e];
    		vert = vertices[edge.vertex1];		//reverse if negative
    	}
    	
    	id = faces[n].texinfo_id;
    	
    	s = dotproduct(vert, texinfo[id].vectorS) + texinfo[id].distS;
    	t = dotproduct(vert, texinfo[id].vectorT) + texinfo[id].distT;
    	
    	++n;
    }
    I realize the product of the loop is nothing (atm). My question is just whether my method describes what you said. I haven't touched the lightmap part yet.
    Last edited by MadGypsy; 02-10-2016, 02:54 AM.

    Leave a comment:


  • Spike
    replied
    surf->surfedges->edges->vertex.
    if the surfedge value is negative, then the edge is backwards and you should flip the two verts.
    by just walking the edges of each face you can construct the polygon that way.

    texture coords depend upon the texinfo. v.s = dotproduct(3dposition, texinfo->vecs[0])+texinfo->vecs[0][3]; v.t = dotproduct(3dposition, texinfo->vecs[1])+texinfo->vecs[1][3];

    lightmap size is determined from the texture coords. divide by 16 to get the size, the lightmap data will be aligned with the smallest point. you'll need to atlas stuff yourself. beware precision.

    Leave a comment:


  • MadGypsy
    replied


    The above shot is just to show I am serious. The main text on the page is a log dump of the models lump for e1m1 (I can do this to any/all lumps). The viewer is proving I can get the miptexs properly. The file list on the right is my complete rewrite of all the BSP structs (except the leaf lump which I am doing right this minute).


    This was already a whole lot of work. I WILL get BSPs to render. Hopefully sooner than later.
    Last edited by MadGypsy; 02-09-2016, 02:01 PM.

    Leave a comment:

Working...
X