Exemple #1
0
/*
===========
Vis_Main
===========
*/
int Vis_Main( int argc, char **argv )
{
    int			i;
    double		start, end;

    printf ("---- vis ----\n");

    fastvis = false;
    verbose = false;
    rvis = true;
    noambientslime = true;
    noreuse = false;
    farplane = 0;

    if (ismcbsp)
        noambient = true;

    for (i=1 ; i<argc ; i++)
    {
        if (!strcmp(argv[i], "-norvis"))
        {
            rvis = false;
            printf ("rvis optimization disabled\n");
        }
        else if (!strcmp(argv[i], "-fast"))
        {
            printf ("fastvis = true\n");
            fastvis = true;
        }
        else if (!strcmp(argv[i], "-level"))
        {
            testlevel = atoi(argv[i+1]);
            printf ("testlevel = %i\n", testlevel);
            i++;
        }
        else if (!strcmp(argv[i], "-v"))
        {
            printf ("verbose = true\n");
            verbose = true;
        }
        else if (!strcmp(argv[i], "-noreuse"))
        {
            printf ("vis rows reusage disabled\n");
            noreuse = true;
        }
        else if (!strcmp(argv[i], "-noambient"))
        {
            noambient = true;
            printf ("all ambient sounds disabled\n");
        }
        else if (!strcmp(argv[i], "-noambientwater"))
        {
            noambientwater = true;
            printf ("ambient water sounds disabled\n");
        }
        else if (!strcmp(argv[i], "-ambientslime"))
        {
            noambientslime = false;
            printf ("ambient slime sounds enabled\n");
        }
        else if (!strcmp(argv[i], "-noambientlava"))
        {
            noambientlava = true;
            printf ("ambient lava sounds disabled\n");
        }
        else if (!strcmp(argv[i], "-noambientsky"))
        {
            noambientsky = true;
            printf ("ambient sky sounds disabled\n");
        }
        else if (!strcmp(argv[i], "-farplane"))
        {
            farplane = atoi (argv[i+1]);
            printf ("farplane = %f\n", farplane);
            i++;
        }
        else if (argv[i][0] == '-')
            Error ("Unknown option \"%s\"", argv[i]);
        else
            break;
    }

    if (i != argc - 1)
    {
        Error ("%s",
               "usage: hmap2 -vis [options] bspfile\n"
               "Compiles visibility data in a .bsp, needs a .prt file\n"
               "\n"
               "What the options do:\n"
               "-level 0-4      quality, default 4\n"
               "-fast           fast but bad quality vis\n"
               "-v              verbose\n"
               "-norvis         disable rvis optimization, 0.001% better quality and 30% slower\n"
               "-ambientslime   do not convert slime channel to water (requires engine support)\n"
               "-noambient      disable ambient sounds (water bubbling, wind, etc)\n"
               "-noambientwater disable ambient water sounds (water)\n"
               "-noambientslime disable ambient slime sounds (water, or -ambientslime)\n"
               "-noambientlava  disable ambient lava sounds (unused by quake)\n"
               "-noambientsky   disable ambient sky sounds (wind)\n"
               "-noreuse        disable merging of identical vis data (less compression)\n"
               "-farplane       limit visible distance (warning: not a good idea without fog)\n"
              );
    }

    // init memory
    Q_InitMem ();

    start = I_DoubleTime ();

    LoadBSPFile (filename_bsp);
    LoadPortals (filename_prt);

    uncompressed = qmalloc(bitlongs*portalleafs*sizeof(long));
    memset (uncompressed, 0, bitlongs*portalleafs*sizeof(long));

//	CalcPassages ();

    CalcVis ();

    printf ("row size: %i\n",bitbytes);
    printf ("c_reused: %i\n",c_reused);
    printf ("c_chains: %i\n",c_chains);

    visdatasize = vismap_p - dvisdata;
    printf ("reused bytes: %i\n",c_reused*bitbytes);
    printf ("visdatasize:%i compressed from %i\n", visdatasize, originalvismapsize);

    if (!noambient)
        CalcAmbientSounds ();

    WriteBSPFile (filename_bsp, false);

//	unlink (portalfile);

    end = I_DoubleTime ();
    printf ("%5.2f seconds elapsed\n\n", end-start);

    // print memory stats
    Q_PrintMem ();

    // free allocated memory
    Q_ShutdownMem ();

    return 0;
}
Exemple #2
0
/*---------------------------------------------------------------------------*/
int 
parse_select_query(qmessage_header_t * qm_header)
{
  int size;
  int i;
  char parsing_failed;
  smessage_header_t * smsg_header;
  squery_data_t * squery_data;
  field_t * field;
  field_data_t * field_data, * fd_tmp;
  expression_t * expr;
  expression_data_t * expr_data; 
  qtable_entry_t * qtable_entry;
  
  smsg_header = (smessage_header_t *)(qm_header + 1);
 
  /* Check whether a query with same id and same query root exists. */
  if(get_query_entry(qm_header->qid, &qm_header->qroot)) {
    PRINTF("[DEBUG]: A Query exists with the same id and same root.\n");
    return -1;
  }

  /* the memory size needed to be allocated. */
  parsing_failed = FALSE;
  size = sizeof(squery_data_t) + 
         (smsg_header->nfields * sizeof(field_data_t)) + 
         (smsg_header->nexprs * sizeof(expression_data_t));

  /* Allocate memory for the SELECT query. */
  squery_data = (squery_data_t *)qmalloc(size);
  if(squery_data == NULL) {
    PRINTF("[DEBUG]: Can not allocate memory. query_id %d\n", qm_header->qid);
    return -1;
  }
  /* set SELECT query header infomations. */
  squery_data->qid = qm_header->qid;
  squery_data->nfields = smsg_header->nfields;
  squery_data->nexprs = smsg_header->nexprs;
  squery_data->in_buffer_id = smsg_header->in_buffer;
  squery_data->out_buffer_id = smsg_header->out_buffer;

  memcpy(&squery_data->epoch_duration, &smsg_header->epoch_duration, 
                                                           sizeof(nw_uint16_t));
  memcpy(&squery_data->nepochs, &smsg_header->nepochs, sizeof(nw_uint16_t));
  memset(&squery_data->current_epoch, 0, sizeof(nw_uint16_t));

  
  /* store field data. */
  field = (field_t *)(smsg_header + 1);
  field_data = (field_data_t *)(squery_data + 1);
  for(i=0; i<squery_data->nfields; i++, field++, field_data++) {
    field_data->id = field->id;
    field_data->in_result = field->in_result; 
    field_data->op = field->op;
    /* fill data value with zero */
    memset(&field_data->data, 0, sizeof(attr_data_t));

  }

  /* store expressions */
  expr = (expression_t *)(field);
  expr_data = (expression_data_t *)(field_data);
  
  for(i=0; i<squery_data->nexprs; i++, expr++, expr_data++) {
    fd_tmp = ((field_data_t *)(squery_data + 1)) + expr->l_value_index;
    if(!get_attr_entry(fd_tmp->id)) {
      parsing_failed = TRUE;
      PRINTF("[DEBUG]: Error! Found unsupported attribute. attribute_id %d\n", 
                                                                    fd_tmp->id);
      break;
    }
    expr_data->l_valuep = fd_tmp;
    expr_data->op = expr->op;
    /* copy right value data */
    memcpy(expr_data->r_value.data_bytes, expr->r_value.data_bytes, 
                                                               ATTR_DATA_SIZE);
  }

  if(parsing_failed) {
    qfree(squery_data);
    PRINTF("[DEBUG]: Parsing SELECT query failed. query_id %d\n", qm_header->qid);
    return -1;
  }
  print_squery(squery_data);
  qtable_entry = add_query_entry(squery_data->qid, QTYPE_SELECT,  
                                                   squery_data, 
                                                   &qm_header->qroot);
  if(!qtable_entry) {
    qfree(squery_data);
    PRINTF("[DEBUG]: Error adding to query table. query_id %d\n", qm_header->qid);
    return -1;
  }


  ctimer_set(&squery_data->timer, 
             CLOCK_SECOND * ntoh_leuint16(&squery_data->epoch_duration), 
             execute_select_query, qtable_entry);

  return 0;
}
Exemple #3
0
sep_t *Findpassages (viswinding_t *source, viswinding_t *pass)
{
    int			i, j, k, l;
    plane_t		plane;
    vec3_t		v1, v2;
    double		d;
    double		length;
    int			counts[3];
    qboolean	fliptest;
    sep_t		*sep, *list;

    list = NULL;

    // hush warnings about uninitialized plane.type (which isn't used here)
    memset(&plane, 0, sizeof(plane));


// check all combinations
    for (i=0 ; i<source->numpoints ; i++)
    {
        l = (i+1)%source->numpoints;
        VectorSubtract (source->points[l] , source->points[i], v1);

        // fing a vertex of pass that makes a plane that puts all of the
        // vertexes of pass on the front side and all of the vertexes of
        // source on the back side
        for (j=0 ; j<pass->numpoints ; j++)
        {
            VectorSubtract (pass->points[j], source->points[i], v2);
            CrossProduct(v1, v2, plane.normal);

            // if points don't make a valid plane, skip it
            length = DotProduct( plane.normal, plane.normal );

            if (length < ON_EPSILON)
                continue;

            length = 1/sqrt(length);
            VectorScale( plane.normal, length, plane.normal );
            plane.dist = DotProduct (pass->points[j], plane.normal);

            //
            // find out which side of the generated seperating plane has the
            // source portal
            //
            fliptest = false;
            for (k=0 ; k<source->numpoints ; k++)
            {
                if (k == i || k == l)
                    continue;
                d = DotProduct (source->points[k], plane.normal) - plane.dist;
                if (d < -ON_EPSILON)
                {   // source is on the negative side, so we want all
                    // pass and target on the positive side
                    fliptest = false;
                    break;
                }
                else if (d > ON_EPSILON)
                {   // source is on the positive side, so we want all
                    // pass and target on the negative side
                    fliptest = true;
                    break;
                }
            }
            if (k == source->numpoints)
                continue;		// planar with source portal

            //
            // flip the normal if the source portal is backwards
            //
            if (fliptest)
            {
                VectorNegate (plane.normal, plane.normal);
                plane.dist = -plane.dist;
            }

            //
            // if all of the pass portal points are now on the positive side,
            // this is the seperating plane
            //
            counts[0] = counts[1] = counts[2] = 0;
            for (k=0 ; k<pass->numpoints ; k++)
            {
                if (k==j)
                    continue;
                d = DotProduct (pass->points[k], plane.normal) - plane.dist;
                if (d < -ON_EPSILON)
                    break;
                else if (d > ON_EPSILON)
                    counts[0]++;
                else
                    counts[2]++;
            }
            if (k != pass->numpoints)
                continue;	// points on negative side, not a seperating plane

            if (!counts[0])
                continue;	// planar with pass portal

            //
            // save this out
            //
            count_sep++;

            sep = qmalloc(sizeof(*sep));
            sep->next = list;
            list = sep;
            sep->plane = plane;
        }
    }

    return list;
}
Exemple #4
0
/*
============
LoadPortals
============
*/
void LoadPortals (char *name)
{
    int			i, j;
    portal_t	*p;
    leaf_t		*l;
    char		magic[80];
    FILE		*f;
    int			numpoints;
    viswinding_t *w;
    int			leafnums[2];
    plane_t		plane;
    vec3_t		origin;
    vec_t		radius;

    if (!strcmp(name,"-"))
        f = stdin;
    else
    {
        f = fopen(name, "r");
        if (!f)
            Error ("LoadPortals: couldn't read %s\n",name);
    }

    if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalleafs, &numportals) != 3)
        Error ("LoadPortals: failed to read header");
    if (strcmp(magic,PORTALFILE))
        Error ("LoadPortals: not a portal file");

    printf ("%4i portalleafs\n", portalleafs);
    printf ("%4i numportals\n", numportals);

    bitbytes = (portalleafs+7)>>3;
    bitlongs = (portalleafs+(8*sizeof(long)-1))/(8*sizeof(long));

