📄 brush.cpp
字号:
/****************************************************************************************/
/* brush.c */
/* */
/* Author: Jim Mischel, Ken Baird, Jeff Lomax, John Pollard */
/* Description: Brush management, io, csg, list management, and transform operations */
/* */
/* The contents of this file are subject to the Genesis3D Public License */
/* Version 1.01 (the "License"); you may not use this file except in */
/* compliance with the License. You may obtain a copy of the License at */
/* http://www.genesis3d.com */
/* */
/* Software distributed under the License is distributed on an "AS IS" */
/* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See */
/* the License for the specific language governing rights and limitations */
/* under the License. */
/* */
/* The Original Code is Genesis3D, released March 25, 1999. */
/*Genesis3D Version 1.1 released November 15, 1999 */
/* Copyright (C) 1999 WildTangent, Inc. All Rights Reserved */
/* */
/* Modified by Tom Morris for GenEdit-Classic ver. 0.57, Feb. 3, 2001 */
/****************************************************************************************/
#include "StdAfx.h"
#include "Globals.h"
#include "brush.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "Vec3d.h"
#include "basetype.h"
#include "typeio.h"
#include "facelist.h"
#include "units.h"
#include "ram.h"
#include "util.h"
//#include "ConsoleTab.h" //for conprintf
#include "Globals.h"
/*
Our brushes work as three different objects. The basic square box is a leaf brush
that contains the original verts and info from the template dialog. Leaf brushes
will have a facelist, and possibly a brushlist containing pieces of the original
brush that have been cut up by others. Leaf is a bit confusing, since these
brushes aren't actually leaf regions in a tree or anything.
Multi brushes such as hollows and arches and other nonconvex brushes will contain
a series of leaf brushes. Multi brushes should contain no faces themselves.
CSG brushes are the end result of cuts. They are stored beneath the parent leaf.
Brushes are not exclusive to volume in our system. We don't csg multiple solid
areas away. Only drastic content changes will cause this. (cuts)
There's alot of work done to keep the data structures hidden to other files. This
is a standard practice here at WildTangent and brush, face, facelist are all good
examples of how "opaque" objects work.
*/
static const int axidx[3][2] ={ 2, 1, 0, 2, 0, 1 };
static const geVec3d VecOrigin ={ 0.0f, 0.0f, 0.0f };
struct tag_BrushList
{
Brush *First;
Brush *Last;
};
#define VectorToSUB(a, b) (*((((geFloat *)(&a))) + (b)))
#define VCOMPARE_EPSILON 0.001f
#define BOGUS_RANGE 32000.0f
enum BrushFlags
{
BRUSH_SOLID =0x0001,
BRUSH_WINDOW =0x0002,
BRUSH_WAVY =0x0004,
BRUSH_DETAIL =0x0008, //not included in vis calculations
BRUSH_HOLLOWCUT =0x0010,
BRUSH_TRANSLUCENT =0x0020,
BRUSH_EMPTY =0x0040,
BRUSH_SUBTRACT =0x0080,
BRUSH_CLIP =0x0100,
BRUSH_FLOCKING =0x0200,
BRUSH_HOLLOW =0x0400,
BRUSH_SHEET =0x0800,
BRUSH_HIDDEN =0x1000,
BRUSH_LOCKED =0x2000,
BRUSH_HINT =0x4000,
BRUSH_AREA =0x8000
// All flags larger than 0x8000 (i.e. 0x00010000 through 0x80000000)
// are reserved for user contents.
};
// Brush flags output to GBSPLIB
enum
{
bfSolid = (1<<0),
bfWindow = (1<<1),
bfEmpty = (1<<2),
bfTranslucent = (1<<3),
bfWavy = (1<<4),
bfDetail = (1<<5),
bfClip = (1<<6),
bfHint = (1<<7),
bfArea = (1<<8),
bfFlocking = (1<<9),
bfSheet = (1<<10)
// flags 11 through 15 are reserved for future expansion.
// flags 16 through 31 are user flags.
};
#define USER_FLAGS_MASK (0xffff0000ul)
#define SYSTEM_FLAGS_MASK (0x0000fffful)
// brush edit flags (not currently used, but please don't remove)
enum
{
befHidden = (1<<0),
befLocked = (1<<1),
befSelected = (1<<2),
befEntity = (1<<3),
// befTexInvalid = (1<<4),
befHollow = (1<<5),
befRing = (1<<6)
};
/*
typedef struct BrushTag // moved to brush.h for g3dc
{
struct BrushTag *Prev, *Next;
FaceList *Faces; //null if multibrush
BrushList *BList; //null if csgbrush
unsigned long Flags;
int Type;
int ModelId;
int GroupId;
geFloat HullSize; //for hollows
uint32 Color;
char *Name;
Box3d BoundingBox;
} Brush;
*/
typedef void (*BrushList_FlagCB)(Brush *pBrush, const geBoolean bState);
typedef void (*BrushList_IntCB)(Brush *pBrush, const int iVal);
typedef void (*BrushList_FloatCB)(Brush *pBrush, const float fVal);
typedef void (*BrushList_Uint32CB)(Brush *pBrush, const uint32 uVal);
static void BrushList_SetFlag(BrushList *bl, const geBoolean bState, BrushList_FlagCB cbSetFlag)
{
Brush *b;
if (bl == NULL)
MessageBox(NULL, "Brush1 == NULL", "BrushList_SetFlag", MB_OK); // post 0.55
assert(bl != NULL);
for(b=bl->First;b;b=b->Next)
{
cbSetFlag(b, bState);
}
}
static void BrushList_SetInt(BrushList *bl, const int iVal, BrushList_IntCB cbSetInt)
{
Brush *b;
if (bl == NULL)
MessageBox(NULL, "Brush1 == NULL", "BrushList_SetInt", MB_OK); // post 0.55
assert(bl != NULL);
for(b=bl->First;b;b=b->Next)
{
cbSetInt(b, iVal);
}
}
static void BrushList_SetUint32(BrushList *bl, const uint32 uVal, BrushList_Uint32CB cbSetUint)
{
Brush *b;
if (bl == NULL)
MessageBox(NULL, "Brush1 == NULL", "BrushList_SetUINT32", MB_OK); // post 0.55
assert(bl != NULL);
for(b=bl->First;b;b=b->Next)
{
cbSetUint(b, uVal);
}
}
static void BrushList_SetFloat(BrushList *bl, const geFloat fVal, BrushList_FloatCB cbSetFloat)
{
Brush *b;
if (bl == NULL)
MessageBox(NULL, "Brush1 == NULL", "BrushList_SetFloat", MB_OK); // post 0.55
assert(bl != NULL);
for(b=bl->First;b;b=b->Next)
{
cbSetFloat(b, fVal);
}
}
Brush *Brush_Create(int Type, const FaceList *fl, const BrushList *BList)
{
Brush *pBrush;
pBrush =(Brush*)geRam_Allocate(sizeof (Brush));
if(pBrush != NULL)
{
pBrush->Prev =NULL;
pBrush->Next =NULL;
pBrush->ModelId =0;
pBrush->GroupId =0;
pBrush->HullSize=1.0f;
pBrush->Color =0;
pBrush->Name =Util_Strdup("NoName");
pBrush->Type =Type;
switch(Type)
{
case BRUSH_MULTI:
assert(fl==NULL);
assert(BList);
pBrush->Faces =NULL;
pBrush->BList =(BrushList *)BList;
pBrush->Flags =BRUSH_SOLID;
BrushList_GetBounds(BList, &pBrush->BoundingBox);
break;
case BRUSH_LEAF:
case BRUSH_CSG:
assert(fl);
assert(BList==NULL); //shouldn't create leaf from multiple
pBrush->Faces =(FaceList *)fl;
pBrush->BList =NULL;
pBrush->Flags =BRUSH_SOLID;
FaceList_GetBounds(fl, &pBrush->BoundingBox);
break;
default:
assert(0);
}
}
return pBrush;
}
//creates a csg brush from a leaf or csg brush
static Brush *Brush_CreateFromParent(const Brush *ParentBrush, const FaceList *fl)
{
Brush *pBrush;
if (ParentBrush == NULL)
MessageBox(NULL, "ParentBrush == NULL", "Brush_CreateFromParent", MB_OK); // post 0.55
assert(ParentBrush);
assert(fl != NULL);
assert(ParentBrush->Type!=BRUSH_MULTI);
pBrush = (BrushTag*)geRam_Allocate(sizeof (Brush));
if(pBrush != NULL)
{
pBrush->Prev =NULL;
pBrush->Next =NULL;
pBrush->Faces =(FaceList *)fl;
pBrush->BList =NULL;
pBrush->Flags =ParentBrush->Flags;
pBrush->ModelId =ParentBrush->ModelId;
pBrush->GroupId =ParentBrush->GroupId;
pBrush->HullSize=ParentBrush->HullSize;
pBrush->Color =ParentBrush->Color;
pBrush->Name =Util_Strdup(ParentBrush->Name);
pBrush->Type =BRUSH_CSG;
FaceList_GetBounds(fl, &pBrush->BoundingBox);
}
return pBrush;
}
void Brush_Destroy(Brush **b)
{
if (b == NULL)
{
MessageBox(NULL, "Brush == NULL", "Brush_Destroy", MB_OK); // post 0.55
return;
}
if (*b == NULL)
{
MessageBox(NULL, "Brush == NULL", "Brush_Destroy", MB_OK); // post 0.55
return;
}
if ((*b)->Prev != NULL)
{
MessageBox(NULL, "Brush->Prev == NULL", "Brush_Destroy", MB_OK); // post 0.55
return;
}
if ((*b)->Next != NULL)
{
MessageBox(NULL, "Brush->Next == NULL", "Brush_Destroy", MB_OK); // post 0.55
return;
}
assert(b != NULL);
assert(*b != NULL);
assert((*b)->Prev == NULL);
assert((*b)->Next == NULL);
if((*b)->Type!=BRUSH_CSG)
{
if((*b)->BList)
{
BrushList_Destroy(&((*b)->BList));
}
}
if((*b)->Type!=BRUSH_MULTI)
{
if((*b)->Faces)
{
FaceList_Destroy(&((*b)->Faces));
}
}
if((*b)->Name)
{
geRam_Free ((*b)->Name);
}
geRam_Free (*b);
*b =NULL;
}
Brush *Brush_Clone(Brush const *from)
{
Brush *to = NULL;
FaceList *NewFaces;
BrushList *MBList;
if (from == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_Clone", MB_OK); // post 0.55
assert(from != NULL);
switch(from->Type)
{
case BRUSH_MULTI:
assert(from->Faces==NULL);
assert(from->BList);
MBList =BrushList_Clone(from->BList);
if(!MBList)
{
break;
}
to =Brush_Create(from->Type, NULL, MBList);
break;
case BRUSH_LEAF:
case BRUSH_CSG:
assert(from->Faces != NULL);
NewFaces =FaceList_Clone(from->Faces);
if(NewFaces != NULL)
{
to =Brush_Create(from->Type, NewFaces, NULL);
}
if(to==NULL)
{
geRam_Free (NewFaces);
}
break;
default:
assert(0);
break;
}
if(to != NULL)
{
to->Flags =from->Flags;
to->Type =from->Type;
to->ModelId =from->ModelId;
to->GroupId =from->GroupId;
to->HullSize =from->HullSize;
to->Color =from->Color;
Brush_SetName (to, from->Name);
to->BoundingBox =from->BoundingBox;
}
return to;
}
static void Brush_CopyFaceInfo(Brush const *src, Brush *dst)
{
assert(src);
assert(dst);
assert(src->Type!=BRUSH_MULTI);
assert(dst->Type!=BRUSH_MULTI);
assert(src->Faces);
assert(dst->Faces);
FaceList_CopyFaceInfo(src->Faces, dst->Faces);
}
int Brush_GetNumFaces(const Brush *b)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_GetNumFaces", MB_OK); // post 0.55
if (b->Faces == NULL)
MessageBox(NULL, "Brush->Faces == NULL", "Brush_GetNumFaces", MB_OK); // post 0.55
assert(b != NULL);
assert(b->Faces != NULL);
return FaceList_GetNumFaces(b->Faces);
}
Face *Brush_GetFace(const Brush *b, int i)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_GetFaces", MB_OK); // post 0.55
if (b->Faces == NULL)
MessageBox(NULL, "Brush->Faces == NULL", "Brush_GetFaces", MB_OK); // post 0.55
assert(b != NULL);
assert(b->Faces != NULL);
return FaceList_GetFace(b->Faces, i);
}
int Brush_GetModelId(const Brush *b)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_GetModelId", MB_OK); // post 0.55
assert(b != NULL);
return b->ModelId;
}
int Brush_GetGroupId(const Brush *b)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_GetGroupId", MB_OK); // post 0.55
assert(b != NULL);
return b->GroupId;
}
geFloat Brush_GetHullSize(const Brush *b)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_GetHullSize", MB_OK); // post 0.55
assert(b != NULL);
return b->HullSize;
}
uint32 Brush_GetColor(const Brush *b)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_GetColor", MB_OK); // post 0.55
assert(b != NULL);
return b->Color;
}
int Brush_GetType (const Brush *b)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_GetType", MB_OK); // post 0.55
return b->Type;
}
const char *Brush_GetName(const Brush *b)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_GetName", MB_OK); // post 0.55
assert(b != NULL);
//are empty names ok?
return b->Name;
}
const BrushList *Brush_GetBrushList(const Brush *b)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_GetBrushList", MB_OK); // post 0.55
assert(b != NULL);
//are empty names ok?
return b->BList;
}
void Brush_SetModelId(Brush *b, const int mid)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_SetModelId", MB_OK); // post 0.55
assert(b != NULL);
if (b->Type == BRUSH_MULTI)
{
BrushList_SetInt (b->BList, mid, Brush_SetModelId);
}
b->ModelId =mid;
}
//should this be set in child brushes too?
void Brush_SetGroupId(Brush *b, const int gid)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_SetGroupId", MB_OK); // post 0.55
assert(b != NULL);
if (b->Type == BRUSH_MULTI)
{
BrushList_SetInt (b->BList, gid, Brush_SetGroupId);
}
b->GroupId =gid;
}
void Brush_SetHullSize(Brush *b, const geFloat hsize)
{
geFloat RealHullSize = hsize;
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_SetHullSize", MB_OK); // post 0.55
assert(b != NULL);
if (hsize < 1.0f)
{
RealHullSize = 1.0f;
}
if(b->Type==BRUSH_MULTI)
{
BrushList_SetFloat(b->BList, RealHullSize, Brush_SetHullSize);
}
b->HullSize =RealHullSize;
}
void Brush_SetColor(Brush *b, const uint32 newcolor)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_SetColor", MB_OK); // post 0.55
assert(b != NULL);
if(b->Type==BRUSH_MULTI)
{
BrushList_SetUint32(b->BList, newcolor, Brush_SetColor);
}
b->Color =newcolor;
}
//should these go to child brushes?
void Brush_SetName(Brush *b, const char *newname)
{
if (b == NULL)
MessageBox(NULL, "Brush == NULL", "Brush_SetName", MB_OK); // post 0.55
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -