Beispiel #1
0
/*
==================
AddAnimatingTextures
==================
*/
void AddAnimatingTextures (void)
{
	int		base;
	int		i, j, k;
	char	name[32];

	base = nummiptex;
	
	for (i=0 ; i<base ; i++)
	{
		if (miptex[i][0] != '+')
			continue;
		strcpy (name, miptex[i]);

		for (j=0 ; j<20 ; j++)
		{
			if (j < 10)
				name[1] = '0'+j;
			else
				name[1] = 'A'+j-10;		// alternate animation
			

		// see if this name exists in the wadfile
			for (k=0 ; k<wadinfo.numlumps ; k++)
				if (!strcmp(name, lumpinfo[k].name))
				{
					FindMiptex (name);	// add to the miptex list
					break;
				}
		}
	}
	
	printf ("added %i texture frames\n", nummiptex - base);
}
Beispiel #2
0
void AddAnimatingTextures (void)
{
	int		base;
	int		i, j;
	char	name[32];

	base = nummiptex;

	for (i = 0;i < base;i++)
	{
		if (miptex[i][0] != '+')
			continue;
		CleanupName (miptex[i], name);

		for (j = 0;j < 20;j++)
		{
			if (j < 10)
				name[1] = j + '0';
			else
				name[1] = j + 'A' - 10;		// alternate animation

			if (!MipTexUsed(name) && FindMipTexFile(name))
				FindMiptex (name);
		}
	}
}
Beispiel #3
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
int FindMiptex (char *name)
{
	int i;
	char path[1024];
	miptex_t	*mt;

	for (i = 0; i < nummiptex; i++)
	{
		if (!strcmp (name, textureref[i].name))
		{
			return i;
		} //end if
	} //end for
	if (nummiptex == MAX_MAP_TEXTURES)
		Error ("MAX_MAP_TEXTURES");
	strcpy (textureref[i].name, name);

	// load the miptex to get the flags and values
	sprintf (path, "%stextures/%s.wal", gamedir, name);
	if (TryLoadFile (path, (void **)&mt) != -1)
	{
		textureref[i].value = LittleLong (mt->value);
		textureref[i].flags = LittleLong (mt->flags);
		textureref[i].contents = LittleLong (mt->contents);
		strcpy (textureref[i].animname, mt->animname);
		FreeMemory(mt);
	} //end if
	nummiptex++;

	if (textureref[i].animname[0])
		FindMiptex (textureref[i].animname);

	return i;
} //end of the function FindMipTex
Beispiel #4
0
// =====================================================================================
//  AddAnimatingTextures
// =====================================================================================
void            AddAnimatingTextures()
{
    int             base;
    int             i, j, k;
    char            name[MAXWADNAME];

    base = nummiptex;

    for (i = 0; i < base; i++)
    {
        if ((miptex[i].name[0] != '+') && (miptex[i].name[0] != '-'))
        {
            continue;
        }

        safe_strncpy(name, miptex[i].name, MAXWADNAME);

        for (j = 0; j < 20; j++)
        {
            if (j < 10)
            {
                name[1] = '0' + j;
            }
            else
            {
                name[1] = 'A' + j - 10;                    // alternate animation
            }

            // see if this name exists in the wadfile
            for (k = 0; k < nTexLumps; k++)
            {
                if (!strcmp(name, lumpinfo[k].name))
                {
                    FindMiptex(name);                      // add to the miptex list
                    break;
                }
            }
        }
    }

    if (nummiptex - base)
    {
        Log("added %i additional animating textures.\n", nummiptex - base);
    }
}
Beispiel #5
0
static void
WADList_AddAnimationFrames(const wad_t *wadlist)
{
    int oldcount, i, j;
    miptex_t name;

    oldcount = map.nummiptex;

    for (i = 0; i < oldcount; i++) {
        if (map.miptex[i][0] != '+')
            continue;
        snprintf(name, sizeof(name), "%s", map.miptex[i]);

        /* Search for all animations (0-9) and alt-animations (A-J) */
        for (j = 0; j < 20; j++) {
            name[1] = (j < 10) ? '0' + j : 'a' + j - 10;
            if (WADList_FindTexture(wadlist, name))
                FindMiptex(name);
        }
    }

    Message(msgStat, "%8d texture frames added", map.nummiptex - oldcount);
}
Beispiel #6
0
/**
 * @brief Parses a brush from the map file
 * @sa FindMiptex
 * @param[in] mapent The entity the brush to parse belongs to
 * @param[in] filename The map filename, used to derive the name for the footsteps file
 */