// each file portal is split into two memory portals
    portals = qmalloc(2*numportals*sizeof(portal_t));
    memset (portals, 0, 2*numportals*sizeof(portal_t));

    leafs = qmalloc(portalleafs*sizeof(leaf_t));
    memset (leafs, 0, portalleafs*sizeof(leaf_t));

    originalvismapsize = portalleafs*((portalleafs+7)/8);

    vismap = vismap_p = dvisdata;
    vismap_end = vismap + MAX_MAP_VISIBILITY;

    for (i=0, p=portals ; i<numportals ; i++)
    {
        if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1])
                != 3)
            Error ("LoadPortals: reading portal %i", i);
        if (numpoints > MAX_POINTS_ON_VISWINDING)
            Error ("LoadPortals: portal %i has too many points", i);
        if ((unsigned)leafnums[0] > (unsigned)portalleafs
                || (unsigned)leafnums[1] > (unsigned)portalleafs)
            Error ("LoadPortals: reading portal %i", i);

        w = p->winding = NewVisWinding (numpoints);
        w->original = true;
        w->numpoints = numpoints;

        for (j=0 ; j<numpoints ; j++)
        {
            double	v[3];
            int		k;

            // scanf into double, then assign to vec_t
            if (fscanf (f, "(%lf %lf %lf ) ", &v[0], &v[1], &v[2]) != 3)
                Error ("LoadPortals: reading portal %i", i);
            for (k=0 ; k<3 ; k++)
                w->points[j][k] = v[k];
        }
        fscanf (f, "\n");

        // calc plane
        PlaneFromVisWinding (w, &plane);

        // calc origin and radius
        VisWindingCentre (w, origin, &radius);

        // create forward portal
        l = &leafs[leafnums[0]];
        if (l->numportals == MAX_PORTALS_ON_LEAF)
            Error ("Leaf with too many portals");
        l->portals[l->numportals] = p;
        l->numportals++;

        p->winding = w;
        VectorCopy (origin, p->origin);
        p->radius = radius;
        VectorNegate (plane.normal, p->plane.normal);
        p->plane.dist = -plane.dist;
        if (p->plane.normal[0] == 1)
            p->plane.type = PLANE_X;
        else if (p->plane.normal[1] == 1)
            p->plane.type = PLANE_Y;
        else if (p->plane.normal[2] == 1)
            p->plane.type = PLANE_Z;
        else
            p->plane.type = PLANE_ANYX;
        p->leaf = leafnums[1];
        p++;

        // create backwards portal
        l = &leafs[leafnums[1]];
        if (l->numportals == MAX_PORTALS_ON_LEAF)
            Error ("Leaf with too many portals");
        l->portals[l->numportals] = p;
        l->numportals++;

        p->winding = w;
        VectorCopy (origin, p->origin);
        p->radius = radius;
        p->plane = plane;
        if (p->plane.normal[0] == 1)
            p->plane.type = PLANE_X;
        else if (p->plane.normal[1] == 1)
            p->plane.type = PLANE_Y;
        else if (p->plane.normal[2] == 1)
            p->plane.type = PLANE_Z;
        else
            p->plane.type = PLANE_ANYX;
        p->leaf = leafnums[0];
        p++;
    }

    fclose (f);
}
Exemple #5
0
qboolean Eclass_hasModel(eclass_t *e, vec3_t &vMin, vec3_t &vMax)
{
	if (e->modelpath != NULL)
	{
		if (e->model == NULL)
		{
			e->model = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
		}
		char *pModelBuff = strdup(e->modelpath);
		char *pSkinBuff = NULL;
		if (e->skinpath)
		{
			pSkinBuff = strdup(e->skinpath);
		}

		CStringList Models;
		CStringList Skins;
		char* pToken = strtok(pModelBuff, ";\0");
		while (pToken != NULL)
		{
			Models.AddTail(pToken);
			pToken = strtok(NULL, ";\0");
		}

		if (pSkinBuff != NULL)
		{
			pToken = strtok(pSkinBuff, ";\0");
			while (pToken != NULL)
			{
				Skins.AddTail(pToken);
				pToken = strtok(NULL, ";\0");
			}
		}

		entitymodel *model = e->model;
		int i = 0;
		for (; i < Models.GetCount(); i++)
		{
			char *pSkin = NULL;
			if (i < Skins.GetCount())
			{
				pSkin = Skins.GetAt(Skins.FindIndex(i)).GetBuffer(0);
			}
			LoadModel(Models.GetAt(Models.FindIndex(i)), e, vMin, vMax, model, pSkin);
			model->pNext = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
			model = model->pNext;
		}

		// at this poitn vMin and vMax contain the min max of the model
		// which needs to be centered at origin 0, 0, 0

		VectorSnap(vMin);
		VectorSnap(vMax);

		if (vMax[0] - vMin[0] < 2)
		{
			vMin[0] -= 1;
			vMax[0] += 1;
		}

		if (vMin[1] - vMax[1] < 2)
		{
			vMin[1] -= 1;
			vMax[1] += 1;
		}

		if (vMax[2] - vMin[2] < 2)
		{
			vMax[2] -= 1;
			vMax[2] += 1;
		}

		vec3_t vTemp;
		VectorAdd(vMin, vMax, vTemp);
		VectorScale(vTemp, 0.5, vTemp);
		model = e->model;
		while (model != NULL)
		{
			for (i = 0; i < model->nTriCount; i++)
			{
				for (int j = 0; j < 3; j++)
				{
					;//VectorSubtract(model->pTriList[i].v[j], vTemp, model->pTriList[i].v[j]);
				}
			}
			model = model->pNext;
		}

		free(pModelBuff);
		free(e->modelpath);
		e->modelpath = NULL;

		if(e->skinpath)
		{
			free(e->skinpath);
			e->skinpath = NULL;
			free(pSkinBuff);
		}

	}
	return (e->model != NULL && e->model->nTriCount > 0);
}
Exemple #6
0
void DoTower(void)
{
	brush_t*	brush1 = NULL;
	brush_t*	brush2 = NULL;
	brush_t*	newBrush = NULL;
	brush_t*	tempBrush = NULL;
	face_t*		topFace = NULL;
	face_t*		bottomFace = NULL;
	face_t*		curFace;
	face_t*		faceList;
	int			zFlag = 0;
	int			i = 0; // loop counter

	if (g_qeglobals.d_select_count != 2)
	{
		Sys_Printf ("Error: you must have exactly 2 brushes selected\n");
		Sys_Beep ();
		return;
	}
	brush1 = selected_brushes.next;
	brush2 = selected_brushes.next->next;
//	establish brush1 as the upper brush
	if (brush2->maxs[2] > brush1->mins[2])
	{
		tempBrush = brush1;
		brush1 = brush2;
		brush2 = tempBrush;
	}
//	test to insure brushes do not "overlap" in the Z direction
	if (brush2->maxs[2] > brush1->mins[2])
	{
		Sys_Printf ("Brushes are not separated in the Z direction!");
		Sys_Beep();
		return;
	}
//  find the bottom Z plane (topFace) in 1 and top Z plane in 2 (bottomFace)
	topFace = brush1->brush_faces;
	while (topFace != NULL)
	{
		zFlag = 0;
		for (i = 0; i<3; i++)
		{
			if (abs(topFace->planepts[i][2] - brush1->mins[2]) < TOWER_EPSILON)
			{
				zFlag++;
			}
		}
		if (zFlag == 3)
		{
			break;
		}
		else
		{
			topFace = topFace->next;
		}
	}
	if (topFace == NULL)
	{
		Sys_Printf("Couldn't find flat bottom-face in top brush", 0);
		Sys_Beep();
		return;
	}
	bottomFace = brush2->brush_faces;
	while (bottomFace != NULL)
	{
		zFlag = 0;
		for (i = 0; i<3; i++)
		{
			if (abs(bottomFace->planepts[i][2] - brush2->maxs[2]) < TOWER_EPSILON)
			{
				zFlag++;
			}
		}
		if (zFlag == 3)
		{
			break;
		}
		else
		{
			bottomFace = bottomFace->next;
		}
	}
	if (bottomFace == NULL)
	{
		Sys_Printf ("Couldn't find flat top-face in bottom brush", 0);
		Sys_Beep();
		return;
	}
//	count vertices on top and bottom planes to make sure they are equal
	if (topFace->face_winding->numpoints != bottomFace->face_winding->numpoints)
	{

		Sys_Printf ("Top and Bottom faces don't have same #'s of vertices!", 0);
		Sys_Beep();
		return;
	}
//  put top and bottom faces on brush
//  reverse winding for top and bottom
	faceList = Face_Alloc();
	for ( i = 0; i<3; i++)
	{
		VectorCopy(topFace->planepts[2-i],faceList->planepts[i]);
	}
	curFace = Face_Alloc();
	for ( i = 0; i < 3; i++)
	{
		VectorCopy(bottomFace->planepts[2-i],curFace->planepts[i]);
	}
	curFace->next = faceList;
	faceList = curFace;
	
	curFace = MakePlaneList(topFace, bottomFace);
	if (curFace == NULL)
	{
		Sys_Printf ("Couldn't make planes for tower!", 0);
		Sys_Beep();
		return;
	}
	else
	{
		faceList->next->next = curFace;
	}

	newBrush = (brush_t*)qmalloc(sizeof(brush_t));
	newBrush->brush_faces = faceList;
	Select_Deselect();
	Brush_AddToList (newBrush, &selected_brushes);

	Entity_LinkBrush (world_entity, newBrush);

	Brush_Build(newBrush);
//	UNDO_FinishBrushAdd("&Undo Tower");
	Sys_UpdateWindows(W_ALL);
	return;

}
Exemple #7
0
// FIXME: this code is a TOTAL clusterfuck
//
void LoadModel(const char *pLocation, eclass_t *e, vec3_t &vMin, vec3_t &vMax, entitymodel *&pModel, const char *pSkin)
{
	// this assumes a path only and uses tris.md2
	// for the model and skin.pcx for the skin
	char cPath[1024];
	char cSkin[1024];
	char cFullLocation[1024];
	//struct _finddata_t fileinfo;

	vMin[0] = vMin[1] = vMin[2] = 99999;
	vMax[0] = vMax[1] = vMax[2] = -99999;

	bool bMD3 = false;
	bool bASE = false;

	strcpy( cFullLocation, pLocation );

	if (strstr(pLocation, ".md3"))
	{
		bMD3 = true;
	}
	else if (strstr(pLocation, ".md2") != NULL)
	{
		sprintf( cFullLocation, "%stris.md2", pLocation);
	}
	else if (strstr(pLocation, ".ase") != NULL)
	{
		bASE = true;
	}

	sprintf( cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cFullLocation);

	Sys_Printf("Loading model %s...", cPath);
	unsigned char* p = NULL;
	bool bOpen = (LoadFile(cPath, reinterpret_cast<void**>(&p)) > 0);
	if (!bOpen)
	{
		Sys_Printf(" failed. Trying PAK file...");
		//    sprintf (cPath, "%stris.md2", pLocation);
		strcpy (cPath, cFullLocation);
		bOpen = (PakLoadAnyFile(cPath, reinterpret_cast<void**>(&p)) > 0);
	}

	if (bOpen)
	{
		Sys_Printf(" successful.\n");

		if (bASE)
		{
			/*
			free(p);
			CString strOut;
			::GetTempPath(1024, strOut.GetBuffer(1024));
			strOut.ReleaseBuffer();
			AddSlash(strOut);
			strOut += "Temp.ase";
			CopyFile(cPath, strOut, false);
			CString strIn = strOut;
			FindReplace(strOut, ".ase", ".md3");
			strcpy(cPath, strIn);
			strcpy(cSkin, strOut);
			Q3Data_ProduceTempMD3(ValueForKey(g_qeglobals.d_project_entity, "basepath"), cPath, cSkin);
			CString strModel = cPath;
			if (LoadFile(strOut.GetBuffer(0), reinterpret_cast<void**>(&p)) == 0)
			{
			Sys_Printf(" Conversion from ASE failed.\n");
			return;
			}
			bMD3 = true;
			*/
		}

		if (bMD3)
		{
			md3Header_t header;
			md3Surface_t *pSurface;
			header = *(md3Header_t *)p;
			if (pSkin != NULL)
			{
				strcpy(cSkin, pSkin);
			}
			else
			{
				cSkin[0] = '\0';
			}
			int n = header.numFrames;
			pSurface = (md3Surface_t *) (p + header.ofsSurfaces);
			for (int z = 0; z < header.numSurfaces; z++ )
			{
				int nTris = pSurface->numTriangles;

				//unsigned char* pTris = reinterpret_cast<unsigned char*>(pSurface);
				//pTris += pSurface->ofsTriangles;

				if (nTris > 0)
				{
					int nStart = 0;
					if (pModel->pTriList == NULL)
					{
						pModel->nModelPosition = 0;
						pModel->pTriList = new trimodel[nTris];
						pModel->nTriCount = nTris;
					}
					else
					{
						// already have one so we need to reallocate
						int nNewCount = pModel->nTriCount + nTris;
						trimodel* pNewModels = new trimodel[nNewCount];
						for (int i = 0; i < pModel->nTriCount; i++)
						{
							memcpy(&pNewModels[i], &pModel->pTriList[i], sizeof(trimodel));
						}
						nStart = pModel->nTriCount;
						pModel->nTriCount = nNewCount;
						//nTris = nNewCount;
						delete [] pModel->pTriList;
						pModel->pTriList = pNewModels;
					}

					md3Triangle_t *pTris = reinterpret_cast<md3Triangle_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsTriangles));
					md3XyzNormal_t *pXyz = reinterpret_cast<md3XyzNormal_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsXyzNormals));
					if (e->nFrame < pSurface->numFrames)
					{
						pXyz += (e->nFrame * pSurface->numVerts);
					}

					md3St_t *pST = reinterpret_cast<md3St_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsSt)); 

					for (int i = 0; i < nTris; i++)
					{
						for (int k = 0; k < 3; k ++)
						{
							for (int j = 0; j < 3; j++)
							{
								//e->pTriList[i].v[k][j] = (f->verts[tri.index_xyz[k]].v[j] * f->scale[j] + f->translate[j]);
								pModel->pTriList[nStart].v[k][j] = pXyz[pTris[i].indexes[k]].xyz[j] * MD3_XYZ_SCALE;
							}
							pModel->pTriList[nStart].st[k][0] = pST[pTris[i].indexes[k]].st[0];
							pModel->pTriList[nStart].st[k][1] = pST[pTris[i].indexes[k]].st[1];
							ExtendBounds (pModel->pTriList[nStart].v[k], vMin, vMax);
						}
						nStart++;
					}

				}

				md3Shader_t *pShader = reinterpret_cast<md3Shader_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsShaders)); 
				sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pShader->name);
				strlwr(cPath);
				pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
				if (pModel->nTextureBind == -1)
				{
					Sys_Printf("Model skin load failed on texture %s\n", cPath);
				}
				pSurface = (md3Surface_t *) ((( char * ) pSurface) + pSurface->ofsEnd);
				pModel->pNext = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
				pModel = pModel->pNext;
			}
		}
		else
		{

			dmdl_t model;
			daliasframe_t *f;
			unsigned char* pTris = p;
			dstvert_t *pST = NULL;
			int nTris = 0;

			// grab model params
			memcpy(&model, p, sizeof(dmdl_t));
			f = (daliasframe_t*)(p + model.ofs_frames);
			pTris += model.ofs_tris;
			pST = reinterpret_cast<dstvert_t*>(p + model.ofs_st);
			nTris = model.num_tris;

			if(pSkin)
			{
				strcpy (cSkin, pSkin);
				if ((cSkin[strlen(cSkin)-1] == '\\') || (cSkin[strlen(cSkin)-1] == '/'))
					strcat(cSkin, "skin.pcx\0");
			}
			else
			{
				strcpy(cSkin, (char *)(p + model.ofs_skins));
			}

			sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cSkin);
			strlwr(cPath);
			pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
			if (pModel->nTextureBind == -1)
			{
				Sys_Printf("Model skin load failed on texture %s\n", cPath);
			}
			int nStart = 0;
			if (pModel->pTriList == NULL)
			{
				pModel->nModelPosition = 0;
				pModel->pTriList = new trimodel[nTris];
				pModel->nTriCount = nTris;
			}
			else
			{
				// already have one so we need to reallocate
				int nNewCount = pModel->nTriCount + nTris;
				trimodel* pNewModels = new trimodel[nNewCount];
				for (int i = 0; i < pModel->nTriCount; i++)
				{
					memcpy(&pNewModels[i], &pModel->pTriList[i], sizeof(trimodel));
				}
				nStart = pModel->nTriCount;
				pModel->nTriCount = nNewCount;
				nTris = nNewCount;
				delete [] pModel->pTriList;
				pModel->pTriList = pNewModels;
			}

			for (int i = nStart; i < nTris; i++)
			{
				dtriangle_t tri;
				memcpy(&tri, pTris, sizeof(dtriangle_t));
				for (int k = 0; k < 3; k ++)
				{
					for (int j = 0; j < 3; j++)
					{
						pModel->pTriList[i].v[k][j] = (f->verts[tri.index_xyz[k]].v[j] * f->scale[j] + f->translate[j]);
					}

					pModel->pTriList[i].st[k][0] = pST[tri.index_st[k]].s / pModel->nSkinWidth;
					pModel->pTriList[i].st[k][1] = pST[tri.index_st[k]].t / pModel->nSkinHeight;;
					ExtendBounds (pModel->pTriList[i].v[k], vMin, vMax);
				}
				pTris += sizeof(dtriangle_t);
			}
		}
		free(p);
	}
	else
	{
		Sys_Printf(" failed.\n");
	}

