Announcement

Collapse
No announcement yet.

Real Flash Quake

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

  • #46
    mg, stop on the first 255. lightstyle 255 means 'no more' rather than 'ignore this one'.
    (this is a slight speedup for the engine, but results in padding that can easily be set randomly)

    be aware that regular surfaces with no lightmap data should be black. unless its water in which case it should be white.

    baker, 32bit clients generally don't use sse. all 64bit processors do support sse, and sse is used as the default floating point unit by compilers targetting that operating mode.
    the x87 fpu supports 80bit long-doubles, and depending on optimisations this can give a different result, even when using single-precision variables (floats can be truncated down to single precision after each operation, but this costs extra cycles).
    conversely the sse fpu uses strict float or double precision.
    or in other words, there will always be some sizes that will fail in at least one engine. the trick is to rescale surfaces slightly to give values outside of an epsilon... the evil hacks lighting tools need to use...
    Some Game Thing

    Comment


    • #47
      thank you both! I'm still digestig some of that but I know I'll find it useful. If I have to use Double I will have to find or write a class. There is no double in flash. Not that I'm aware of. I'm pretty sure I'd be aware.
      http://www.nextgenquake.com

      Comment


      • #48
        Originally posted by MadGypsy View Post
        thank you both! I'm still digestig some of that but I know I'll find it useful. If I have to use Double I will have to find or write a class. There is no double in flash. Not that I'm aware of. I'm pretty sure I'd be aware.
        Flash probably does. Single precision 32 bit floating-point sucks (IMHO).

        Flash might even use 64 bit by default. I mean Javascript and ancient Visual Basic 6 use double-precision for calculations. Double precision dates back to at least the 1990s as common place.

        (But read what Spike said)
        Quakeone.com - Being exactly one-half good and one-half evil has advantages. When a portal opens to the antimatter universe, my opposite is just me with a goatee.

        So while you guys all have to fight your anti-matter counterparts, me and my evil twin will be drinking a beer laughing at you guys ...

        Comment


        • #49
          AS3 Number Is double-precision IEEE 754. I just went to see.

          When I said there was no Double. I meant there is no type named Double. I was unsure what Number actually was.
          Last edited by MadGypsy; 02-20-2016, 10:56 PM.
          http://www.nextgenquake.com

          Comment


          • #50
            Originally posted by MadGypsy View Post
            AS3 Number Is double-precision IEEE 754. I just went to see.
            That's what I would have expected.

            In C, for instance, all the floating point math functions return double like atof (converts string to number) and C promotes single precision float to double for formatted printing (sprintf).

            32-bit floating sucks because for any 32-bit integer X, you cannot necessarily convert it to 32-bit floating point.

            So 32-bit floating point can't store the full range of numbers available in 32-bit integer --- therefore if you need a numeric type that can handle floating point and all possible 32-bit integers you need double precision 64-bit int.

            So single precision float fails as a master numeric data type.

            Which is why, Javascript, for instance uses double and damn near everything else. (Except the Open GL API .... )

            /Probably boring, but from a language design standpoint, if you are going to have one numeric type it sure as hell is going to be double precision floating point --- which is exactly what Javascript does.
            Quakeone.com - Being exactly one-half good and one-half evil has advantages. When a portal opens to the antimatter universe, my opposite is just me with a goatee.

            So while you guys all have to fight your anti-matter counterparts, me and my evil twin will be drinking a beer laughing at you guys ...

            Comment


            • #51
              stop on the first 255 - line 399;
              regular surfaces with no lightmap data should be black - line 380, ternary else
              unless its water in which case it should be white - line 379, ternary then

              There is no doubt these are correct. Where there is doubt is line 378. Should I be determining if it is water using surface_t[n].animated?
              Last edited by MadGypsy; 02-21-2016, 12:07 AM.
              http://www.nextgenquake.com

              Comment


              • #52
                Can some engine developer pretty please point me to the exact classes in any quake source you want where lightmaps, surface extents and uvs are being calculated? It seems like the only way I am ever going to get this part right is with a direct C(x) to AS3 port.

                I cant program in any C's but I can understand it when I read it. All I need are the filenames that contain the data. Approx line numbers would be nice but I can figure it out with or without that.

                Alternately if some engine programmer would like to take a stab at fixing my totally destroyed function, I would be willing to share and owe you one or maybe even just pay you. Want to make 100 bucks writing the guts of my face_t loop? It's actually a bit embarrassing how confused this one method is.

                I think baker would be perfect for this. Obv spike could do it in his sleep. You don't have to program in AS3. Just write some shit that once I AS3 it, it will work. Bonus points ($) for attempting AS3 syntax though.
                Last edited by MadGypsy; 02-22-2016, 01:07 AM.
                http://www.nextgenquake.com

                Comment


                • #53
                  [I did tell you this would be a royal pain, didn't I? Haha ...]

                  Of out my engine (Mark V) source code:


                  Code:
                  /*
                  ================
                  CalcSurfaceExtents
                  
                  Fills in s->texturemins[] and s->extents[]
                  ================
                  */
                  static void CalcSurfaceExtents (msurface_t *s)
                  {
                  	float	mins[2], maxs[2], val;
                  	int		i, j, e;
                  	mvertex_t	*v;
                  	mtexinfo_t	*tex;
                  	int		bmins[2], bmaxs[2];
                  
                  	mins[0] = mins[1] = 999999;
                  	maxs[0] = maxs[1] = -99999;
                  
                  	tex = s->texinfo;
                  
                  	for (i=0 ; i<s->numedges ; i++)
                  	{
                  		e = loadmodel->surfedges[s->firstedge+i];
                  
                  		if (e >= 0)
                  			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
                  		else v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
                  
                  		for (j=0 ; j<2 ; j++)
                  		{
                  #if 1  // Quakespasm, ericw -- for 64-bit
                  			val =   ((double)v->position[0] * (double)tex->vecs[j][0]) +
                  					((double)v->position[1] * (double)tex->vecs[j][1]) +
                  					((double)v->position[2] * (double)tex->vecs[j][2]) +
                  					(double)tex->vecs[j][3];
                  #else
                  			val = v->position[0] * tex->vecs[j][0] +
                  				v->position[1] * tex->vecs[j][1] +
                  				v->position[2] * tex->vecs[j][2] +
                  				tex->vecs[j][3];
                  #endif
                  
                  			if (val < mins[j])
                  				mins[j] = val;
                  
                  			if (val > maxs[j])
                  				maxs[j] = val;
                  		}
                  	}
                  
                  	for (i = 0 ; i < 2 ; i++)
                  	{
                  		bmins[i] = floor(mins[i]/16);
                  		bmaxs[i] = ceil(maxs[i]/16);
                  
                  		s->texturemins[i] = bmins[i] * 16;
                  		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
                  
                  		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > MAX_FITZQUAKE_SURFACE_EXTENTS) //johnfitz -- was 512 in glquake, 256 in winquake
                  			Host_Error ("CalcSurfaceExtents: Bad surface extents %d (MAX: %d), texture is %s.", s->extents[i], MAX_FITZQUAKE_SURFACE_EXTENTS, tex->texture->name);
                  
                  		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > MAX_WINQUAKE_SURFACE_EXTENTS /* 256*/ )
                  			Con_Warning ("%d surface extents exceed standard limit of %d.\n", s->extents[i], MAX_WINQUAKE_SURFACE_EXTENTS);
                  
                  	}
                  
                  	s->smax = (s->extents[0] >> 4) + 1;
                  	s->tmax = (s->extents[1] >> 4) + 1;
                  }
                  (When you see x << 4, that is a bit shift that is the "elite" and "fast" of saying multiply by 16 (2 to 4th power). And by "elite" I mean pointlessly confusing with no performance gain on modern compilers to the best of my knowledge.)

                  Which I guess in old compilers would perform the operation faster. But in most cases, using << or >> instead of multiplication just makes the source code harder to read. Which is probably the case here.)
                  Last edited by Baker; 02-21-2016, 02:49 PM.
                  Quakeone.com - Being exactly one-half good and one-half evil has advantages. When a portal opens to the antimatter universe, my opposite is just me with a goatee.

                  So while you guys all have to fight your anti-matter counterparts, me and my evil twin will be drinking a beer laughing at you guys ...

                  Comment


                  • #54
                    @pain - yeah, but, it's a labor of love, bro. I actually don't feel like it is a "pain" (perse) more of just a challenge. One I am willing to accept though.

                    If I get this to work based on what you posted. I'm still going to tip you. I can never find anything in quake sources. You just saved me time. Probably need to throw spike some bones too before this is all over. There is no reason why you guys should be my very own volunteer engine consultants and I was prepared to maybe have to pay people smarter than I for certain parts anyway.

                    edit: hmmm, my code is already almost identical to yours.
                    http://www.nextgenquake.com

                    Comment


                    • #55
                      OK surface extents is not the problem. Our scripts are so similar it is scary. Where is the UV and Lightmap calculations?

                      edit: check out the only differences between your script and mine

                      mins[n]
                      bounds[mins][n]

                      bmins[n]
                      sbounds[mins][n]

                      same for maxs. In other words I shoved the array in an array.

                      and (999999, -99999) to (1e3, -1e3)

                      I don't have the if/else for 64 bit

                      i don't check extents against specific engines MAXs

                      that is all!
                      Last edited by MadGypsy; 02-21-2016, 03:30 PM.
                      http://www.nextgenquake.com

                      Comment


                      • #56
                        Originally posted by MadGypsy View Post
                        Where is the UV and Lightmap calculations?
                        It's ugly

                        Code:
                        /*
                        ================
                        BuildSurfaceDisplayList -- called at level load time
                        ================
                        */
                        static void BuildSurfaceDisplayList (qmodel_t *curmodel, msurface_t *fa)
                        {
                        	medge_t		*pedges = curmodel->edges;
                        
                        // reconstruct the polygon
                        	int			lnumverts = fa->numedges;
                        	glpoly_t	*poly = (glpoly_t *) Hunk_AllocName (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float), "lm_polys");
                        
                        	medge_t 	*r_pedge;
                        
                        	int			i, lindex;
                        	float		*vec, s, t;
                        	//
                        	// draw texture
                        	//
                        	poly->next = fa->polys;
                        	fa->polys = poly;
                        	poly->numverts = lnumverts;
                        
                        	for (i = 0 ; i < lnumverts ; i++)
                        	{
                        		lindex = curmodel->surfedges[fa->firstedge + i];
                        
                        		if (lindex > 0)
                        		{
                        			r_pedge = &pedges[lindex];
                        			vec = curmodel->vertexes[r_pedge->v[0]].position;
                        		}
                        		else
                        		{
                        			r_pedge = &pedges[-lindex];
                        			vec = curmodel->vertexes[r_pedge->v[1]].position;
                        		}
                        
                        		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
                        		s /= fa->texinfo->texture->width;
                        
                        		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
                        		t /= fa->texinfo->texture->height;
                        
                        		VectorCopy (vec, poly->verts[i]);
                        		poly->verts[i][3] = s;
                        		poly->verts[i][4] = t;
                        
                        		//
                        		// lightmap texture coordinates
                        		//
                        		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
                        		s -= fa->texturemins[0];
                        		s += fa->light_s * 16;
                        		s += 8;
                        		s /= LIGHTMAPS_BLOCK_WIDTH * 16; //fa->texinfo->texture->width;
                        
                        		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
                        		t -= fa->texturemins[1];
                        		t += fa->light_t*16;
                        		t += 8;
                        		t /= LIGHTMAPS_BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
                        
                        		poly->verts[i][5] = s;
                        		poly->verts[i][6] = t;
                        	}
                        
                        	poly->numverts = lnumverts;
                        }
                        Where

                        #define LIGHTMAPS_BLOCK_WIDTH 128 (i.e. lightmaps_block_width = 128 )
                        #define LIGHTMAPS_BLOCK_HEIGHT 128

                        See the // lightmap texture coordinates in the block
                        Last edited by Baker; 02-21-2016, 03:51 PM.
                        Quakeone.com - Being exactly one-half good and one-half evil has advantages. When a portal opens to the antimatter universe, my opposite is just me with a goatee.

                        So while you guys all have to fight your anti-matter counterparts, me and my evil twin will be drinking a beer laughing at you guys ...

                        Comment


                        • #57
                          What sucks is that each lightmap is allocated onto a big block texture, and there usually are multiple big block textures.

                          Code:
                          /*
                          ========================
                          AllocBlock -- returns a texture number and the position inside it
                          ========================
                          */
                          
                          static int AllocBlock (int w, int h, int *x, int *y)
                          {
                          	int		i, j;
                          	int		best, best2;
                          	int		texnum;
                          
                          //	for (texnum=0 ; texnum<MAX_FITZQUAKE_LIGHTMAPS ; texnum++)
                          	for (texnum = last_lightmap_allocated ; texnum < MAX_FITZQUAKE_LIGHTMAPS ; texnum++, last_lightmap_allocated++) // Quakespasm / ericw
                          	{
                          		best = LIGHTMAPS_BLOCK_HEIGHT;
                          
                          		for (i=0 ; i<LIGHTMAPS_BLOCK_WIDTH-w ; i++)
                          		{
                          			best2 = 0;
                          
                          			for (j=0 ; j<w ; j++)
                          			{
                          				if (lightmap[texnum].allocated[i+j] >= best)
                          					break;
                          				if (lightmap[texnum].allocated[i+j] > best2)
                          					best2 = lightmap[texnum].allocated[i+j];
                          			}
                          			if (j == w)
                          			{	// this is a valid spot
                          				*x = i;
                          				*y = best = best2;
                          			}
                          		}
                          
                          		if (best + h > LIGHTMAPS_BLOCK_HEIGHT)
                          			continue;
                          
                          		for (i=0 ; i<w ; i++)
                          			lightmap[texnum].allocated[*x + i] = best + h;
                          
                          		return texnum;
                          	}
                          
                          	Host_Error ("AllocBlock: full");
                          	return 0;
                          }
                          The x and y are the coordinates within the block texture. I would assume you are just handling each lightmap as a separate texture (?).

                          (You probably should just create an image for each lightmap to keep your sanity.)
                          Quakeone.com - Being exactly one-half good and one-half evil has advantages. When a portal opens to the antimatter universe, my opposite is just me with a goatee.

                          So while you guys all have to fight your anti-matter counterparts, me and my evil twin will be drinking a beer laughing at you guys ...

                          Comment


                          • #58
                            I'm just reading what you posted and I will be on that right after I post this.

                            My calcSurfExtents method didn't actually exist. The guts of said function was directly inside of my face construction loop. I moved it to it's own method. I went over your code and made sure that I was doing all of the exact same stuff. My solution is a bit different in expression. You should check it out, right below. It's been considered heavily.



                            PS> in AS3 a Vector is just a dense array with basetyped indexes. In other words its [n's] always have to be <someExactSameType> and you can't skip around adding values to length that doesn't even exist. You can manipulate as high as vector[vector.length] ...creating a new vector.length. Since I didn't use new in the return I'm actually casting the return as Vector.<Number> and it does not get allocated.
                            Last edited by MadGypsy; 02-21-2016, 05:41 PM.
                            http://www.nextgenquake.com

                            Comment


                            • #59
                              what does position return?
                              vec = curmodel->vertexes[r_pedge->v[0]].position;

                              I'm assuming vertexes is vertex_t[ edge_t[lstedge].vertex0 ]

                              there is no ".position". Well, I don't have that and don't see where it is created, anyway.

                              aside:

                              I completely crushed calc_surf_exts down to be as direct as possible. It's allocating probably 60 or more percent less. Considering a map like e1m1 its allocating "60%" less over 5000 times. I think my (b)mins/maxs solution is clever.
                              Last edited by MadGypsy; 02-21-2016, 07:25 PM.
                              http://www.nextgenquake.com

                              Comment


                              • #60
                                Originally posted by MadGypsy View Post
                                what does position return?
                                vec = curmodel->vertexes[r_pedge->v[0]].position;
                                It's a vector3 (i..e x, y, z)

                                model.h
                                typedef struct
                                {
                                vec3_t position;
                                } mvertex_t;


                                The engine loads Vertexes from the .bsp as such from Mod_LoadBrushModel --> Mod_LoadVertexes --> allocates vertexes

                                Code:
                                /*
                                =================
                                Mod_LoadVertexes
                                =================
                                */
                                static void Mod_LoadVertexes (lump_t *l)
                                {
                                	dvertex_t	*in;
                                	mvertex_t	*out;
                                	int			i, count;
                                
                                	in = (dvertex_t *)(mod_base + l->fileofs);
                                	if (l->filelen % sizeof(*in))
                                		Host_Error ("Mod_LoadVertexes: funny lump size in %s",loadmodel->name);
                                
                                	count = l->filelen / sizeof(*in);
                                
                                	out = (mvertex_t *)Hunk_AllocName ( count*sizeof(*out), loadname);
                                
                                
                                	loadmodel->vertexes = out;
                                	loadmodel->numvertexes = count;
                                
                                	for ( i=0 ; i<count ; i++, in++, out++)
                                	{
                                		out->position[0] = LittleFloat (in->point[0]);
                                		out->position[1] = LittleFloat (in->point[1]);
                                		out->position[2] = LittleFloat (in->point[2]);
                                	}
                                }
                                Where you see "LittleFloat" ignore it. That's for little-endian vs. big endian, when compiling for little endian (basically everything is Intel these days, basically nothing is RISC or another Big Endian platform any more).

                                On a Little Endian (like Intel), the LittleFloat macro is just like a function that returns the same value it was passed. On Big Endian, the macro would rearrange the bytes and then evaluate it.
                                Quakeone.com - Being exactly one-half good and one-half evil has advantages. When a portal opens to the antimatter universe, my opposite is just me with a goatee.

                                So while you guys all have to fight your anti-matter counterparts, me and my evil twin will be drinking a beer laughing at you guys ...

                                Comment

                                Working...
                                X