static void ParseBrush (entity_t* mapent, const char* filename)
{
	int j, k;
	brush_texture_t td;
	vec3_t planepts[3];
	const int checkOrFix = config.performMapCheck || config.fixMap ;

	if (nummapbrushes == MAX_MAP_BRUSHES)
		Sys_Error("nummapbrushes == MAX_MAP_BRUSHES (%i)", nummapbrushes);

	mapbrush_t* b = &mapbrushes[nummapbrushes];
	OBJZERO(*b);
	b->original_sides = &brushsides[nummapbrushsides];
	b->entitynum = num_entities - 1;
	b->brushnum = nummapbrushes - mapent->firstbrush;

	do {
		if (Q_strnull(GetToken()))
			break;
		if (*parsedToken == '}')
			break;

		if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
			Sys_Error("nummapbrushsides == MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides);
		side_t* side = &brushsides[nummapbrushsides];

		/* read the three point plane definition */
		for (int i = 0; i < 3; i++) {
			if (i != 0)
				GetToken();
			if (*parsedToken != '(')
				Sys_Error("parsing brush");

			for (j = 0; j < 3; j++) {
				GetToken();
				planepts[i][j] = atof(parsedToken);
			}

			GetToken();
			if (*parsedToken != ')')
				Sys_Error("parsing brush");
		}

		/* read the texturedef */
		GetToken();
		if (strlen(parsedToken) >= MAX_TEXPATH) {
			if (config.performMapCheck || config.fixMap)
				Com_Printf("  ");/* hack to make this look like output from Check_Printf() */
			Com_Printf("ParseBrush: texture name too long (limit %i): %s\n", MAX_TEXPATH, parsedToken);
			if (config.fixMap)
				Sys_Error("Aborting, as -fix is active and saving might corrupt *.map by truncating texture name");
		}
		Q_strncpyz(td.name, parsedToken, sizeof(td.name));

		td.shift[0] = atof(GetToken());
		td.shift[1] = atof(GetToken());
		td.rotate = atof(GetToken());
		td.scale[0] = atof(GetToken());
		td.scale[1] = atof(GetToken());

		/* find default flags and values */
		const int mt = FindMiptex(td.name);
		side->surfaceFlags = td.surfaceFlags = side->contentFlags = td.value = 0;

		if (TokenAvailable()) {
			side->contentFlags = atoi(GetToken());
			side->surfaceFlags = td.surfaceFlags = atoi(GetToken());
			td.value = atoi(GetToken());
		}

		/* if in check or fix mode, let them choose to do this (with command line options),
		 * and then call is made elsewhere */
		if (!checkOrFix) {
			SetImpliedFlags(side, &td, b);
			/* if no other content flags are set - make this solid */
			if (!checkOrFix && side->contentFlags == 0)
				side->contentFlags = CONTENTS_SOLID;
		}

		/* translucent objects are automatically classified as detail and window */
		if (side->surfaceFlags & (SURF_BLEND33 | SURF_BLEND66 | SURF_ALPHATEST)) {
			side->contentFlags |= CONTENTS_DETAIL;
			side->contentFlags |= CONTENTS_TRANSLUCENT;
			side->contentFlags |= CONTENTS_WINDOW;
			side->contentFlags &= ~CONTENTS_SOLID;
		}
		if (config.fulldetail)
			side->contentFlags &= ~CONTENTS_DETAIL;
		if (!checkOrFix) {
			if (!(side->contentFlags & ((LAST_VISIBLE_CONTENTS - 1)
				| CONTENTS_ACTORCLIP | CONTENTS_WEAPONCLIP | CONTENTS_LIGHTCLIP)))
				side->contentFlags |= CONTENTS_SOLID;

			/* hints and skips are never detail, and have no content */
			if (side->surfaceFlags & (SURF_HINT | SURF_SKIP)) {
				side->contentFlags = 0;
				side->surfaceFlags &= ~CONTENTS_DETAIL;
			}
		}

		/* check whether the flags are ok */
		CheckFlags(side, b);

		/* generate a list of textures that should have footsteps when walking on them */
		if (mt > 0 && (side->surfaceFlags & SURF_FOOTSTEP))
			GenerateFootstepList(filename, mt);
		GenerateMaterialFile(filename, mt, side);

		/* find the plane number */
		int planenum = PlaneFromPoints(b, planepts[0], planepts[1], planepts[2]);
		if (planenum == PLANENUM_LEAF) {
			Com_Printf("Entity %i, Brush %i: plane with no normal\n", b->entitynum, b->brushnum);
			continue;
		}

		for (j = 0; j < 3; j++)
			VectorCopy(planepts[j], mapplanes[planenum].planeVector[j]);

		/* see if the plane has been used already */
		for (k = 0; k < b->numsides; k++) {
			const side_t* s2 = b->original_sides + k;
			if (s2->planenum == planenum) {
				Com_Printf("Entity %i, Brush %i: duplicate plane\n", b->entitynum, b->brushnum);
				break;
			}
			if (s2->planenum == (planenum ^ 1)) {
				Com_Printf("Entity %i, Brush %i: mirrored plane\n", b->entitynum, b->brushnum);
				break;
			}
		}
		if (k != b->numsides)
			continue;		/* duplicated */

		/* keep this side */
		side = b->original_sides + b->numsides;
		side->planenum = planenum;
		side->texinfo = TexinfoForBrushTexture(&mapplanes[planenum],
			&td, vec3_origin, side->contentFlags & CONTENTS_TERRAIN);
		side->brush = b;

		/* save the td off in case there is an origin brush and we
		 * have to recalculate the texinfo */
		side_brushtextures[nummapbrushsides] = td;

		Verb_Printf(VERB_DUMP, "Brush %i Side %i (%f %f %f) (%f %f %f) (%f %f %f) texinfo:%i[%s] plane:%i\n", nummapbrushes, nummapbrushsides,
			planepts[0][0], planepts[0][1], planepts[0][2],
			planepts[1][0], planepts[1][1], planepts[1][2],
			planepts[2][0], planepts[2][1], planepts[2][2],
			side->texinfo, td.name, planenum);

		nummapbrushsides++;
		b->numsides++;
	} while (1);

	/* get the content for the entire brush */
	b->contentFlags = BrushContents(b);

	/* copy all set face contentflags to the brush contentflags */
	for (int m = 0; m < b->numsides; m++)
		b->contentFlags |= b->original_sides[m].contentFlags;

	/* set DETAIL, TRANSLUCENT contentflags on all faces, if they have been set on any.
	 * called separately, if in check/fix mode */
	if (!checkOrFix)
		CheckPropagateParserContentFlags(b);

	/* allow detail brushes to be removed */
	if (config.nodetail && (b->contentFlags & CONTENTS_DETAIL)) {
		b->numsides = 0;
		return;
	}

	/* allow water brushes to be removed */
	if (config.nowater && (b->contentFlags & CONTENTS_WATER)) {
		b->numsides = 0;
		return;
	}

	/* create windings for sides and bounds for brush */
	MakeBrushWindings(b);

	Verb_Printf(VERB_DUMP, "Brush %i mins (%f %f %f) maxs (%f %f %f)\n", nummapbrushes,
		b->mbBox.mins[0], b->mbBox.mins[1], b->mbBox.mins[2],
		b->mbBox.maxs[0], b->mbBox.maxs[1], b->mbBox.maxs[2]);

	/* origin brushes are removed, but they set
	 * the rotation origin for the rest of the brushes (like func_door)
	 * in the entity. After the entire entity is parsed, the planenums
	 * and texinfos will be adjusted for the origin brush */
	if (!checkOrFix && (b->contentFlags & CONTENTS_ORIGIN)) {
		char string[32];
		vec3_t origin;

		if (num_entities == 1) {
			Sys_Error("Entity %i, Brush %i: origin brushes not allowed in world"
				, b->entitynum, b->brushnum);
			return;
		}

		b->mbBox.getCenter(origin);

		Com_sprintf(string, sizeof(string), "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
		SetKeyValue(&entities[b->entitynum], "origin", string);
		Verb_Printf(VERB_EXTRA, "Entity %i, Brush %i: set origin to %s\n", b->entitynum, b->brushnum, string);

		VectorCopy(origin, entities[b->entitynum].origin);

		/* don't keep this brush */
		b->numsides = 0;

		return;
	}

	if (!checkOrFix)
		AddBrushBevels(b);

	nummapbrushes++;
	mapent->numbrushes++;
}
Beispiel #7
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
int TexinfoForBrushTexture(plane_t *plane, brush_texture_t *bt, vec3_t origin)
{
	vec3_t	vecs[2];
	int		sv, tv;
	vec_t	ang, sinv, cosv;
	vec_t	ns, nt;
	texinfo_t	tx, *tc;
	int		i, j, k;
	float	shift[2];
	brush_texture_t		anim;
	int				mt;

	if (!bt->name[0])
		return 0;

	memset (&tx, 0, sizeof(tx));
	strcpy (tx.texture, bt->name);

	TextureAxisFromPlane(plane, vecs[0], vecs[1]);

	shift[0] = DotProduct (origin, vecs[0]);
	shift[1] = DotProduct (origin, vecs[1]);

	if (!bt->scale[0])
		bt->scale[0] = 1;
	if (!bt->scale[1])
		bt->scale[1] = 1;


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

	if (vecs[0][0])
		sv = 0;
	else if (vecs[0][1])
		sv = 1;
	else
		sv = 2;
				
	if (vecs[1][0])
		tv = 0;
	else if (vecs[1][1])
		tv = 1;
	else
		tv = 2;
					
	for (i=0 ; i<2 ; i++)
	{
		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;
	}

	for (i=0 ; i<2 ; i++)
		for (j=0 ; j<3 ; j++)
			tx.vecs[i][j] = vecs[i][j] / bt->scale[i];

	tx.vecs[0][3] = bt->shift[0] + shift[0];
	tx.vecs[1][3] = bt->shift[1] + shift[1];
	tx.flags = bt->flags;
	tx.value = bt->value;

	//
	// find the texinfo
	//
	tc = texinfo;
	for (i=0 ; i<numtexinfo ; i++, tc++)
	{
		if (tc->flags != tx.flags)
			continue;
		if (tc->value != tx.value)
			continue;
		for (j=0 ; j<2 ; j++)
		{
			if (strcmp (tc->texture, tx.texture))
				goto skip;
			for (k=0 ; k<4 ; k++)
			{
				if (tc->vecs[j][k] != tx.vecs[j][k])
					goto skip;
			}
		}
		return i;
skip:;
	}
	*tc = tx;
	numtexinfo++;

	// load the next animation
	mt = FindMiptex (bt->name);
	if (textureref[mt].animname[0])
	{
		anim = *bt;
		strcpy (anim.name, textureref[mt].animname);
		tc->nexttexinfo = TexinfoForBrushTexture (plane, &anim, origin);
	}
	else
		tc->nexttexinfo = -1;


	return i;
} //end of the function TexinfoForBrushTexture
Beispiel #8
0
void ParseBrushFace (entity_t *ent, mbrush_t **brushpointer, brushtype_t brushtype)
{
	int			i, j, hltexdef, bpface, brushplane;
//	int			facecontents, faceflags, facevalue, q2brushface, q3brushface;
	vec_t		planepts[3][3], t1[3], t2[3], d, rotate, scale[2], vecs[2][4], ang, sinv, cosv, 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, ")"))
	{
		brushplane = false;
		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
		brushplane = true;
		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

		bp[0][0] = 1;
		bp[0][1] = 0;
		bp[0][2] = 0;
		bp[1][0] = 0;
		bp[1][1] = 1;
		bp[1][2] = 0;
	}
	// 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: line %i: brush plane with no normal\n", scriptline);
		return;
	}

	scale[0] = 1.0 / scale[0];
	scale[1] = 1.0 / scale[1];

	if (bpface)
	{
		// calculate proper texture vectors from GTKRadiant/Doom3 brushprimitives matrix
		float a, ac, as, bc, bs;
		a = -atan2(plane.normal[2], sqrt(plane.normal[0]*plane.normal[0]+plane.normal[1]*plane.normal[1]));
		ac = cos(a);
		as = sin(a);
		a = atan2(plane.normal[1], plane.normal[0]);
		bc = cos(a);
		bs = sin(a);
		vecs[0][0] = -bs;
		vecs[0][1] = bc;
		vecs[0][2] = 0;
		vecs[1][0] = -as*bc;
		vecs[1][1] = -as*bs;
		vecs[1][2] = -ac;
		tx.vecs[0][0] = bp[0][0] * vecs[0][0] + bp[0][1] * vecs[1][0];
		tx.vecs[0][1] = bp[0][0] * vecs[0][1] + bp[0][1] * vecs[1][1];
		tx.vecs[0][2] = bp[0][0] * vecs[0][2] + bp[0][1] * vecs[1][2];
		tx.vecs[0][3] = bp[0][0] * vecs[0][3] + bp[0][1] * vecs[1][3] + bp[0][2];
		tx.vecs[1][0] = bp[1][0] * vecs[0][0] + bp[1][1] * vecs[1][0];
		tx.vecs[1][1] = bp[1][0] * vecs[0][1] + bp[1][1] * vecs[1][1];
		tx.vecs[1][2] = bp[1][0] * vecs[0][2] + bp[1][1] * vecs[1][2];
		tx.vecs[1][3] = bp[1][0] * vecs[0][3] + bp[1][1] * vecs[1][3] + bp[1][2];
	}
	else if (hltexdef)
	{
		// HL texture vectors are almost ready to go
		for (i = 0; i < 2; i++)
		{
			for (j = 0; j < 3; j++)
				tx.vecs[i][j] = vecs[i][j] * scale[i];
			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

		// texture rotation around the plane normal
			 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);}

		if (fabs(plane.normal[2]) < fabs(plane.normal[0]))
		{
			if (fabs(plane.normal[0]) < fabs(plane.normal[1]))
			{
				// Y primary
				VectorSet4(tx.vecs[0],  cosv*scale[0],  0,  sinv*scale[0], vecs[0][3]);
				VectorSet4(tx.vecs[1],  sinv*scale[1],  0, -cosv*scale[1], vecs[1][3]);
			}
			else
			{
				// X primary
				VectorSet4(tx.vecs[0],  0,  cosv*scale[0],  sinv*scale[0], vecs[0][3]);
				VectorSet4(tx.vecs[1],  0,  sinv*scale[1], -cosv*scale[1], vecs[1][3]);
			}
		}
		else if (fabs(plane.normal[2]) < fabs(plane.normal[1]))
		{
			// Y primary
			VectorSet4(tx.vecs[0],  cosv*scale[0],  0,  sinv*scale[0], vecs[0][3]);
			VectorSet4(tx.vecs[1],  sinv*scale[1],  0, -cosv*scale[1], vecs[1][3]);
		}
		else
		{
			// Z primary
			VectorSet4(tx.vecs[0],  cosv*scale[0],  sinv*scale[0], 0, vecs[0][3]);
			VectorSet4(tx.vecs[1],  sinv*scale[1], -cosv*scale[1], 0, vecs[1][3]);
		}
		//printf("plane + rotate scale = texture vectors:\n(%f %f %f %f) + [%f %f %f] =\n[%f %f %f %f] [%f %f %f %f]\n", plane.normal[0], plane.normal[1], plane.normal[2], plane.dist, rotate, scale[0], scale[1], tx.vecs[0][0], tx.vecs[0][1], tx.vecs[0][2], tx.vecs[0][3], tx.vecs[1][0], tx.vecs[1][1], tx.vecs[1][2], tx.vecs[1][3]);
	}

	for (i = 0;i < 2;i++)
	{
		for (j = 0;j < 4;j++)
		{
			if (tx.vecs[i][j] > -BOGUS_RANGE && tx.vecs[i][j] < BOGUS_RANGE)
				continue;
			printf( "WARNING: line %i: corrupt texture mapping vectors, using defaults\n", scriptline);
			cosv = 1;
			sinv = 0;
			scale[0] = 1;
			scale[1] = 1;
			vecs[0][3] = 0;
			vecs[1][3] = 0;
			if (fabs(plane.normal[2]) < fabs(plane.normal[0]))
			{
				if (fabs(plane.normal[0]) < fabs(plane.normal[1]))
				{
					// Y primary
					VectorSet4(tx.vecs[0],  cosv*scale[0],  0,  sinv*scale[0], vecs[0][3]);
					VectorSet4(tx.vecs[1],  sinv*scale[1],  0, -cosv*scale[1], vecs[1][3]);
				}
				else
				{
					// X primary
					VectorSet4(tx.vecs[0],  0,  cosv*scale[0],  sinv*scale[0], vecs[0][3]);
					VectorSet4(tx.vecs[1],  0,  sinv*scale[1], -cosv*scale[1], vecs[1][3]);
				}
			}
			else if (fabs(plane.normal[2]) < fabs(plane.normal[1]))
			{
				// Y primary
				VectorSet4(tx.vecs[0],  cosv*scale[0],  0,  sinv*scale[0], vecs[0][3]);
				VectorSet4(tx.vecs[1],  sinv*scale[1],  0, -cosv*scale[1], vecs[1][3]);
			}
			else
			{
				// Z primary
				VectorSet4(tx.vecs[0],  cosv*scale[0],  sinv*scale[0], 0, vecs[0][3]);
				VectorSet4(tx.vecs[1],  sinv*scale[1], -cosv*scale[1], 0, vecs[1][3]);
			}
			break;
		}
	}
	
	/*
	// 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: line %i: correcting minor math errors in brushface\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: line %i: minor misalignment of brushface\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 (brushplane)
		{
			for (f2 = b->faces ; f2 ;f2=f2->next)
				if (VectorCompare(plane.normal, f2->plane.normal) && fabs(plane.dist - f2->plane.dist) < ON_EPSILON)
					break;
			if (f2)
			{
				printf ("WARNING: line %i: brush with duplicate plane\n", scriptline);
				return;
			}
		}
		else
		{
			// 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: line %i: brush with duplicate plane\n", scriptline);
				return;
			}
		}
	}
	else
	{
		b = &mapbrushes[nummapbrushes];
		nummapbrushes++;
		b->next = ent->brushes;
		ent->brushes = b;
		b->scriptline = scriptline;
		*brushpointer = b;
	}

	f = qmalloc(sizeof(mface_t));
	f->next = b->faces;
	b->faces = f;
	f->scriptline = scriptline;
	f->plane = plane;
	f->texinfo = FindTexinfo (&tx);
	nummapbrushfaces++;
}
Beispiel #9
0
/*
=================
ParseBrush
=================
*/
void ParseBrush (void)
{
	mbrush_t	*b;
	mface_t		*f, *f2;
	vec3_t		planepts[3];
	vec3_t		t1, t2, t3;
	int			i,j;
	texinfo_t	tx;
	vec_t		d;
	float		shift[2], rotate, scale[2];

	b = &mapbrushes[nummapbrushes];
	nummapbrushes++;
	b->next = mapent->brushes;
	mapent->brushes = b;

	do
	{
		if (!GetToken (true))
			break;
		if (!strcmp (token, "}") )
			break;

		// read the three point plane definition
		for (i=0 ; i<3 ; i++)
		{
			if (i != 0)
				GetToken (true);
			if (strcmp (token, "(") )
				Error ("parsing brush");

			for (j=0 ; j<3 ; j++)
			{
				GetToken (false);
				planepts[i][j] = atof(token); // LordHavoc: float coords
			}

			GetToken (false);
			if (strcmp (token, ")") )
				Error ("parsing brush");
		}

		fflush(stdout);
		// read the texturedef
		memset (&tx, 0, sizeof(tx));
		GetToken (false);
		tx.miptex = FindMiptex (token);
		GetToken (false);
		shift[0] = atof(token); // LordHavoc: float coords
		GetToken (false);
		shift[1] = atof(token); // LordHavoc: float coords
		GetToken (false);
		rotate = atof(token);	 // LordHavoc: float coords
		GetToken (false);
		scale[0] = atof(token); // LordHavoc: was already float coords
		GetToken (false);
		scale[1] = atof(token); // LordHavoc: was already float coords

		// 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\n");
			continue;
		}

		f = malloc(sizeof(mface_t));
		f->next = b->faces;
		b->faces = f;

		// convert to a vector / dist plane
		for (j=0 ; j<3 ; j++)
		{
			t1[j] = planepts[0][j] - planepts[1][j];
			t2[j] = planepts[2][j] - planepts[1][j];
			t3[j] = planepts[1][j];
		}

		CrossProduct(t1,t2, f->plane.normal);
		if (VectorCompare (f->plane.normal, vec3_origin))
		{
			printf ("WARNING: brush plane with no normal\n");
			b->faces = f->next;
			free (f);
			break;
		}
		VectorNormalize (f->plane.normal);
		f->plane.dist = DotProduct (t3, f->plane.normal);

		//
		// fake proper texture vectors from QuakeEd style
		//
		{
			vec3_t	vecs[2];
			int		sv, tv;
			float	ang, sinv, cosv;
			float	ns, nt;

			TextureAxisFromPlane(&f->plane, vecs[0], vecs[1]);

			if (!scale[0])
				scale[0] = 1;
			if (!scale[1])
				scale[1] = 1;

			// 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 / 180 * Q_PI;
				sinv = sin(ang);
				cosv = cos(ang);
			}

			if (vecs[0][0])
				sv = 0;
			else if (vecs[0][1])
				sv = 1;
			else
				sv = 2;
					
			if (vecs[1][0])
				tv = 0;
			else if (vecs[1][1])
				tv = 1;
			else
				tv = 2;
						
			for (i=0 ; i<2 ; i++)
			{
				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;
			}

			for (i=0 ; i<2 ; i++)
			for (j=0 ; j<3 ; j++)
			tx.vecs[i][j] = vecs[i][j] / scale[i];

			tx.vecs[0][3] = shift[0];
			tx.vecs[1][3] = shift[1];
		}

		// unique the texinfo
		f->texinfo = FindTexinfo (&tx);		
	} while (1);
}
Beispiel #10
0
// =====================================================================================
//  TexinfoForBrushTexture
// =====================================================================================
int             TexinfoForBrushTexture(const plane_t* const plane, brush_texture_t* bt, const vec3_t origin)
{
    vec3_t          vecs[2];
    int             sv, tv;
    vec_t           ang, sinv, cosv;
    vec_t           ns, nt;
    texinfo_t       tx;
    texinfo_t*      tc;
    int             i, j, k;

    memset(&tx, 0, sizeof(tx));
	if(!strncmp(bt->name,"BEVEL",5))
	{
		tx.flags |= TEX_BEVEL;
		safe_strncpy(bt->name,"NULL",5);
	}
    tx.miptex = FindMiptex(bt->name);

    // Note: FindMiptex() still needs to be called here to add it to the global miptex array

    // Very Sleazy Hack 104 - since the tx.miptex index will be bogus after we sort the miptex array later
    // Put the string name of the miptex in this "index" until after we are done sorting it in WriteMiptex().
    tx.miptex = texmap64_store(strdup(bt->name));

    // set the special flag
    if (bt->name[0] == '*'
        || !strncasecmp(bt->name, "sky", 3)

// =====================================================================================
//Cpt_Andrew - Env_Sky Check
// =====================================================================================
        || !strncasecmp(bt->name, "env_sky", 5)
// =====================================================================================

        || !strncasecmp(bt->name, "clip", 4)
        || !strncasecmp(bt->name, "origin", 6)
#ifdef ZHLT_NULLTEX // AJM
        || !strncasecmp(bt->name, "null", 4)
#endif
        || !strncasecmp(bt->name, "aaatrigger", 10)
       )
    {
        tx.flags |= TEX_SPECIAL;
    }

    if (bt->txcommand)
    {
        memcpy(tx.vecs, bt->vects.quark.vects, sizeof(tx.vecs));
        if (origin[0] || origin[1] || origin[2])
        {
            tx.vecs[0][3] += DotProduct(origin, tx.vecs[0]);
            tx.vecs[1][3] += DotProduct(origin, tx.vecs[1]);
        }
    }
    else
    {
        if (g_nMapFileVersion < 220)
        {
            TextureAxisFromPlane(plane, vecs[0], vecs[1]);
        }

        if (!bt->vects.valve.scale[0])
        {
            bt->vects.valve.scale[0] = 1;
        }
        if (!bt->vects.valve.scale[1])
        {
            bt->vects.valve.scale[1] = 1;
        }

        if (g_nMapFileVersion < 220)
        {
            // rotate axis
            if (bt->vects.valve.rotate == 0)
            {
                sinv = 0;
                cosv = 1;
            }
            else if (bt->vects.valve.rotate == 90)
            {
                sinv = 1;
                cosv = 0;
            }
            else if (bt->vects.valve.rotate == 180)
            {
                sinv = 0;
                cosv = -1;
            }
            else if (bt->vects.valve.rotate == 270)
            {
                sinv = -1;
                cosv = 0;
            }
            else
            {
                ang = bt->vects.valve.rotate / 180 * Q_PI;
                sinv = sin(ang);
                cosv = cos(ang);
            }

            if (vecs[0][0])
            {
                sv = 0;
            }
            else if (vecs[0][1])
            {
                sv = 1;
            }
            else
            {
                sv = 2;
            }

            if (vecs[1][0])
            {
                tv = 0;
            }
            else if (vecs[1][1])
            {
                tv = 1;
            }
            else
            {
                tv = 2;
            }

            for (i = 0; i < 2; i++)
            {
                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;
            }

            for (i = 0; i < 2; i++)
            {
                for (j = 0; j < 3; j++)
                {
                    tx.vecs[i][j] = vecs[i][j] / bt->vects.valve.scale[i];
                }
            }
        }
        else
        {
            vec_t           scale;

            scale = 1 / bt->vects.valve.scale[0];
            VectorScale(bt->vects.valve.UAxis, scale, tx.vecs[0]);

            scale = 1 / bt->vects.valve.scale[1];
            VectorScale(bt->vects.valve.VAxis, scale, tx.vecs[1]);
        }

        tx.vecs[0][3] = bt->vects.valve.shift[0] + DotProduct(origin, tx.vecs[0]);
        tx.vecs[1][3] = bt->vects.valve.shift[1] + DotProduct(origin, tx.vecs[1]);
    }

    //
    // find the g_texinfo
    //
    ThreadLock();
    tc = g_texinfo;
    for (i = 0; i < g_numtexinfo; i++, tc++)
    {
        // Sleazy hack 104, Pt 3 - Use strcmp on names to avoid dups
        if (strcmp(texmap64_retrieve((tc->miptex)), texmap64_retrieve((tx.miptex))) != 0)
        {
            continue;
        }
        if (tc->flags != tx.flags)
        {
            continue;
        }
        for (j = 0; j < 2; j++)
        {
            for (k = 0; k < 4; k++)
            {
                if (tc->vecs[j][k] != tx.vecs[j][k])
                {
                    goto skip;
                }
            }
        }
        ThreadUnlock();
        return i;
skip:;
    }

    hlassume(g_numtexinfo < MAX_MAP_TEXINFO, assume_MAX_MAP_TEXINFO);

    *tc = tx;
    g_numtexinfo++;
    ThreadUnlock();
    return i;
}
Beispiel #11
0
/*
=================
ParseBrush
=================
*/
void ParseBrush (entity_t *mapent)
{
	mapbrush_t		*b;
	int			i,j, k;
	int			mt;
	side_t		*side, *s2;
	int			planenum;
	brush_texture_t	td;
	int			planepts[3][3];

	if (nummapbrushes == MAX_MAP_BRUSHES)
		Error ("nummapbrushes == MAX_MAP_BRUSHES");

	b = &mapbrushes[nummapbrushes];
	b->original_sides = &brushsides[nummapbrushsides];
	b->entitynum = num_entities-1;
	b->brushnum = nummapbrushes - mapent->firstbrush;

	do
	{
		if (!GetToken (true))
			break;
		if (!strcmp (token, "}") )
			break;

		if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
			Error ("MAX_MAP_BRUSHSIDES");
		side = &brushsides[nummapbrushsides];

		// read the three point plane definition
		for (i=0 ; i<3 ; i++)
		{
			if (i != 0)
				GetToken (true);
			if (strcmp (token, "(") )
				Error ("parsing brush");
			
			for (j=0 ; j<3 ; j++)
			{
				GetToken (false);
				planepts[i][j] = atoi(token);
			}
			
			GetToken (false);
			if (strcmp (token, ")") )
				Error ("parsing brush");
				
		}


		//
		// read the texturedef
		//
		GetToken (false);
		strcpy (td.name, token);

		GetToken (false);
		td.shift[0] = atoi(token);
		GetToken (false);
		td.shift[1] = atoi(token);
		GetToken (false);
		td.rotate = atoi(token);	
		GetToken (false);
		td.scale[0] = atof(token);
		GetToken (false);
		td.scale[1] = atof(token);

		// find default flags and values
		mt = FindMiptex (td.name);
		td.flags = textureref[mt].flags;
		td.value = textureref[mt].value;
		side->contents = textureref[mt].contents;
		side->surf = td.flags = textureref[mt].flags;

		if (TokenAvailable())
		{
			GetToken (false);
			side->contents = atoi(token);
			GetToken (false);
			side->surf = td.flags = atoi(token);
			GetToken (false);
			td.value = atoi(token);
		}

		// translucent objects are automatically classified as detail
		if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
			side->contents |= CONTENTS_DETAIL;
		if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
			side->contents |= CONTENTS_DETAIL;
		if (fulldetail)
			side->contents &= ~CONTENTS_DETAIL;
		if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 
			| CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST)  ) )
			side->contents |= CONTENTS_SOLID;

		// hints and skips are never detail, and have no content
		if (side->surf & (SURF_HINT|SURF_SKIP) )
		{
			side->contents = 0;
			side->surf &= ~CONTENTS_DETAIL;
		}


		//
		// find the plane number
		//
		planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
		if (planenum == -1)
		{
			printf ("Entity %i, Brush %i: plane with no normal\n"
				, b->entitynum, b->brushnum);
			continue;
		}

		//
		// see if the plane has been used already
		//
		for (k=0 ; k<b->numsides ; k++)
		{
			s2 = b->original_sides + k;
			if (s2->planenum == planenum)
			{
				printf ("Entity %i, Brush %i: duplicate plane\n"
					, b->entitynum, b->brushnum);
				break;
			}
			if ( s2->planenum == (planenum^1) )
			{
				printf ("Entity %i, Brush %i: mirrored plane\n"
					, b->entitynum, b->brushnum);
				break;
			}
		}
		if (k != b->numsides)
			continue;		// duplicated

		//
		// keep this side
		//

		side = b->original_sides + b->numsides;
		side->planenum = planenum;
		side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
			&td, vec3_origin);

		// save the td off in case there is an origin brush and we
		// have to recalculate the texinfo
		side_brushtextures[nummapbrushsides] = td;

		nummapbrushsides++;
		b->numsides++;
	} while (1);

	// get the content for the entire brush
	b->contents = BrushContents (b);

	// allow detail brushes to be removed 
	if (nodetail && (b->contents & CONTENTS_DETAIL) )
	{
		b->numsides = 0;
		return;
	}

	// allow water brushes to be removed
	if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
	{
		b->numsides = 0;
		return;
	}

	// create windings for sides and bounds for brush
	MakeBrushWindings (b);

	// brushes that will not be visible at all will never be
	// used as bsp splitters
	if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
	{
		c_clipbrushes++;
		for (i=0 ; i<b->numsides ; i++)
			b->original_sides[i].texinfo = TEXINFO_NODE;
	}

	//
	// origin brushes are removed, but they set
	// the rotation origin for the rest of the brushes
	// in the entity.  After the entire entity is parsed,
	// the planenums and texinfos will be adjusted for
	// the origin brush
	//
	if (b->contents & CONTENTS_ORIGIN)
	{
		char	string[32];
		vec3_t	origin;

		if (num_entities == 1)
		{
			Error ("Entity %i, Brush %i: origin brushes not allowed in world"
				, b->entitynum, b->brushnum);
			return;
		}

		VectorAdd (b->mins, b->maxs, origin);
		VectorScale (origin, 0.5, origin);

		sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
		SetKeyValue (&entities[b->entitynum], "origin", string);

		VectorCopy (origin, entities[b->entitynum].origin);

		// don't keep this brush
		b->numsides = 0;

		return;
	}

	AddBrushBevels (b);

	nummapbrushes++;
	mapent->numbrushes++;		
}
Beispiel #12
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++;
}
Beispiel #13
0
/*
=================
Q2_ParseBrush
=================
*/
void Q2_ParseBrush(script_t *script, entity_t *mapent)
{
	mapbrush_t      *b;
	int             i, j, k;
	int             mt;
	side_t          *side, *s2;
	int             planenum;
	brush_texture_t td;
	int             planepts[3][3];
	token_t         token;

	if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
	{
		Error("nummapbrushes == MAX_MAPFILE_BRUSHES");
	}

	b                 = &mapbrushes[nummapbrushes];
	b->original_sides = &brushsides[nummapbrushsides];
	b->entitynum      = num_entities - 1;
	b->brushnum       = nummapbrushes - mapent->firstbrush;
	b->leafnum        = -1;

	do
	{
		if (!PS_ReadToken(script, &token))
		{
			break;
		}
		if (!strcmp(token.string, "}"))
		{
			break;
		}

		//IDBUG: mixed use of MAX_MAPFILE_? and MAX_MAP_? this could
		//			lead to out of bound indexing of the arrays
		if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
		{
			Error("MAX_MAPFILE_BRUSHSIDES");
		}
		side = &brushsides[nummapbrushsides];

		//read the three point plane definition
		for (i = 0; i < 3; i++)
		{
			if (i != 0)
			{
				PS_ExpectTokenString(script, "(");
			}
			for (j = 0; j < 3; j++)
			{
				PS_ExpectAnyToken(script, &token);
				planepts[i][j] = atof(token.string);
			} //end for
			PS_ExpectTokenString(script, ")");
		} //end for

		//
		//read the texturedef
		//
		PS_ExpectAnyToken(script, &token);
		strcpy(td.name, token.string);

		PS_ExpectAnyToken(script, &token);
		td.shift[0] = atol(token.string);
		PS_ExpectAnyToken(script, &token);
		td.shift[1] = atol(token.string);
		PS_ExpectAnyToken(script, &token);
		td.rotate = atol(token.string);
		PS_ExpectAnyToken(script, &token);
		td.scale[0] = atof(token.string);
		PS_ExpectAnyToken(script, &token);
		td.scale[1] = atof(token.string);

		//find default flags and values
		mt             = FindMiptex(td.name);
		td.flags       = textureref[mt].flags;
		td.value       = textureref[mt].value;
		side->contents = textureref[mt].contents;
		side->surf     = td.flags = textureref[mt].flags;

		//check if there's a number available
		if (PS_CheckTokenType(script, TT_NUMBER, 0, &token))
		{
			side->contents = token.intvalue;
			PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
			side->surf = td.flags = token.intvalue;
			PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
			td.value = token.intvalue;
		}

		// translucent objects are automatically classified as detail
//		if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
//			side->contents |= CONTENTS_DETAIL;
		if (side->contents & (CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP))
		{
			side->contents |= CONTENTS_DETAIL;
		}
		if (fulldetail)
		{
			side->contents &= ~CONTENTS_DETAIL;
		}
		if (!(side->contents & ((LAST_VISIBLE_CONTENTS - 1)
		                        | CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP | CONTENTS_MIST)))
		{
			side->contents |= CONTENTS_SOLID;
		}

		// hints and skips are never detail, and have no content
//		if (side->surf & (SURF_HINT|SURF_SKIP) )
//		{
//			side->contents = 0;
//			side->surf &= ~CONTENTS_DETAIL;
//		}

#ifdef ME
		//for creating AAS... this side is textured
		side->flags |= SFL_TEXTURED;
#endif //ME
		//
		// find the plane number
		//
		planenum = PlaneFromPoints(planepts[0], planepts[1], planepts[2]);
		if (planenum == -1)
		{
			Log_Print("Entity %i, Brush %i: plane with no normal\n"
			          , b->entitynum, b->brushnum);
			continue;
		}

		//
		// see if the plane has been used already
		//
		for (k = 0 ; k < b->numsides ; k++)
		{
			s2 = b->original_sides + k;
			if (s2->planenum == planenum)
			{
				Log_Print("Entity %i, Brush %i: duplicate plane\n"
				          , b->entitynum, b->brushnum);
				break;
			}
			if (s2->planenum == (planenum ^ 1))
			{
				Log_Print("Entity %i, Brush %i: mirrored plane\n"
				          , b->entitynum, b->brushnum);
				break;
			}
		}
		if (k != b->numsides)
		{
			continue;       // duplicated

		}
		//
		// keep this side
		//

		side           = b->original_sides + b->numsides;
		side->planenum = planenum;
		side->texinfo  = TexinfoForBrushTexture(&mapplanes[planenum],
		                                        &td, vec3_origin);

		// save the td off in case there is an origin brush and we
		// have to recalculate the texinfo
		side_brushtextures[nummapbrushsides] = td;

		nummapbrushsides++;
		b->numsides++;
	}
	while (1);

	// get the content for the entire brush
	b->contents = Q2_BrushContents(b);

#ifdef ME
	if (BrushExists(b))
	{
		c_squattbrushes++;
		b->numsides = 0;
		return;
	} //end if

	if (create_aas)
	{
		//create AAS brushes, and add brush bevels
		AAS_CreateMapBrushes(b, mapent, true);
		//NOTE: if we return here then duplicate plane errors occur for the non world entities
		return;
	} //end if
#endif //ME

	// allow detail brushes to be removed
	if (nodetail && (b->contents & CONTENTS_DETAIL))
	{
		b->numsides = 0;
		return;
	}

	// allow water brushes to be removed
	if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)))
	{
		b->numsides = 0;
		return;
	}

	// create windings for sides and bounds for brush
	MakeBrushWindings(b);

	// brushes that will not be visible at all will never be
	// used as bsp splitters
	if (b->contents & (CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP))
	{
		c_clipbrushes++;
		for (i = 0 ; i < b->numsides ; i++)
			b->original_sides[i].texinfo = TEXINFO_NODE;
	}

	//
	// origin brushes are removed, but they set
	// the rotation origin for the rest of the brushes
	// in the entity.  After the entire entity is parsed,
	// the planenums and texinfos will be adjusted for
	// the origin brush
	//
	if (b->contents & CONTENTS_ORIGIN)
	{
		char   string[32];
		vec3_t origin;

		if (num_entities == 1)
		{
			Error("Entity %i, Brush %i: origin brushes not allowed in world"
			      , b->entitynum, b->brushnum);
			return;
		}

		VectorAdd(b->mins, b->maxs, origin);
		VectorScale(origin, 0.5, origin);

		sprintf(string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
		SetKeyValue(&entities[b->entitynum], "origin", string);

		VectorCopy(origin, entities[b->entitynum].origin);

		// don't keep this brush
		b->numsides = 0;

		return;
	}

	AddBrushBevels(b);

	nummapbrushes++;
	mapent->numbrushes++;
}
Beispiel #14
0
/*
=================
ParseBrush
=================
*/
void ParseBrush (entity_t *mapent)
{
	char *tl;
	mapbrush_t		*b;
	int			i,j, k;
	int			mt;
	side_t		*side, *s2;
	int			planenum;
	brush_texture_t	td;
	float			planepts[3][3];
	qboolean		phongShading;

	MarkBrushBegin();

	if (nummapbrushes == MAX_MAP_BRUSHES)
		Error ("nummapbrushes == MAX_MAP_BRUSHES");

	b = &mapbrushes[nummapbrushes];
	b->original_sides = &brushsides[nummapbrushsides];
	b->entitynum = num_entities-1;
	b->brushnum = nummapbrushes - mapent->firstbrush;

	// Knightmare added
	b->optimizedDetail = false;
	b->isTerrain = (!strcmp("func_group", ValueForKey (&entities[b->entitynum], "classname"))
				&& strlen(ValueForKey (&entities[b->entitynum], "terrain")) > 0);
	b->isGenSurf = (!strcmp("func_group", ValueForKey (&entities[b->entitynum], "classname"))
				&& strlen(ValueForKey (&entities[b->entitynum], "gensurf")) > 0);
	phongShading = (!strcmp("func_group", ValueForKey (&entities[b->entitynum], "classname"))
				&& strlen(ValueForKey (&entities[b->entitynum], "phongshading")) > 0);
	//if (b->isTerrain) 
	//	printf ("Brush number %i in enitity number %i has terrain flag set.\n", b->brushnum, b->entitynum);
	//if (b->phongShading) 
	//	printf ("Brush number %i in enitity number %i has phong shading flag set.\n", b->brushnum, b->entitynum);
	if (verbosebrushes)
		printf ("enitity %i, brush  %i\n", b->entitynum, b->brushnum);
	// end Knightmare

	do
	{
		if (!GetToken (true))
			break;
		if (!strcmp (token, "}") )
			break;

		if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
			Error ("MAX_MAP_BRUSHSIDES");
		side = &brushsides[nummapbrushsides];

		// read the three point plane definition
		for (i=0 ; i<3 ; i++)
		{
			if (i != 0)
				GetToken (true);
			if (strcmp (token, "(") )
				Error ("parsing brush\n  Brush: %s", i+1, brush_info);
			
			for (j=0 ; j<3 ; j++)
			{
				GetToken (false);
				planepts[i][j] = atof(token);
			}
			
			GetToken (false);
			if (strcmp (token, ")") )
				Error ("parsing brush\n  Brush: %s", i+1, brush_info);
				
		}

		//
		// read the texturedef
		//
		GetToken (false);
        strcpy (td.name, token);

		tl = td.name;

		for(tl = td.name; *tl != 0; tl++)
			*tl = tolower(*tl);

		GetToken (false);
		td.shift[0] = atoi(token);
		GetToken (false);
		td.shift[1] = atoi(token);
		GetToken (false);
		td.rotate = atoi(token);	
		GetToken (false);
		td.scale[0] = atof(token);
		GetToken (false);
		td.scale[1] = atof(token);

		// find default flags and values
		mt = FindMiptex (td.name);
		td.flags = textureref[mt].flags;
		td.value = textureref[mt].value;
		side->contents = textureref[mt].contents;
		side->surf = td.flags = textureref[mt].flags;

		if (TokenAvailable())
		{
			GetToken (false);
			side->contents = atoi(token);
			GetToken (false);
			side->surf = td.flags = atoi(token);
			GetToken (false);
			td.value = atoi(token);
		}

		// translucent objects are automatically classified as detail
		if (side->surf & (SURF_TRANS33|SURF_TRANS66|SURF_ALPHATEST) ) // Knightmare- added alphatest
			side->contents |= CONTENTS_DETAIL;
		if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
			side->contents |= CONTENTS_DETAIL;
		if (fulldetail)
			side->contents &= ~CONTENTS_DETAIL;
		if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 
			| CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST)  ) )
			side->contents |= CONTENTS_SOLID;

		// hints and skips are never detail, and have no content
		if (side->surf & (SURF_HINT|SURF_SKIP) )
		{
			//side->contents = 0;
			//side->surf &= ~CONTENTS_DETAIL;
			side->contents &= CONTENTS_DETAIL; // allow only detail content- Geoffery DeWan?
		}

		//
		// find the plane number
		//
		planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
		if (planenum == -1)
		{
			printf ("Entity %i, Brush %i: plane with no normal\n  Brush: %s\n"
				, b->entitynum, b->brushnum, brush_info);
			continue;
		}

		//
		// see if the plane has been used already
		//
		for (k=0 ; k<b->numsides ; k++)
		{
			s2 = b->original_sides + k;
			if (s2->planenum == planenum)
			{
				printf ("Entity %i, Brush %i: duplicate plane\n  Brush: %s\n"
					, b->entitynum, b->brushnum, brush_info);
				break;
			}
			if ( s2->planenum == (planenum^1) )
			{
				printf ("Entity %i, Brush %i: mirrored plane\n  Brush: %s\n"
					, b->entitynum, b->brushnum, brush_info);
				break;
			}
		}
		if (k != b->numsides)
			continue;		// duplicated

		//
		// keep this side
		//

		side = b->original_sides + b->numsides;
		side->planenum = planenum;
		side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
			&td, vec3_origin, b->isTerrain); // Knightmare added

		// save the td off in case there is an origin brush and we
		// have to recalculate the texinfo
		side_brushtextures[nummapbrushsides] = td;

		nummapbrushsides++;
		b->numsides++;
	} while (1);

	// get the content for the entire brush
	b->contents = BrushContents (b);

	// allow detail brushes to be removed 
	if (nodetail && (b->contents & CONTENTS_DETAIL) )
	{
		b->numsides = 0;
		return;
	}

	// allow water brushes to be removed
	if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
	{
		b->numsides = 0;
		return;
	}

	// Knightmare- check if this is an optimized detail brush (has caulk faces)
	// also exclude trans brushes and terrain
	if ((b->contents & CONTENTS_DETAIL) && (b->contents & CONTENTS_SOLID) && !b->isTerrain && !b->isGenSurf)
		for (i=0; i<b->numsides; i++)
		{
			if ( !strcmp(texinfo[b->original_sides[i].texinfo].texture, "system/caulk")
				|| !strcmp(texinfo[b->original_sides[i].texinfo].texture, "common/caulk") )
			{
				b->optimizedDetail = true;
				//printf ("Entity %i, Brush %i: optimized detail\n", b->entitynum, b->brushnum);
				break;
			}
		}

	// Knightmare- special handling for terrain brushes
	if (b->isTerrain || b->isGenSurf || phongShading)
		for (i=0; i<b->numsides; i++)
		{
			s2 = &b->original_sides[i];
			// set ArghRad phong shading value (because EasyGen/GTKGenSurf doesn't allow this)
			if (strcmp(texinfo[b->original_sides[i].texinfo].texture, "system/caulk")
				&& strcmp(texinfo[b->original_sides[i].texinfo].texture, "common/caulk"))
			{
				texinfo[s2->texinfo].value = 777 + b->entitynum;	// lucky 7's
				texinfo[s2->texinfo].flags &= ~SURF_LIGHT;			// must not be light-emitting
			}
		}

	// create windings for sides and bounds for brush

	// MEM_LEAK
	MakeBrushWindings (b);
	t_w = b->original_sides[0].winding;

	// brushes that will not be visible at all will never be
	// used as bsp splitters
	if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
	{
		c_clipbrushes++;
		for (i=0 ; i<b->numsides ; i++)
			b->original_sides[i].texinfo = TEXINFO_NODE;
	}

	//
	// origin brushes are removed, but they set
	// the rotation origin for the rest of the brushes
	// in the entity.  After the entire entity is parsed,
	// the planenums and texinfos will be adjusted for
	// the origin brush
	//
	if (b->contents & CONTENTS_ORIGIN)
	{
		char	string[32];
		vec3_t	origin;

		if (num_entities == 1)
		{
			Error ("Entity %i, Brush %i: origin brushes not allowed in world\n  BrushL %s",
				b->entitynum, b->brushnum, brush_info);
			return;
		}

		VectorAdd (b->mins, b->maxs, origin);
		VectorScale (origin, 0.5, origin);

		sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
		SetKeyValue (&entities[b->entitynum], "origin", string);

		VectorCopy (origin, entities[b->entitynum].origin);

		// don't keep this brush
		b->numsides = 0;

		return;
	}

	AddBrushBevels (b);

	nummapbrushes++;
	mapent->numbrushes++;		
}
Beispiel #15
0
// =====================================================================================
//  WriteMiptex
// =====================================================================================
void            WriteMiptex()
{
    int             len, texsize, totaltexsize = 0;
    byte*           data;
    dmiptexlump_t*  l;
    double          start, end;

    g_texdatasize = 0;

    start = I_FloatTime();
    {
        if (!TEX_InitFromWad())
            return;

        AddAnimatingTextures();
    }
    end = I_FloatTime();
    Verbose("TEX_InitFromWad & AddAnimatingTextures elapsed time = %ldms\n", (long)(end - start));

    start = I_FloatTime();
    {
        int             i;

        for (i = 0; i < nummiptex; i++)
        {
            lumpinfo_t*     found;

            found = FindTexture(miptex + i);
            if (found)
            {
                miptex[i] = *found;
            }
            else
            {
                miptex[i].iTexFile = miptex[i].filepos = miptex[i].disksize = 0;
            }
        }
    }
    end = I_FloatTime();
    Verbose("FindTextures elapsed time = %ldms\n", (long)(end - start));

    start = I_FloatTime();
    {
        int             i;
        texinfo_t*      tx = g_texinfo;

        // Sort them FIRST by wadfile and THEN by name for most efficient loading in the engine.
        qsort((void*)miptex, (size_t) nummiptex, sizeof(miptex[0]), lump_sorter_by_wad_and_name);

        // Sleazy Hack 104 Pt 2 - After sorting the miptex array, reset the texinfos to point to the right miptexs
        for (i = 0; i < g_numtexinfo; i++, tx++)
        {
            char*          miptex_name = texmap64_retrieve(tx->miptex);

            tx->miptex = FindMiptex(miptex_name);

            // Free up the originally strdup()'ed miptex_name
            free(miptex_name);
        }
    }
    end = I_FloatTime();
    Verbose("qsort(miptex) elapsed time = %ldms\n", (long)(end - start));

    start = I_FloatTime();
    {
        int             i;

        // Now setup to get the miptex data (or just the headers if using -wadtextures) from the wadfile
        l = (dmiptexlump_t*)g_dtexdata;
        data = (byte*) & l->dataofs[nummiptex];
        l->nummiptex = nummiptex;
        for (i = 0; i < nummiptex; i++)
        {
            l->dataofs[i] = data - (byte*) l;
            len = LoadLump(miptex + i, data, &texsize);

            if (!len)
            {
                l->dataofs[i] = -1;                        // didn't find the texture
            }
            else
            {
                totaltexsize += texsize;

                hlassume(totaltexsize < g_max_map_miptex, assume_MAX_MAP_MIPTEX);
            }
            data += len;
        }
        g_texdatasize = data - g_dtexdata;
    }
    end = I_FloatTime();
    Log("Texture usage is at %1.2f mb (of %1.2f mb MAX)\n", (float)totaltexsize / (1024 * 1024),
        (float)g_max_map_miptex / (1024 * 1024));
    Verbose("LoadLump() elapsed time = %ldms\n", (long)(end - start));
}
Beispiel #16
0
Datei: map.c Projekt: kellyrm/Q1
/*
=================
ParseBrush
=================
*/
void ParseBrush (void)
{
	mbrush_t  *b;
	mface_t	  *f, *f2;
	vec3_t	  planepts[3];
	vec3_t	  t1, t2, t3, VAxis[2];
	int	  i, j, Faces;
	texinfo_t tx;
	vec_t	  d;
	vec_t	  shift[2], rotate, scale[2];
	qboolean  ok, Valve220;

        ExtendArray(mapbrushes, nummapbrushes);
	b = &mapbrushes[nummapbrushes];
	b->Line = scriptline;

	ok = GetToken (true);

	while (ok)
	{
		txcommand = 0;
		if (!strcmp (token, "}") )
		{
			if (!options.onlyents)
			{
				if (InvalidBrush(b, &Faces))
				{
					// Too few faces in brush or not closed; drop it
					DropBrush (b);
					nummapfaces -= Faces;
					// Note: texinfo array is not corrected here
					return;
				}
			}

			if (options.SortFace)
				SortFaces(b);

			break;
		}

	// read the three point plane definition
		for (i=0 ; i<3 ; i++)
		{
			if (i != 0)
				GetToken (true);
			if (strcmp (token, "(") )
				Message (MSGERR, "Invalid brush plane format on line %d", scriptline);

			for (j=0 ; j<3 ; j++)
			{
				GetToken (false);
				planepts[i][j] = atof(token);	// AR: atof
			}

			GetToken (false);
			if (strcmp (token, ")") )
				Message (MSGERR, "Invalid brush plane format on line %d", scriptline);

		}

	// read the texturedef
		memset (&tx, 0, sizeof(tx));
		GetToken (false);

		if (options.Q2Map)
			Q2ToQ1Tex (token);

		// Check texture name length
		if (strlen(token) > sizeof(char16) - 1)
			Message (MSGERR, "Texture name \"%s\" too long on line %d", token, scriptline);

		if (options.SolidMap && num_entities == 1 && token[0] == '*' ||
		    options.noents && num_entities > 1)
		{
			// No liquid worldbrushes or only worldbrushes allowed; drop brush
			DropBrush (b);

			while (GetToken(true) && strcmp(token, "}"))
				;

			return;
		}

		Valve220 = false;

		tx.miptex = FindMiptex (token);
		GetToken (false);
		
		if (!strcmp (token, "["))
		{
			// Valve 220 map import
			Valve220 = true;
			GetValveTex (VAxis[0]);
		}

		shift[0] = atoi(token);
		GetToken (false);
		
		if (Valve220)
		{
			// Skip ]
			GetToken (false);
			GetValveTex (VAxis[1]);
		}

		shift[1] = atoi(token);
		GetToken (false);

		if (Valve220)
			GetToken (false); // Skip ]

		rotate = atoi(token);
		GetToken (false);
		scale[0] = atof(token);
		GetToken (false);
		scale[1] = atof(token);

		if (options.Q2Map)
		{
			// Skip extra Q2 style face info
			GetToken (false);
			GetToken (false);
			GetToken (false);
		}

		ok = GetToken (true); // Note : scriptline normally gets advanced here

		// 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)
		{
			Message (MSGWARN, "Brush with duplicate plane on line %d", scriptline - 1);
			continue;
		}

		f = AllocOther(sizeof(mface_t));

	// convert to a vector / dist plane
		for (j=0 ; j<3 ; j++)
		{
			t1[j] = planepts[0][j] - planepts[1][j];
			t2[j] = planepts[2][j] - planepts[1][j];
			t3[j] = planepts[1][j];
		}

		CrossProduct(t1,t2, f->plane.normal);
		if (VectorCompare (f->plane.normal, vec3_origin))
		{
			Message (MSGWARN, "Brush plane with no normal on line %d", scriptline - 1);
			FreeOther (f);
			continue;
		}
		VectorNormalize (f->plane.normal);
		f->plane.dist = DotProduct (t3, f->plane.normal);

		f->next = b->faces;
		b->faces = f;

		if (txcommand=='1' || txcommand=='2')
		{		// from QuArK, the texture vectors are given directly from the three points
			vec3_t	TexPt[2];
			int		k;
			vec_t	dot22, dot23, dot33, mdet, aa, bb, dd;

			k = txcommand-'0';
			for (j=0; j<3; j++)
				TexPt[1][j] = (planepts[k][j] - planepts[0][j]) * ScaleCorrection;
			k = 3-k;
			for (j=0; j<3; j++)
				TexPt[0][j] = (planepts[k][j] - planepts[0][j]) * ScaleCorrection;

			dot22 = DotProduct (TexPt[0], TexPt[0]);
			dot23 = DotProduct (TexPt[0], TexPt[1]);
			dot33 = DotProduct (TexPt[1], TexPt[1]);
			mdet = dot22*dot33-dot23*dot23;
			if (mdet<1E-6 && mdet>-1E-6)
			{
				aa = bb = dd = 0;
				Message (MSGWARN, "Degenerate QuArK-style brush texture on line %d", scriptline - 1);
			}
			else
			{
				mdet = 1.0/mdet;
      			aa = dot33*mdet;
      			bb = -dot23*mdet;
				//cc = -dot23*mdet;     // cc = bb
				dd = dot22*mdet;
			}

			for (j=0; j<3; j++)
			{
				tx.vecs[0][j] = aa * TexPt[0][j] + bb * TexPt[1][j];
				tx.vecs[1][j] = -(/*cc*/ bb * TexPt[0][j] + dd * TexPt[1][j]);
			}

			tx.vecs[0][3] = -DotProduct(tx.vecs[0], planepts[0]);
			tx.vecs[1][3] = -DotProduct(tx.vecs[1], planepts[0]);
		}
		else if (Valve220)
		{
			// Valve 220 texturedef
			vec3_t vec;
			vec_t  tscale;

			// Prevent division by zero
			if (!scale[0])
				scale[0] = 1;
			if (!scale[1])
				scale[1] = 1;

			// FIXME: If origin brushes are in use, this is where to fix their tex alignment!!!
			for (i = 0; i < 2; ++i)
			{
				tscale = 1 / scale[i];
				VectorScale(VAxis[i], tscale, vec);
				
				for (j = 0; j < 3; ++j)
					tx.vecs[i][j] = (float)vec[j];
				
				tx.vecs[i][3] = (float)shift[i] + DotProduct(vec3_origin, vec);
			}
		}
		else
	//
	// fake proper texture vectors from QuakeEd style
	//
		{
			vec3_t	vecs[2];
			int		sv, tv;
			vec_t	ang, sinv, cosv;
			vec_t	ns, nt;

			TextureAxisFromPlane(&f->plane, vecs[0], vecs[1]);

			if (!scale[0])
				scale[0] = 1;
			if (!scale[1])
				scale[1] = 1;

		// 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 / 180 * Q_PI;
				sinv = sin(ang);
				cosv = cos(ang);
			}

			if (vecs[0][0])
				sv = 0;
			else if (vecs[0][1])
				sv = 1;
			else
				sv = 2;

			if (vecs[1][0])
				tv = 0;
			else if (vecs[1][1])
				tv = 1;
			else
				tv = 2;

			for (i=0 ; i<2 ; i++)
			{
				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;
			}

			for (i=0 ; i<2 ; i++)
				for (j=0 ; j<3 ; j++)
					tx.vecs[i][j] = vecs[i][j] / scale[i];

			tx.vecs[0][3] = shift[0];
			tx.vecs[1][3] = shift[1];
		}

	// unique the texinfo
		f->texinfo = FindTexinfo (&tx);
		nummapfaces++;
	};

	nummapbrushes++;
	b->next = mapent->brushes;
	mapent->brushes = b;
}
Beispiel #17
0
/*
=================
ParseBrush
=================
*/
void ParseBrush (void)
{
	int			i, j, sv, tv, hltexdef;
	vec_t		planepts[3][3], t1[3], t2[3], d, rotate, scale[2], vecs[2][4], ang, sinv, cosv, ns, nt;
	mbrush_t	*b;
	mface_t		*f, *f2;
	plane_t	plane;
	texinfo_t	tx;

	b = &mapbrushes[nummapbrushes];
	nummapbrushes++;
	b->next = mapent->brushes;
	mapent->brushes = b;

	do
	{
		if (!GetToken (true))
			break;
		if (!strcmp (token, "}") )
			break;

		// read the three point plane definition
		for (i = 0;i < 3;i++)
		{
			if (i != 0)
				GetToken (true);
			if (strcmp (token, "(") )
				Error ("parsing brush on line %d\n", scriptline);

			for (j = 0;j < 3;j++)
			{
				GetToken (false);
				planepts[i][j] = atof(token); // LordHavoc: float coords
			}

			GetToken (false);
			if (strcmp (token, ")") )
				Error ("parsing brush on line %d\n", scriptline);
		}

		//fflush(stdout);

		// 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);

		// read the texturedef
		memset (&tx, 0, sizeof(tx));
		GetToken (false);
		tx.miptex = FindMiptex (token);
		GetToken (false);
		if ((hltexdef = !strcmp(token, "[")))
		{
			// S vector
			GetToken(false);
			vecs[0][0] = atof(token);
			GetToken(false);
			vecs[0][1] = atof(token);
			GetToken(false);
			vecs[0][2] = atof(token);
			GetToken(false);
			vecs[0][3] = atof(token);
			// ]
			GetToken(false);
			// [
			GetToken(false);
			// T vector
			GetToken(false);
			vecs[1][0] = atof(token);
			GetToken(false);
			vecs[1][1] = atof(token);
			GetToken(false);
			vecs[1][2] = atof(token);
			GetToken(false);
			vecs[1][3] = atof(token);
			// ]
			GetToken(false);
		}
		else
		{
			vecs[0][3] = atof(token); // LordHavoc: float coords
			GetToken (false);
			vecs[1][3] = atof(token); // LordHavoc: float coords
		}
		GetToken (false);
		rotate = atof(token);	 // LordHavoc: float coords
		GetToken (false);
		scale[0] = atof(token); // LordHavoc: was already float coords
		GetToken (false);
		scale[1] = atof(token); // LordHavoc: was already float coords

		// 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);
			continue;
		}

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

		/*
		// 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;
		*/

		if (!hltexdef)
		{
			// fake proper texture vectors from QuakeEd style
			TextureAxisFromPlane(&plane, vecs[0], vecs[1]);
		}

		// 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];
		}

		f = malloc(sizeof(mface_t));
		f->next = b->faces;
		b->faces = f;
		f->plane = plane;
		f->texinfo = FindTexinfo (&tx);
		nummapbrushfaces++;
	}
	while (1);
}
Beispiel #18
0
static void
ParseBrush(void)
{
    vec3_t planepts[3];
    vec3_t t1, t2, t3;
    int i, j;
    texinfo_t tx;
    vec_t d;
    int shift[2], rotate;
    vec_t scale[2];
    int iFace;
    int tx_type;

    map.rgBrushes[map.iBrushes].iFaceEnd = map.iFaces + 1;

    while (ParseToken(PARSE_NORMAL)) {
	if (!strcmp(token, "}"))
	    break;

	// read the three point plane definition
	for (i = 0; i < 3; i++) {
	    if (i != 0)
		ParseToken(PARSE_NORMAL);
	    if (strcmp(token, "("))
		Message(msgError, errInvalidMapPlane, linenum);

	    for (j = 0; j < 3; j++) {
		ParseToken(PARSE_SAMELINE);
		planepts[i][j] = atof(token);
	    }

	    ParseToken(PARSE_SAMELINE);
	    if (strcmp(token, ")"))
		Message(msgError, errInvalidMapPlane, linenum);
	}

	// read the texturedef
	memset(&tx, 0, sizeof(tx));
	ParseToken(PARSE_SAMELINE);
	tx.miptex = FindMiptex(token);
	ParseToken(PARSE_SAMELINE);
	shift[0] = atoi(token);
	ParseToken(PARSE_SAMELINE);
	shift[1] = atoi(token);
	ParseToken(PARSE_SAMELINE);
	rotate = atoi(token);
	ParseToken(PARSE_SAMELINE);
	scale[0] = atof(token);
	ParseToken(PARSE_SAMELINE);
	scale[1] = atof(token);

	// if the three points are all on a previous plane, it is a
	// duplicate plane
	for (iFace = map.rgBrushes[map.iBrushes].iFaceEnd - 1;
	     iFace > map.iFaces; iFace--) {
	    for (i = 0; i < 3; i++) {
		d = DotProduct(planepts[i], map.rgFaces[iFace].plane.normal) -
		    map.rgFaces[iFace].plane.dist;
		if (d < -ON_EPSILON || d > ON_EPSILON)
		    break;
	    }
	    if (i == 3)
		break;
	}
	if (iFace > map.iFaces) {
	    Message(msgWarning, warnBrushDuplicatePlane, linenum);
	    continue;
	}

	if (map.iFaces < 0)
	    Message(msgError, errLowFaceCount);

	// convert to a vector / dist plane
	for (j = 0; j < 3; j++) {
	    t1[j] = planepts[0][j] - planepts[1][j];
	    t2[j] = planepts[2][j] - planepts[1][j];
	    t3[j] = planepts[1][j];
	}

	CrossProduct(t1, t2, map.rgFaces[map.iFaces].plane.normal);
	if (VectorCompare(map.rgFaces[map.iFaces].plane.normal, vec3_origin)) {
	    Message(msgWarning, warnNoPlaneNormal, linenum);
	    break;
	}
	VectorNormalize(map.rgFaces[map.iFaces].plane.normal);
	map.rgFaces[map.iFaces].plane.dist =
	    DotProduct(t3, map.rgFaces[map.iFaces].plane.normal);

	tx_type = ParseExtendedTX();
	switch (tx_type) {
	case TX_QUARK_TYPE1:
	case TX_QUARK_TYPE2:
	    SetTexinfo_QuArK(planepts, tx_type, &tx);
	    break;
	default:
	    SetTexinfo_QuakeEd(shift, rotate, scale, &tx);
	    break;
	}

	// unique the texinfo
	map.rgFaces[map.iFaces].texinfo = FindTexinfo(&tx);
	map.iFaces--;
	Message(msgPercent, map.cFaces - map.iFaces - 1, map.cFaces);
    }

    map.rgBrushes[map.iBrushes].iFaceStart = map.iFaces + 1;
    map.iBrushes--;
}
Beispiel #19
0
void ParseBrush (void)