#if 0
	if (pModel->pTriList != NULL && pModel->nTriCount > 0 && !bMD3)
	{
		if(fabs(vMin[2]) < ((vMax[2]-vMin[2]) / 10.0))	// > 90% above 0 point.
			pModel->nModelPosition = 1;
		//	sprintf (cPath, "%s/%sskin.pcx", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pLocation);
		sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cSkin);
		pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
		if (pModel->nTextureBind == -1)
		{
			//      sprintf (cPath, "%sskin.pcx", pLocation);
			strcpy (cPath, cSkin);
			pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
		}
	}
#endif

}
/*
============
Entity_Create

Creates a new entity out of the selected_brushes list.
If the entity class is fixed size, the brushes are only
used to find a midpoint.  Otherwise, the brushes have
their ownershi[ transfered to the new entity.
============
*/
entity_t	*Entity_Create (eclass_t *c)
{
	entity_t	*e;
	brush_t		*b;
	vec3_t		mins, maxs;
	int			i;

	// check to make sure the brushes are ok

	for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
		if (b->owner != world_entity)
		{
			Sys_Printf ("Entity NOT created, brushes not all from world\n");
			Sys_Beep ();
			return NULL;
		}

	// create it

	e = (entity_t*)qmalloc(sizeof(*e));
	e->brushes.onext = e->brushes.oprev = &e->brushes;
	e->eclass = c;
	SetKeyValue (e, "classname", c->name);
							  
	// add the entity to the entity list
	e->next = entities.next;
	entities.next = e;
	e->next->prev = e;
	e->prev = &entities;

	if (c->fixedsize)
	{
		//
		// just use the selection for positioning
		//
		b = selected_brushes.next;
		for (i=0 ; i<3 ; i++)
			e->origin[i] = b->mins[i] - c->mins[i];

		// create a custom brush
		VectorAdd (c->mins, e->origin, mins);
		VectorAdd (c->maxs, e->origin, maxs);

	  b = Brush_Create (mins, maxs, &c->texdef);

		Entity_LinkBrush (e, b);

		// delete the current selection
		Select_Delete ();

		// select the new brush
		b->next = b->prev = &selected_brushes;
		selected_brushes.next = selected_brushes.prev = b;

		Brush_Build( b );
	}
	else
	{
		//
		// change the selected brushes over to the new entity
		//
		for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
		{
			Entity_UnlinkBrush (b);
			Entity_LinkBrush (e, b);
			Brush_Build( b );	// so the key brush gets a name
		}
	}

	Sys_UpdateWindows (W_ALL);
	return e;
}
Exemple #9
0
bool_t model_md2_save(const model_t *orig_model, xbuf_t *xbuf, char **out_error)
{
	char *error;
	int skinwidth, skinheight;
	char **skinfilenames;
	const skininfo_t *skininfo;
	model_t *model;
	const mesh_t *mesh;
	md2_data_t *md2data;
	md2_header_t *header;
	dtriangle_t *dtriangles;
	int i, j, k;

	model = model_merge_meshes(orig_model);

	mesh = &model->meshes[0];

	skinwidth = (texwidth != -1) ? texwidth : 0;
	skinheight = (texheight != -1) ? texheight : 0;
	for (i = 0, skininfo = model->skininfo; i < model->num_skins; i++, skininfo++)
	{
		for (j = 0; j < skininfo->num_skins; j++)
		{
			int offset = skininfo->skins[j].offset;

			if (!mesh->skins[offset].components[SKIN_DIFFUSE])
			{
				if (out_error)
					*out_error = msprintf("Model has missing skin.");
				model_free(model);
				return false;
			}

			if (skinwidth && skinheight && (skinwidth != mesh->skins[offset].components[SKIN_DIFFUSE]->width || skinheight != mesh->skins[offset].components[SKIN_DIFFUSE]->height))
			{
				if (out_error)
					*out_error = msprintf("Model has skins of different sizes. Use -texwidth and -texheight to resize all images to the same size");
				model_free(model);
				return false;
			}
			skinwidth = mesh->skins[offset].components[SKIN_DIFFUSE]->width;
			skinheight = mesh->skins[offset].components[SKIN_DIFFUSE]->height;

		/* if fullbright texture is a different size, resample it to match the diffuse texture */
			if (mesh->skins[offset].components[SKIN_FULLBRIGHT] && (mesh->skins[offset].components[SKIN_FULLBRIGHT]->width != skinwidth || mesh->skins[offset].components[SKIN_FULLBRIGHT]->height != skinheight))
			{
				image_rgba_t *image = image_resize(mem_globalpool, mesh->skins[offset].components[SKIN_FULLBRIGHT], skinwidth, skinheight);
				image_free(&mesh->skins[offset].components[SKIN_FULLBRIGHT]);
				mesh->skins[offset].components[SKIN_FULLBRIGHT] = image;
			}
		}
	}

	if (!skinwidth || !skinheight)
	{
		if (out_error)
			*out_error = msprintf("Model has no skin. Use -texwidth and -texheight to set the skin dimensions, or -tex to import a skin");
		model_free(model);
		return false;
	}

/* create 8-bit skins and save them to PCX files */
	skinfilenames = (char**)qmalloc(sizeof(char*) * model->num_skins);

	for (i = 0, skininfo = model->skininfo; i < model->num_skins; i++, skininfo++)
	{
		image_paletted_t *pimage;

		int offset = skininfo->skins[0].offset; /* skingroups not supported, just take the first skin from the group */

		skinfilenames[i] = md2_create_skin_filename(skininfo->skins[0].name);

		pimage = image_palettize(mem_globalpool, &palette_quake2, mesh->skins[offset].components[SKIN_DIFFUSE], mesh->skins[offset].components[SKIN_FULLBRIGHT]);

	/* FIXME - this shouldn't be a fatal error */
		if (!image_paletted_save(skinfilenames[i], pimage, &error))
		{
			if (out_error)
				*out_error = msprintf("Failed to write %s: %s", skinfilenames[i], error);
			qfree(error);
			qfree(pimage);
			for (j = 0; j < i; j++)
				qfree(skinfilenames[j]);
			qfree(skinfilenames);
			model_free(model);
			return false;
		}

		qfree(pimage);
	}

/* optimize vertices for md2 format */
	md2data = md2_process_vertices(model, mesh, skinwidth, skinheight);

/* write header */
	header = (md2_header_t*)xbuf_reserve_data(xbuf, sizeof(md2_header_t));

	memcpy(header->ident, "IDP2", 4);
	header->version       = LittleLong(8);
	header->skinwidth     = LittleLong(skinwidth);
	header->skinheight    = LittleLong(skinheight);
	header->framesize     = LittleLong(sizeof(daliasframe_t) + sizeof(dtrivertx_t) * md2data->numvertices);
	header->num_skins     = LittleLong(model->num_skins);
	header->num_vertices  = LittleLong(md2data->numvertices);
	header->num_st        = LittleLong(md2data->numtexcoords);
	header->num_tris      = LittleLong(mesh->num_triangles);
	header->num_glcmds    = 0; /* filled in later */
	header->num_frames    = LittleLong(model->num_frames);
	header->offset_skins  = 0;
	header->offset_st     = 0;
	header->offset_tris   = 0;
	header->offset_frames = 0;
	header->offset_glcmds = 0;
	header->offset_end    = 0;

/* write skins */
	header->offset_skins = LittleLong(xbuf_get_bytes_written(xbuf));

	for (i = 0; i < model->num_skins; i++)
	{
		md2_skin_t md2skin;
		
		strlcpy(md2skin.name, skinfilenames[i], sizeof(md2skin.name));

		xbuf_write_data(xbuf, sizeof(md2_skin_t), &md2skin);
	}

/* write texcoords */
	for (i = 0; i < md2data->numtexcoords; i++)
	{
		md2data->texcoords[i].s = LittleShort(md2data->texcoords[i].s);
		md2data->texcoords[i].t = LittleShort(md2data->texcoords[i].t);
	}

	header->offset_st = LittleLong(xbuf_get_bytes_written(xbuf));

	xbuf_write_data(xbuf, sizeof(dstvert_t) * md2data->numtexcoords, md2data->texcoords);

/* write triangles */
	dtriangles = (dtriangle_t*)qmalloc(sizeof(dtriangle_t) * mesh->num_triangles);
	for (i = 0; i < mesh->num_triangles; i++)
	{
		for (j = 0; j < 3; j++)
		{
			dtriangles[i].index_xyz[j] = LittleShort(md2data->vertex_lookup[mesh->triangle3i[i*3+j]]);
			dtriangles[i].index_st[j] = LittleShort(md2data->texcoord_lookup[mesh->triangle3i[i*3+j]]);
		}
	}

	header->offset_tris = LittleLong(xbuf_get_bytes_written(xbuf));

	xbuf_write_data(xbuf, sizeof(dtriangle_t) * mesh->num_triangles, dtriangles);

/* write frames */
	header->offset_frames = LittleLong(xbuf_get_bytes_written(xbuf));

	for (i = 0; i < model->num_frames; i++)
	{
		daliasframe_t md2frame;

		for (j = 0; j < 3; j++)
		{
			md2frame.scale[j] = LittleFloat(md2data->frames[i].scale[j]);
			md2frame.translate[j] = LittleFloat(md2data->frames[i].translate[j]);
		}

		strlcpy(md2frame.name, model->frameinfo[i].frames[0].name, sizeof(md2frame.name));

		xbuf_write_data(xbuf, sizeof(daliasframe_t), &md2frame);

	/* write vertices */
		for (j = 0; j < md2data->numvertices; j++)
		{
			const dtrivertx_t *md2vertex = md2data->original_vertices + md2data->vertices[j] * model->num_frames + i;
			dtrivertx_t vtx;

			for (k = 0; k < 3; k++)
				vtx.v[k] = md2vertex->v[k];

			vtx.lightnormalindex = md2vertex->lightnormalindex;

			xbuf_write_data(xbuf, sizeof(dtrivertx_t), &vtx);
		}
	}

/* write glcmds */
	triangles = dtriangles;
	num_tris = mesh->num_triangles;

	md2_build_glcmds(md2data->texcoords, skinwidth, skinheight);

	header->num_glcmds = LittleLong(numcommands);
	header->offset_glcmds = LittleLong(xbuf_get_bytes_written(xbuf));

	for (i = 0; i < numcommands; i++)
		commands[i] = LittleLong(commands[i]);
	xbuf_write_data(xbuf, sizeof(int) * numcommands, commands);

/* write end */
	header->offset_end = LittleLong(xbuf_get_bytes_written(xbuf));

/* done */
	qfree(dtriangles);
	md2_free_data(md2data);

	for (i = 0; i < model->num_skins; i++)
		qfree(skinfilenames[i]);
	qfree(skinfilenames);

	model_free(model);
	return true;
}
Exemple #10
0
eclass_t *Eclass_InitFromText (char *text)
{
	char	*t;
	int		len;
	int		r, i;
	char	parms[256], *p;
	eclass_t	*e;
	char	color[128];

	e = qmalloc(sizeof(*e));
	memset (e, 0, sizeof(*e));

	text += strlen("/*QUAKED ");

// grab the name
	text = COM_Parse (text);
	e->name = qmalloc (strlen(com_token)+1);
	strcpy (e->name, com_token);
	debugname = e->name;

// grab the color, reformat as texture name
	r = sscanf (text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2]);
	if (r != 3)
		return e;
	sprintf (color, "(%f %f %f)", e->color[0], e->color[1], e->color[2]);
	strcpy (e->texdef.name, color);

	while (*text != ')')
	{
		if (!*text)
			return e;
		text++;
	}
	text++;