{

	mbrush_t		*b;

	mface_t		*f, *f2;

	vec3_t		planepts[3];

	vec3_t			t1, t2, t3;

	int			i,j;

	texinfo_t	tx;

	double		d;

	float		shift[2], rotate, scale[2];

	char		name[64];



	b = &mapbrushes[nummapbrushes];

		

	do

	{

		if (!GetToken (true))

			break;

		if (!strcmp (token, "}") )

			break;

		

	// read the three point plane definition

		for (i=0 ; i<3 ; i++)

		{

			if (i != 0)

				GetToken (true);

			if (strcmp (token, "(") )

				logerror ("parsing brush"); // jkrige - was Error()

			

			for (j=0 ; j<3 ; j++)

			{

				GetToken (false);

				// jkrige - floating point texture support
				//planepts[i][j] = atoi(token);
				planepts[i][j] = atof(token);
				// jkrige - floating point texture support

			}

			

			GetToken (false);

			if (strcmp (token, ")") )

				logerror ("parsing brush"); // jkrige - was Error()

				

		}



	// read the texturedef

		memset (&tx, 0, sizeof(tx));

		GetToken (false);



		strcpy (name, token);	// JDC 8/8/97: for origin texture



		tx.miptex = FindMiptex (token);
		
		GetToken (false);
		
		shift[0] = atoi(token);
		
		GetToken (false);
		
		shift[1] = atoi(token);
		
		GetToken (false);
		
		rotate = atoi(token);	
		
		GetToken (false);

		scale[0] = atof(token);

		GetToken (false);

		scale[1] = atof(token);

		GetToken (false);

		b->Light = atol(token);



		// 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)		

		{

			logprint ("WARNING: brush with duplicate plane\n");

			continue;

		}



		f = malloc(sizeof(mface_t));

		f->next = b->faces;

		b->faces = f;

		

	// convert to a vector / dist plane

		for (j=0 ; j<3 ; j++)

		{

			t1[j] = planepts[0][j] - planepts[1][j];

			t2[j] = planepts[2][j] - planepts[1][j];

			t3[j] = planepts[1][j];

		}

		

		CrossProduct(t1,t2, f->plane.normal);

		if (VectorCompare (f->plane.normal, vec3_origin))

		{

			logprint ("WARNING: brush plane with no normal\n");

			b->faces = f->next;

			free (f);

			break;

		}

		VectorNormalize (f->plane.normal);

		f->plane.dist = DotProduct (t3, f->plane.normal);



	//

	// fake proper texture vectors from QuakeEd style

	//

		{

			vec3_t	vecs[2];

			int		sv, tv;

			float	ang, sinv, cosv;

			float	ns, nt;

			

			TextureAxisFromPlane(&f->plane, vecs[0], vecs[1]);

		

			if (!scale[0])

				scale[0] = 1;

			if (!scale[1])

				scale[1] = 1;

		

		

		// 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 / 180 * Q_PI;

				sinv = sin(ang);

				cosv = cos(ang);

			}

		

			if (vecs[0][0])

				sv = 0;

			else if (vecs[0][1])

				sv = 1;

			else

				sv = 2;

						

			if (vecs[1][0])

				tv = 0;

			else if (vecs[1][1])

				tv = 1;

			else

				tv = 2;

							

			for (i=0 ; i<2 ; i++)

			{

				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;

			}

		

			for (i=0 ; i<2 ; i++)

				for (j=0 ; j<3 ; j++)

					tx.vecs[i][j] = vecs[i][j] / scale[i];

		

			tx.vecs[0][3] = shift[0];

			tx.vecs[1][3] = shift[1];

		}

	

	// unique the texinfo

		f->texinfo = FindTexinfo (&tx);		

	} while (1);



	// JDC 8/8/97

	// origin brushes are removed, but they set

	// the rotation origin for the rest of the brushes

	// in the entity

	//

	if (Q_strncasecmp (name, "origin",6))

	{	// keep it

		nummapbrushes++;

		b->next = mapent->brushes;

		mapent->brushes = b;

	}

	else

	{	// don't save the brush, just use as entity origin

		char	string[32];

		vec3_t	origin;



		if (num_entities == 1)

			logerror ("Origin brushes not allowed in world"); // jkrige - was Error()



		BrushOrigin (b, origin);



		sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);

		SetKeyValue (mapent, "origin", string);



		VectorCopy (origin, mapent->origin);



		memset (b, 0, sizeof(*b));

	}

}
Beispiel #20
0
static void
ParseBrush(parser_t *parser, mapbrush_t *brush)
{
    vec3_t planepts[3];
    vec3_t t1, t2, t3;
    int i, j;
    texinfo_t tx;
    vec_t d;
    int shift[2], rotate;
    vec_t scale[2];
    int tx_type;
    plane_t *plane;
    mapface_t *face, *checkface;

    brush->faces = face = map.faces + map.numfaces;
    while (ParseToken(parser, PARSE_NORMAL)) {
	if (!strcmp(parser->token, "}"))
	    break;

	// read the three point plane definition
	for (i = 0; i < 3; i++) {
	    if (i != 0)
		ParseToken(parser, PARSE_NORMAL);
	    if (strcmp(parser->token, "("))
		Error(errInvalidMapPlane, parser->linenum);

	    for (j = 0; j < 3; j++) {
		ParseToken(parser, PARSE_SAMELINE);
		planepts[i][j] = atof(parser->token);
	    }

	    ParseToken(parser, PARSE_SAMELINE);
	    if (strcmp(parser->token, ")"))
		Error(errInvalidMapPlane, parser->linenum);
	}

	// read the texturedef
	memset(&tx, 0, sizeof(tx));
	ParseToken(parser, PARSE_SAMELINE);
	tx.miptex = FindMiptex(parser->token);
	ParseToken(parser, PARSE_SAMELINE);
	shift[0] = atoi(parser->token);
	ParseToken(parser, PARSE_SAMELINE);
	shift[1] = atoi(parser->token);
	ParseToken(parser, PARSE_SAMELINE);
	rotate = atoi(parser->token);
	ParseToken(parser, PARSE_SAMELINE);
	scale[0] = atof(parser->token);
	ParseToken(parser, PARSE_SAMELINE);
	scale[1] = atof(parser->token);

	// if the three points are all on a previous plane, it is a
	// duplicate plane
	for (checkface = brush->faces; checkface < face; checkface++) {
	    plane = &checkface->plane;
	    for (i = 0; i < 3; i++) {
		d = DotProduct(planepts[i], plane->normal) - plane->dist;
		if (d < -ON_EPSILON || d > ON_EPSILON)
		    break;
	    }
	    if (i == 3)
		break;
	}
	if (checkface < face) {
	    Message(msgWarning, warnBrushDuplicatePlane, parser->linenum);
	    continue;
	}

	if (map.numfaces == map.maxfaces)
	    Error(errLowFaceCount);

	// convert to a vector / dist plane
	for (j = 0; j < 3; j++) {
	    t1[j] = planepts[0][j] - planepts[1][j];
	    t2[j] = planepts[2][j] - planepts[1][j];
	    t3[j] = planepts[1][j];
	}

	plane = &face->plane;
	CrossProduct(t1, t2, plane->normal);
	if (VectorCompare(plane->normal, vec3_origin)) {
	    Message(msgWarning, warnNoPlaneNormal, parser->linenum);
	    continue;
	}
	VectorNormalize(plane->normal);
	plane->dist = DotProduct(t3, plane->normal);

	tx_type = ParseExtendedTX(parser);
	switch (tx_type) {
	case TX_QUARK_TYPE1:
	case TX_QUARK_TYPE2:
	    SetTexinfo_QuArK(parser, &planepts[0], tx_type, &tx);
	    break;
	default:
	    SetTexinfo_QuakeEd(plane, shift, rotate, scale, &tx);
	    break;
	}
	face->texinfo = FindTexinfo(&tx);

	face++;
	map.numfaces++;
	Message(msgPercent, map.numfaces, map.maxfaces);
    }

    brush->numfaces = face - brush->faces;
    if (!brush->numfaces)
	brush->faces = NULL;
}