// get the size
	text = COM_Parse (text);
	if (com_token[0] == '(')
	{	// parse the size as two vectors
		e->fixedsize = true;
		r = sscanf (text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2],
			&e->maxs[0], &e->maxs[1], &e->maxs[2]);
		if (r != 6)
			return e;

		for (i=0 ; i<2 ; i++)
		{
			while (*text != ')')
			{
				if (!*text)
					return e;
				text++;
			}
			text++;
		}
	}
	else
	{	// use the brushes
	}

// get the flags


// copy to the first /n
	p = parms;
	while (*text && *text != '\n')
		*p++ = *text++;
	*p = 0;
	text++;

// any remaining words are parm flags
	p = parms;
	for (i=0 ; i<8 ; i++)
	{
		p = COM_Parse (p);
		if (!p)
			break;
		strcpy (e->flagnames[i], com_token);
	}

// find the length until close comment
	for (t=text ; t[0] && !(t[0]=='*' && t[1]=='/') ; t++)
	;

// copy the comment block out
	len = t-text;
	e->comments = qmalloc (len+1);
	memcpy (e->comments, text, len);
#if 0
	for (i=0 ; i<len ; i++)
		if (text[i] == '\n')
			e->comments[i] = '\r';
		else
			e->comments[i] = text[i];
#endif
	e->comments[len] = 0;

	return e;
}
Exemple #11
0
static void md2_build_glcmds(const dstvert_t *texcoords, int skinwidth, int skinheight)
{
	int i, j;
	int startv;
	int len, bestlen, besttype = -1;
	int best_xyz[1024];
	int best_st[1024];
	int best_tris[1024];
	int type;

	numcommands = 0;
	used = (int*)qmalloc(sizeof(int) * num_tris);
	memset(used, 0, sizeof(int) * num_tris);
	for (i = 0; i < num_tris; i++)
	{
	/* pick an unused triangle and start the trifan */
		if (used[i])
			continue;

		bestlen = 0;
		for (type = 0; type < 2; type++)
		{
			for (startv = 0; startv < 3; startv++)
			{
				if (type == 1)
					len = md2_strip_length(i, startv);
				else
					len = md2_fan_length(i, startv);

				if (len > bestlen)
				{
					besttype = type;
					bestlen = len;
					for (j = 0; j < bestlen + 2; j++)
					{
						best_st[j] = strip_st[j];
						best_xyz[j] = strip_xyz[j];
					}
					for (j = 0; j < bestlen; j++)
						best_tris[j] = strip_tris[j];
				}
			}
		}

	/* mark the tris on the best strip/fan as used */
		for (j = 0; j < bestlen; j++)
			used[best_tris[j]] = 1;

		if (besttype == 1)
			commands[numcommands++] = (bestlen+2);
		else
			commands[numcommands++] = -(bestlen+2);

		for (j = 0; j < bestlen + 2; j++)
		{
			union { float f; int i; } u;
			u.f = (texcoords[best_st[j]].s + 0.5f) / skinwidth;
			commands[numcommands++] = u.i;
			u.f = (texcoords[best_st[j]].t + 0.5f) / skinheight;
			commands[numcommands++] = u.i;
			commands[numcommands++] = best_xyz[j];
		}
	}

	commands[numcommands++] = 0; /* end of list marker */

	qfree(used);
}
Exemple #12
0
static md2_data_t *md2_process_vertices(const model_t *model, const mesh_t *mesh, int skinwidth, int skinheight)
{
	md2_data_t *data;
	int i, j, k;

	data = (md2_data_t*)qmalloc(sizeof(md2_data_t));

/* convert texcoords to integer and combine duplicates */
	data->texcoords = (dstvert_t*)qmalloc(sizeof(dstvert_t) * mesh->num_vertices);
	data->numtexcoords = 0;
	data->texcoord_lookup = (int*)qmalloc(sizeof(int) * mesh->num_vertices);

	for (i = 0; i < mesh->num_vertices; i++)
	{
		dstvert_t md2texcoord;

		md2texcoord.s = (int)(mesh->texcoord2f[i*2+0] * skinwidth);
		md2texcoord.t = (int)(mesh->texcoord2f[i*2+1] * skinheight);

		for (j = 0; j < data->numtexcoords; j++)
			if (md2texcoord.s == data->texcoords[j].s && md2texcoord.t == data->texcoords[j].t)
				break;
		if (j == data->numtexcoords)
			data->texcoords[data->numtexcoords++] = md2texcoord;
		data->texcoord_lookup[i] = j;
	}

/* compress vertices */
	data->frames = (daliasframe_t*)qmalloc(sizeof(daliasframe_t) * model->num_frames);
	data->original_vertices = (dtrivertx_t*)qmalloc(sizeof(dtrivertx_t) * mesh->num_vertices * model->num_frames);

	for (i = 0; i < model->num_frames; i++)
	{
		daliasframe_t *md2frame = &data->frames[i];
		const float *v, *n;
		float mins[3], maxs[3], iscale[3];

	/* calculate bounds of frame */
		VectorClear(mins);
		VectorClear(maxs);
		v = mesh->vertex3f + model->frameinfo[i].frames[0].offset * mesh->num_vertices * 3;
		for (j = 0; j < mesh->num_vertices; j++, v += 3)
		{
			for (k = 0; k < 3; k++)
			{
				mins[k] = (j == 0) ? v[k] : min(mins[k], v[k]);
				maxs[k] = (j == 0) ? v[k] : max(maxs[k], v[k]);
			}
		}

		for (j = 0; j < 3; j++)
		{
			md2frame->scale[j] = (maxs[j] - mins[j]) * (1.0f / 255.0f);
			md2frame->translate[j] = mins[j];

			iscale[j] = md2frame->scale[j] ? (1.0f / md2frame->scale[j]) : 0.0f;
		}

	/* compress vertices */
		v = mesh->vertex3f + model->frameinfo[i].frames[0].offset * mesh->num_vertices * 3;
		n = mesh->normal3f + model->frameinfo[i].frames[0].offset * mesh->num_vertices * 3;
		for (j = 0; j < mesh->num_vertices; j++, v += 3, n += 3)
		{
			dtrivertx_t *md2vertex = &data->original_vertices[j * model->num_frames + i];

			for (k = 0; k < 3; k++)
			{
				float pos = (v[k] - md2frame->translate[k]) * iscale[k];

				pos = (float)floor(pos + 0.5f);
				pos = bound(0.0f, pos, 255.0f);

				md2vertex->v[k] = (unsigned char)pos;
			}

			md2vertex->lightnormalindex = compress_normal(n);
		}
	}

/* combine duplicate vertices */
	data->vertices = (int*)qmalloc(sizeof(int) * mesh->num_vertices);
	data->numvertices = 0;
	data->vertex_lookup = (int*)qmalloc(sizeof(int) * mesh->num_vertices);

	for (i = 0; i < mesh->num_vertices; i++)
	{
		const dtrivertx_t *v1 = data->original_vertices + i * model->num_frames;

	/* see if a vertex at this position already exists */
		for (j = 0; j < data->numvertices; j++)
		{
			const dtrivertx_t *v2 = data->original_vertices + data->vertices[j] * model->num_frames;

			for (k = 0; k < model->num_frames; k++)
				if (v1[k].v[0] != v2[k].v[0] || v1[k].v[1] != v2[k].v[1] || v1[k].v[2] != v2[k].v[2] || v1[k].lightnormalindex != v2[k].lightnormalindex)
					break;
			if (k == model->num_frames)
				break;
		}
		if (j == data->numvertices)
		{
		/* no match, add this one */
			data->vertices[data->numvertices++] = i;
		}
		data->vertex_lookup[i] = j;
	}

	return data;
}
Exemple #13
0
group_t* Group_Alloc(char *name)
{
  group_t *g = (group_t*)qmalloc(sizeof(group_t));
	SetKeyValue( g->epairs, "group", name );
  return g;
}
Exemple #14
0
static bool save_var (const char *filename, const char *section, const char *key, const char *value)
{
  char line[1024], *ptr;
  MemStream old_rc;
  bool found;
  FILE *rc;

  rc = fopen (filename, "rb");

  if (rc != NULL)
  {
    guint32 len;
    void *buf;

    fseek (rc, 0, SEEK_END);
    len = ftell (rc);
    rewind (rc);
    buf = qmalloc (len);
    fread (buf, len, 1, rc);
    old_rc.Write (buf, len);
    free (buf);
    fclose (rc);
    old_rc.Seek (0, SEEK_SET);
  }

  // TTimo: changed to binary writing. It doesn't seem to affect linux version, and win32 version was happending a lot of '\n'
  rc = fopen (filename, "wb");

  if (rc == NULL)
    return false;

  // First we need to find the section
  found = false;
  while (old_rc.ReadString (line, 1024) != NULL)
  {
    fputs (line, rc);

    if (line[0] == '[')
    {
      ptr = strchr (line, ']');
      *ptr = '\0';

      if (strcmp (&line[1], section) == 0)
      {
	found = true;
	break;
      }
    }
  } 

  if (!found)
  {
    fputs ("\n", rc);
    fprintf (rc, "[%s]\n", section);
  }

  fprintf (rc, "%s=%s\n", key, value);

  while (old_rc.ReadString (line, 1024) != NULL)
  {
    ptr = strchr (line, '=');

    if (ptr != NULL)
    {
      *ptr = '\0';

      if (strcmp (line, key) == 0)
	break;
 
      *ptr = '=';
      fputs (line, rc);
    }
    else
    {
      fputs (line, rc);
      break;
    }
  }

  while (old_rc.ReadString (line, 1024) != NULL)
    fputs (line, rc);

  fclose (rc);
  return true;
}
Exemple #15
0
eclass_t *Eclass_InitFromText (char *text)
{
	char	*t;
	int		len;
	int		r, i;
	char	parms[256], *p;
	eclass_t	*e;
	char	color[128];

	e = (eclass_t*)qmalloc(sizeof(*e));
	memset (e, 0, sizeof(*e));

	text += strlen("/*QUAKED ");

	// grab the name
	text = COM_Parse (text);
	e->name = (char*)qmalloc (strlen(com_token)+1);
	strcpy (e->name, com_token);
	debugname = e->name;

	// grab the color, reformat as texture name
	r = sscanf (text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2]);
	if (r != 3)
		return e;
	sprintf (color, "(%f %f %f)", e->color[0], e->color[1], e->color[2]);
	//strcpy (e->texdef.name, color);
	e->texdef.SetName(color);

	while (*text != ')')
	{
		if (!*text)
			return e;
		text++;
	}
	text++;

	// get the size	
	text = COM_Parse (text);
	if (com_token[0] == '(')
	{	// parse the size as two vectors
		e->fixedsize = true;
		r = sscanf (text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2],
			&e->maxs[0], &e->maxs[1], &e->maxs[2]);
		if (r != 6)
			return e;

		for (i=0 ; i<2 ; i++)
		{
			while (*text != ')')
			{
				if (!*text)
					return e;
				text++;
			}
			text++;
		}
	}
	else
	{	// use the brushes
	}

	// get the flags


	// copy to the first /n
	p = parms;
	while (*text && *text != '\n')
		*p++ = *text++;
	*p = 0;
	text++;

	// any remaining words are parm flags
	p = parms;
	for (i=0 ; i<8 ; i++)
	{
		p = COM_Parse (p);
		if (!p)
			break;
		strcpy (e->flagnames[i], com_token);
	} 

	// find the length until close comment
	for (t=text ; t[0] && !(t[0]=='*' && t[1]=='/') ; t++)
		;

	// copy the comment block out
	len = t-text;
	e->comments = (char*)qmalloc (len+1);
	memcpy (e->comments, text, len);
#if 0
	for (i=0 ; i<len ; i++)
		if (text[i] == '\n')
			e->comments[i] = '\r';
		else
			e->comments[i] = text[i];
#endif
	e->comments[len] = 0;

	setSpecialLoad(e, "model=", e->modelpath);
	setSpecialLoad(e, "skin=", e->skinpath);
	char *pFrame = NULL;
	setSpecialLoad(e, "frame=", pFrame);
	if (pFrame != NULL)
	{
		e->nFrame = atoi(pFrame);
	}

	if(!e->skinpath)
		setSpecialLoad(e, "texture=", e->skinpath);

	// setup show flags
	e->nShowFlags = 0;
	if (strcmpi(e->name, "light") == 0)
	{
		e->nShowFlags |= ECLASS_LIGHT;
	}

	if (  (strnicmp(e->name, "info_player", strlen("info_player")) == 0)
		||(strnicmp(e->name, "path_corner", strlen("path_corner")) == 0) 
		||(strnicmp(e->name, "team_ctf", strlen("team_ctf")) == 0) )
	{
		e->nShowFlags |= ECLASS_ANGLE;
	}
	if (strcmpi(e->name, "path") == 0)
	{
		e->nShowFlags |= ECLASS_PATH;
	}
	if (strcmpi(e->name, "misc_model") == 0)
	{
		e->nShowFlags |= ECLASS_MISCMODEL;
	}


	return e;
}
Exemple #16
0
void ParseBrushFace (entity_t *ent, mbrush_t **brushpointer, brushtype_t brushtype)
{
	int			i, j, sv, tv, hltexdef, facecontents, faceflags, facevalue, q2brushface, q3brushface, bpface;
	vec_t		planepts[3][3], t1[3], t2[3], d, rotate, scale[2], vecs[2][4], ang, sinv, cosv, ns, nt, bp[2][3];
	mface_t		*f, *f2;
	plane_t	plane;
	texinfo_t	tx;
	mbrush_t	*b;

	if (brushtype == BRUSHTYPE_PATCHDEF2 || brushtype == BRUSHTYPE_PATCHDEF3)
		return;
	// read the three point plane definition
	if (strcmp (token, "(") )
		Error ("parsing brush on line %d\n", scriptline);
	GetToken (false);
	planepts[0][0] = atof(token);
	GetToken (false);
	planepts[0][1] = atof(token);
	GetToken (false);
	planepts[0][2] = atof(token);
	GetToken (false);
	if (!strcmp(token, ")"))
	{
		GetToken (false);
		if (strcmp(token, "("))
			Error("parsing brush on line %d\n", scriptline);
		GetToken (false);
		planepts[1][0] = atof(token);
		GetToken (false);
		planepts[1][1] = atof(token);
		GetToken (false);
		planepts[1][2] = atof(token);
		GetToken (false);
		if (strcmp(token, ")"))
			Error("parsing brush on line %d\n", scriptline);

		GetToken (false);
		if (strcmp(token, "("))
			Error("parsing brush on line %d\n", scriptline);
		GetToken (false);
		planepts[2][0] = atof(token);
		GetToken (false);
		planepts[2][1] = atof(token);
		GetToken (false);
		planepts[2][2] = atof(token);
		GetToken (false);
		if (strcmp(token, ")"))
			Error("parsing brush on line %d\n", scriptline);

		// convert points to a plane
		VectorSubtract(planepts[0], planepts[1], t1);
		VectorSubtract(planepts[2], planepts[1], t2);
		CrossProduct(t1, t2, plane.normal);
		VectorNormalize(plane.normal);
		plane.dist = DotProduct(planepts[1], plane.normal);
	}
	else
	{
		// oh, it's actually a 4 value plane
		plane.normal[0] = planepts[0][0];
		plane.normal[1] = planepts[0][1];
		plane.normal[2] = planepts[0][2];
		plane.dist = -atof(token);
		GetToken (false);
		if (strcmp(token, ")"))
			Error("parsing brush on line %d\n", scriptline);
	}

	// read the texturedef
	memset (&tx, 0, sizeof(tx));
	GetToken (false);
	bpface = false;
	hltexdef = false;
	if (!strcmp(token, "("))
	{
		// brush primitives, utterly insane
		bpface = true;
		// (
		GetToken(false);
		// (
		GetToken(false);
		bp[0][0] = atof(token);
		GetToken(false);
		bp[0][1] = atof(token);
		GetToken(false);
		bp[0][2] = atof(token);
		GetToken(false);
		// )
		GetToken(false);
		// (
		GetToken(false);
		bp[1][0] = atof(token);
		GetToken(false);
		bp[1][1] = atof(token);
		GetToken(false);
		bp[1][2] = atof(token);
		GetToken(false);
		// )
		GetToken (false);
		GetToken (false);
		tx.miptex = FindMiptex (token);
		rotate = 0;
		scale[0] = 1;
		scale[1] = 1;
	}
	else
	{
		// if the texture name contains a / then this is a q2/q3 brushface
		// strip off the path, wads don't use a path on texture names
		tx.miptex = FindMiptex (token);
		GetToken (false);
		if (!strcmp(token, "["))
		{
			hltexdef = true;
			// S vector
			GetToken(false);
			vecs[0][0] = (vec_t)atof(token);
			GetToken(false);
			vecs[0][1] = (vec_t)atof(token);
			GetToken(false);
			vecs[0][2] = (vec_t)atof(token);
			GetToken(false);
			vecs[0][3] = (vec_t)atof(token);
			// ]
			GetToken(false);
			// [
			GetToken(false);
			// T vector
			GetToken(false);
			vecs[1][0] = (vec_t)atof(token);
			GetToken(false);
			vecs[1][1] = (vec_t)atof(token);
			GetToken(false);
			vecs[1][2] = (vec_t)atof(token);
			GetToken(false);
			vecs[1][3] = (vec_t)atof(token);
			// ]
			GetToken(false);

			// rotation (unused - implicit in tex coords)
			GetToken(false);
			rotate = 0;
		}
		else
		{
			vecs[0][3] = (vec_t)atof(token); // LordHavoc: float coords
			GetToken (false);
			vecs[1][3] = (vec_t)atof(token); // LordHavoc: float coords
			GetToken (false);
			rotate = atof(token); // LordHavoc: float coords
		}

		GetToken (false);
		scale[0] = (vec_t)atof(token); // LordHavoc: was already float coords
		GetToken (false);
		scale[1] = (vec_t)atof(token); // LordHavoc: was already float coords
	}
	// q3 .map properties, currently unused but parsed
	facecontents = 0;
	faceflags = 0;
	facevalue = 0;
	q2brushface = false;
	q3brushface = false;
	if (GetToken (false))
	{
		q2brushface = true;
		facecontents = atoi(token);
		if (GetToken (false))
		{
			faceflags = atoi(token);
			if (GetToken (false))
			{
				q2brushface = false;
				q3brushface = true;
				facevalue = atoi(token);
			}
		}
	}
	// skip trailing info (the 3 q3 .map parameters for example)
	while (GetToken (false));

	if (DotProduct(plane.normal, plane.normal) < 0.1)
	{
		printf ("WARNING: brush plane with no normal on line %d\n", scriptline);
		return;
	}

	if (bpface)
	{
		// fake proper texture vectors from QuakeEd style
		TextureAxisFromPlane(&plane, vecs[0], vecs[1], true);
		// FIXME: deal with the bp stuff here
		printf("warning: brush primitive texturing not yet supported (line %d)\n", scriptline);
		// generic texturing
		tx.vecs[0][0] = vecs[0][0];
		tx.vecs[0][1] = vecs[0][1];
		tx.vecs[0][2] = vecs[0][2];
		tx.vecs[0][3] = vecs[0][3];
		tx.vecs[1][0] = vecs[1][0];
		tx.vecs[1][1] = vecs[1][1];
		tx.vecs[1][2] = vecs[1][2];
		tx.vecs[1][3] = vecs[1][3];
	}
	else
	{
		if (hltexdef)
		{
			for (i = 0; i < 2; i++)
			{
				d = 1.0 / (scale[i] ? scale[i] : 1.0);
				for (j = 0; j < 3; j++)
					tx.vecs[i][j] = vecs[i][j] * d;
				tx.vecs[i][3] = vecs[i][3] /*+ DotProduct(origin, tx.vecs[i])*/;
// Sajt: ripped the commented out bit from the HL compiler code, not really sure what it is exactly doing
// 'origin': origin set on bmodel by origin brush or origin key
			}
		}
		else
		{
			// fake proper texture vectors from QuakeEd style
			TextureAxisFromPlane(&plane, vecs[0], vecs[1], q3brushface);

			// rotate axis
				 if (rotate ==  0) {sinv = 0;cosv = 1;}
			else if (rotate == 90) {sinv = 1;cosv = 0;}
			else if (rotate == 180) {sinv = 0;cosv = -1;}
			else if (rotate == 270) {sinv = -1;cosv = 0;}
			else {ang = rotate * (Q_PI / 180);sinv = sin(ang);cosv = cos(ang);}

			// LordHavoc: I don't quite understand this
			for (sv = 0;sv < 2 && !vecs[0][sv];sv++);
			for (tv = 0;tv < 2 && !vecs[1][tv];tv++);

			for (i = 0;i < 2;i++)
			{
				// rotate
				ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
				nt = sinv * vecs[i][sv] + cosv * vecs[i][tv];
				vecs[i][sv] = ns;
				vecs[i][tv] = nt;
				// scale and store into texinfo
				d = 1.0 / (scale[i] ? scale[i] : 1.0);
				for (j = 0;j < 3;j++)
					tx.vecs[i][j] = vecs[i][j] * d;
				tx.vecs[i][3] = vecs[i][3];
			}
		}
	}

	/*
	// LordHavoc: fix for CheckFace: point off plane errors in some maps (most notably QOOLE ones),
	// and hopefully preventing most 'portal clipped away' warnings
	VectorNormalize (plane.normal);
	for (j = 0;j < 3;j++)
		plane.normal[j] = (Q_rint((vec_t) plane.normal[j] * (vec_t) 8.0)) * (vec_t) (1.0 / 8.0);
	VectorNormalize (plane.normal);
	plane.dist = DotProduct (t3, plane.normal);
	d = (Q_rint(plane.dist * 8.0)) * (1.0 / 8.0);
	//if (fabs(d - plane.dist) >= (0.4 / 8.0))
	//	printf("WARNING: correcting minor math errors in brushface on line %d\n", scriptline);
	plane.dist = d;
	*/

	/*
	VectorNormalize (plane.normal);
	plane.dist = DotProduct (t3, plane.normal);

	VectorCopy(plane.normal, v);
	//for (j = 0;j < 3;j++)
	//	v[j] = (Q_rint((vec_t) v[j] * (vec_t) 32.0)) * (vec_t) (1.0 / 32.0);
	VectorNormalize (v);
	d = (Q_rint(DotProduct (t3, v) * 8.0)) * (1.0 / 8.0);

	// if deviation is too high, warn  (frequently happens on QOOLE maps)
	if (fabs(DotProduct(v, plane.normal) - 1.0) > (0.5 / 32.0)
	 || fabs(d - plane.dist) >= (0.25 / 8.0))
		printf("WARNING: minor misalignment of brushface on line %d\n"
			   "normal     %f %f %f (l: %f d: %f)\n"
			   "rounded to %f %f %f (l: %f d: %f r: %f)\n",
			   scriptline,
			   (vec_t) plane.normal[0], (vec_t) plane.normal[1], (vec_t) plane.normal[2], (vec_t) sqrt(DotProduct(plane.normal, plane.normal)), (vec_t) DotProduct (t3, plane.normal),
			   (vec_t) v[0], (vec_t) v[1], (vec_t) v[2], (vec_t) sqrt(DotProduct(v, v)), (vec_t) DotProduct(t3, v), (vec_t) d);
	//VectorCopy(v, plane.normal);
	//plane.dist = d;
	*/

	b = *brushpointer;
	if (b)
	{
		// if the three points are all on a previous plane, it is a
		// duplicate plane
		for (f2 = b->faces ; f2 ; f2=f2->next)
		{
			for (i = 0;i < 3;i++)
			{
				d = DotProduct(planepts[i],f2->plane.normal) - f2->plane.dist;
				if (d < -ON_EPSILON || d > ON_EPSILON)
					break;
			}
			if (i==3)
				break;
		}
		if (f2)
		{
			printf ("WARNING: brush with duplicate plane (first point is at %g %g %g, .map file line number %d)\n", planepts[0][0], planepts[0][1], planepts[0][2], scriptline);
			return;
		}
	}
	else
	{
		b = &mapbrushes[nummapbrushes];
		nummapbrushes++;
		b->next = ent->brushes;
		ent->brushes = b;
		*brushpointer = b;
	}

	f = qmalloc(sizeof(mface_t));
	f->next = b->faces;
	b->faces = f;
	f->plane = plane;
	f->texinfo = FindTexinfo (&tx);
	nummapbrushfaces++;
}
/*
================
Entity_Parse

If onlypairs is set, the classname info will not
be looked up, and the entity will not be added
to the global list.  Used for parsing the project.
================
*/
entity_t	*Entity_Parse (qboolean onlypairs, brush_t* pList)
{
	entity_t	*ent;
	eclass_t	*e;
	brush_t		*b;
	vec3_t		mins, maxs;
	epair_t		*ep;
	qboolean	has_brushes;
#ifdef SOF
	float		scale;
#endif

	if (!GetToken (true))
		return NULL;

	if (strcmp (token, "{") )
		Error ("ParseEntity: { not found");
	
	ent = (entity_t*)qmalloc (sizeof(*ent));
	ent->brushes.onext = ent->brushes.oprev = &ent->brushes;

	do
	{
		if (!GetToken (true))
    {
			Warning ("ParseEntity: EOF without closing brace");
      return NULL;
    }
		if (!strcmp (token, "}") )
			break;
		if (!strcmp (token, "{") )
		{
			b = Brush_Parse ();
      if (b != NULL)
      {
			  b->owner = ent;

			  // add to the end of the entity chain
			  b->onext = &ent->brushes;
			  b->oprev = ent->brushes.oprev;
			  ent->brushes.oprev->onext = b;
			  ent->brushes.oprev = b;
      }
      else
      {
        break;
      }
    
		}
		else
		{
			ep = ParseEpair ();
			{
				// update: the original code here may have been simple, but it meant that every map load/save
				//	the key/value pair fields were reversed in the save file, which messes up SourceSafe when it
				//	tries to delta the two versions during check-in... -slc
#if 0
				ep->next = ent->epairs;
				ent->epairs = ep;
#else
				// join this onto the END of the chain instead...
				//
				if (ent->epairs == NULL)	// special case for if there isn't a chain yet... :-)
				{
					ep->next = ent->epairs;
					ent->epairs = ep;
				}
				else
				{						
					for (epair_t* ep2 = ent->epairs ; ep2 ; ep2=ep2->next)
					{
						if (ep2->next == NULL)
						{
							// found the end, so...
							//
							ep2->next = ep;							
							ep->next = NULL;
							break;
						}
					}
				}
#endif
			}
		}
	} while (1);

	if (onlypairs)
		return ent;

	if (ent->brushes.onext == &ent->brushes)
		has_brushes = false;
	else
		has_brushes = true;

	GetVectorForKey (ent, "origin", ent->origin);

	e = Eclass_ForName (ValueForKey (ent, "classname"), has_brushes);
	ent->eclass = e;
	if (e->fixedsize)
	{	// fixed size entity
		if (ent->brushes.onext != &ent->brushes)
		{
			printf ("Warning: Fixed size entity with brushes\n");
#if 0
			while (ent->brushes.onext != &ent->brushes)
			{	// FIXME: this will free the entity and crash!
				Brush_Free (b);
			}
#endif
      ent->brushes.next = ent->brushes.prev = &ent->brushes;
		}

    // create a custom brush
		VectorAdd (e->mins, ent->origin, mins);
		VectorAdd (e->maxs, ent->origin, maxs);

    float a = 0;
    if (strnicmp(e->name, "misc_model",10) == 0)
    {
      char* p = ValueForKey(ent, "model");
      if (p != NULL && strlen(p) > 0)
      {
        vec3_t vMin, vMax;
        a = FloatForKey (ent, "angle");
		gEntityToSetBoundsOf = ent;
        if (GetCachedModel(ent, p, vMin, vMax))
        {
	      // create a custom brush
	      VectorAdd (ent->md3Class->mins, ent->origin, mins);
	      VectorAdd (ent->md3Class->maxs, ent->origin, maxs);
        }
      }
    }
#ifdef SOF
	if (strnicmp(e->name, "misc_",			5) == 0 ||
		strnicmp(e->name, "light_",			6) == 0 ||
		strnicmp(e->name, "m_",				2) == 0 ||
		strnicmp(e->name, "item_weapon_",	12)== 0 ||
		strnicmp(e->name, "item_ammo_",		10)== 0
		)
		a = FloatForKey (ent, "angle");
#endif		
		b = Brush_Create (mins, maxs, &e->texdef);
///////
		b->owner = ent;

		b->onext = ent->brushes.onext;
		b->oprev = &ent->brushes;
		ent->brushes.onext->oprev = b;
		ent->brushes.onext = b;
///////
		Brush_Build(b);

#ifdef SOF
		scale = FloatForKey (ent, "scale");
		if (scale)
		{
		  Brush_Scale2(e, b, scale, ent->origin,false);
		}
#endif

//		if (a)
//		{
//			vec3_t vAngle;
//			vAngle[0] = vAngle[1] = 0;
//			vAngle[2] = a;
//			Brush_Rotate(b, vAngle, ent->origin, false);
//		}

/*
		b->owner = ent;

		b->onext = ent->brushes.onext;
		b->oprev = &ent->brushes;
		ent->brushes.onext->oprev = b;
		ent->brushes.onext = b;
*/
		// do this AFTER doing the brush stuff just above, so don't join to the other "if (a)"...
		//
		if (a)
		{
			// pick any old value to rotate away to, then back from, to avoid 0/360 weirdness on key-compares
			//
			SetKeyValue(ent, "angle", "0",			false);	// false = no tracking, ie just set the angle and nothing else			
			SetKeyValue(ent, "angle", va("%g",a),	true);	// true = do tracking, ie actually do the brush rotate
		}
	}
	else
	{	// brush entity
		if (ent->brushes.next == &ent->brushes)
			printf ("Warning: Brush entity with no brushes\n");
	}

	// add all the brushes to the main list
  if (pList)
  {
	  for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
    {
		  b->next = pList->next;
		  pList->next->prev = b;
		  b->prev = pList;
		  pList->next = b;
    }
  }

	return ent;
}