light: implement _shadowworldonly, fix _shadowself which was broken
This commit is contained in:
parent
62db977309
commit
6f07303504
|
|
@ -158,8 +158,10 @@ CreateGeometryFromWindings(RTCScene scene, const std::vector<winding_t *> &windi
|
|||
|
||||
RTCDevice device;
|
||||
RTCScene scene;
|
||||
/* global shadow casters */
|
||||
sceneinfo skygeom, solidgeom, fencegeom, selfshadowgeom, switchableshadowgeom;
|
||||
|
||||
sceneinfo skygeom; // sky. always occludes.
|
||||
sceneinfo solidgeom; // solids. always occludes.
|
||||
sceneinfo filtergeom; // conditional occluders.. needs to run ray intersection filter
|
||||
|
||||
static const bsp2_t *bsp_static;
|
||||
|
||||
|
|
@ -175,12 +177,8 @@ Embree_SceneinfoForGeomID(unsigned int geomID)
|
|||
return skygeom;
|
||||
} else if (geomID == solidgeom.geomID) {
|
||||
return solidgeom;
|
||||
} else if (geomID == fencegeom.geomID) {
|
||||
return fencegeom;
|
||||
} else if (geomID == selfshadowgeom.geomID) {
|
||||
return selfshadowgeom;
|
||||
} else if (geomID == switchableshadowgeom.geomID) {
|
||||
return switchableshadowgeom;
|
||||
} else if (geomID == filtergeom.geomID) {
|
||||
return filtergeom;
|
||||
} else {
|
||||
Error("unexpected geomID");
|
||||
}
|
||||
|
|
@ -227,6 +225,15 @@ void AddGlassToRay(const RTCIntersectContext* context, unsigned rayIndex, float
|
|||
|
||||
void AddDynamicOccluderToRay(const RTCIntersectContext* context, unsigned rayIndex, int style);
|
||||
|
||||
static const unsigned RAYMASK_HASMODEL_SHIFT = 0;
|
||||
static const unsigned RAYMASK_HASMODEL_MASK = (1 << RAYMASK_HASMODEL_SHIFT);
|
||||
|
||||
static const unsigned RAYMASK_MODELINDEX_SHIFT = 1;
|
||||
static const unsigned RAYMASK_MODELINDEX_MASK = (0xffff << RAYMASK_MODELINDEX_SHIFT);
|
||||
|
||||
static const unsigned RAYMASK_RAYINDEX_SHIFT = 17;
|
||||
static const unsigned RAYMASK_RAYINDEX_MASK = (0x7fff << RAYMASK_RAYINDEX_SHIFT);
|
||||
|
||||
// called to evaluate transparency
|
||||
template<filtertype_t filtertype>
|
||||
static void
|
||||
|
|
@ -251,76 +258,94 @@ Embree_FilterFuncN(int* valid,
|
|||
const unsigned &primID = RTCHitN_primID(potentialHit, N, i);
|
||||
|
||||
// unpack ray index
|
||||
const unsigned rayIndex = (mask >> 1);
|
||||
const bool hasmodel = static_cast<bool>((mask & RAYMASK_HASMODEL_MASK) >> RAYMASK_HASMODEL_SHIFT);
|
||||
const unsigned raySourceModelindex = (mask & RAYMASK_MODELINDEX_MASK) >> RAYMASK_MODELINDEX_SHIFT;
|
||||
const unsigned rayIndex = (mask & RAYMASK_RAYINDEX_MASK) >> RAYMASK_RAYINDEX_SHIFT;
|
||||
|
||||
// bail if we hit a selfshadow face, but the ray is not coming from within that model
|
||||
if (geomID == selfshadowgeom.geomID) {
|
||||
const bool from_selfshadow = ((mask & 1) == 1);
|
||||
if (!from_selfshadow) {
|
||||
const modelinfo_t *source_modelinfo = hasmodel ? ModelInfoForModel(bsp_static, raySourceModelindex) : nullptr;
|
||||
const modelinfo_t *hit_modelinfo = Embree_LookupModelinfo(geomID, primID);
|
||||
Q_assert(hit_modelinfo != nullptr);
|
||||
|
||||
if (hit_modelinfo->shadowworldonly.boolValue()) {
|
||||
// we hit "_shadowworldonly" "1" geometry. Ignore the hit unless we are from world.
|
||||
if (!source_modelinfo || !source_modelinfo->isWorld()) {
|
||||
// reject hit
|
||||
valid[i] = INVALID;
|
||||
continue;
|
||||
}
|
||||
} else if (geomID == switchableshadowgeom.geomID) {
|
||||
}
|
||||
|
||||
if (hit_modelinfo->shadowself.boolValue()) {
|
||||
// only casts shadows on itself
|
||||
if (source_modelinfo != hit_modelinfo) {
|
||||
// reject hit
|
||||
valid[i] = INVALID;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (hit_modelinfo->switchableshadow.boolValue()) {
|
||||
// we hit a dynamic shadow caster. reject the hit, but store the
|
||||
// info about what we hit.
|
||||
const modelinfo_t *modelinfo = Embree_LookupModelinfo(geomID, primID);
|
||||
int style = modelinfo->switchshadstyle.intValue();
|
||||
|
||||
int style = hit_modelinfo->switchshadstyle.intValue();
|
||||
|
||||
AddDynamicOccluderToRay(context, rayIndex, style);
|
||||
|
||||
// reject hit
|
||||
valid[i] = INVALID;
|
||||
continue;
|
||||
} else {
|
||||
// test fence textures and glass
|
||||
const bsp2_dface_t *face = Embree_LookupFace(geomID, primID);
|
||||
const modelinfo_t *modelinfo = Embree_LookupModelinfo(geomID, primID);
|
||||
}
|
||||
|
||||
// test fence textures and glass
|
||||
const bsp2_dface_t *face = Embree_LookupFace(geomID, primID);
|
||||
const char *name = Face_TextureName(bsp_static, face);
|
||||
|
||||
const float alpha = hit_modelinfo->alpha.floatValue();
|
||||
const bool isFence = (name[0] == '{');
|
||||
const bool isGlass = (alpha < 1.0f);
|
||||
|
||||
if (isFence || isGlass) {
|
||||
vec3_t hitpoint;
|
||||
Embree_RayEndpoint(ray, potentialHit, N, i, hitpoint);
|
||||
const int sample = SampleTexture(face, bsp_static, hitpoint);
|
||||
|
||||
float alpha = 1.0f;
|
||||
if (modelinfo != nullptr) {
|
||||
alpha = modelinfo->alpha.floatValue();
|
||||
if (alpha < 1.0f) {
|
||||
// hit glass...
|
||||
if (isGlass) {
|
||||
// hit glass...
|
||||
|
||||
vec3_t rayDir = {
|
||||
RTCRayN_dir_x(ray, N, i),
|
||||
RTCRayN_dir_y(ray, N, i),
|
||||
RTCRayN_dir_z(ray, N, i)
|
||||
};
|
||||
vec3_t potentialHitGeometryNormal = {
|
||||
RTCHitN_Ng_x(potentialHit, N, i),
|
||||
RTCHitN_Ng_y(potentialHit, N, i),
|
||||
RTCHitN_Ng_z(potentialHit, N, i)
|
||||
};
|
||||
vec3_t rayDir = {
|
||||
RTCRayN_dir_x(ray, N, i),
|
||||
RTCRayN_dir_y(ray, N, i),
|
||||
RTCRayN_dir_z(ray, N, i)
|
||||
};
|
||||
vec3_t potentialHitGeometryNormal = {
|
||||
RTCHitN_Ng_x(potentialHit, N, i),
|
||||
RTCHitN_Ng_y(potentialHit, N, i),
|
||||
RTCHitN_Ng_z(potentialHit, N, i)
|
||||
};
|
||||
|
||||
VectorNormalize(rayDir);
|
||||
VectorNormalize(potentialHitGeometryNormal);
|
||||
VectorNormalize(rayDir);
|
||||
VectorNormalize(potentialHitGeometryNormal);
|
||||
|
||||
const vec_t raySurfaceCosAngle = DotProduct(rayDir, potentialHitGeometryNormal);
|
||||
const vec_t raySurfaceCosAngle = DotProduct(rayDir, potentialHitGeometryNormal);
|
||||
|
||||
// only pick up the color of the glass on the _exiting_ side of the glass.
|
||||
// (we currently trace "backwards", from surface point --> light source)
|
||||
if (raySurfaceCosAngle < 0) {
|
||||
vec3_t samplecolor;
|
||||
glm_to_vec3_t(Palette_GetColor(sample), samplecolor);
|
||||
VectorScale(samplecolor, 1/255.0, samplecolor);
|
||||
// only pick up the color of the glass on the _exiting_ side of the glass.
|
||||
// (we currently trace "backwards", from surface point --> light source)
|
||||
if (raySurfaceCosAngle < 0) {
|
||||
vec3_t samplecolor;
|
||||
glm_to_vec3_t(Palette_GetColor(sample), samplecolor);
|
||||
VectorScale(samplecolor, 1/255.0, samplecolor);
|
||||
|
||||
AddGlassToRay(context, rayIndex, alpha, samplecolor);
|
||||
}
|
||||
|
||||
// reject hit
|
||||
valid[i] = INVALID;
|
||||
continue;
|
||||
AddGlassToRay(context, rayIndex, alpha, samplecolor);
|
||||
}
|
||||
|
||||
// reject hit
|
||||
valid[i] = INVALID;
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *name = Face_TextureName(bsp_static, face);
|
||||
if (name[0] == '{') {
|
||||
|
||||
if (isFence) {
|
||||
if (sample == 255) {
|
||||
// reject hit
|
||||
valid[i] = INVALID;
|
||||
|
|
@ -526,53 +551,72 @@ Embree_TraceInit(const bsp2_t *bsp)
|
|||
bsp_static = bsp;
|
||||
Q_assert(device == nullptr);
|
||||
|
||||
std::vector<const bsp2_dface_t *> skyfaces, solidfaces, fencefaces, selfshadowfaces, switchableshadowfaces;
|
||||
std::vector<const bsp2_dface_t *> skyfaces, solidfaces, filterfaces;
|
||||
|
||||
/* Check against the list of global shadow casters */
|
||||
for (const modelinfo_t *model : tracelist) {
|
||||
// TODO: factor out
|
||||
const bool isWorld = (model->model == &bsp->dmodels[0]);
|
||||
// check all modelinfos
|
||||
for (int mi = 0; mi<bsp->nummodels; mi++) {
|
||||
const modelinfo_t *model = ModelInfoForModel(bsp, mi);
|
||||
|
||||
const bool isWorld = model->isWorld();
|
||||
const bool shadow = model->shadow.boolValue();
|
||||
const bool shadowself = model->shadowself.boolValue();
|
||||
const bool shadowworldonly = model->shadowworldonly.boolValue();
|
||||
const bool switchableshadow = model->switchableshadow.boolValue();
|
||||
|
||||
if (!(isWorld || shadow || shadowself || shadowworldonly || switchableshadow))
|
||||
continue;
|
||||
|
||||
for (int i=0; i<model->model->numfaces; i++) {
|
||||
const bsp2_dface_t *face = BSP_GetFace(bsp, model->model->firstface + i);
|
||||
const char *texname = Face_TextureName(bsp, face);
|
||||
|
||||
// check for TEX_NOSHADOW
|
||||
const uint64_t extended_flags = extended_texinfo_flags[face->texinfo];
|
||||
if (extended_flags & TEX_NOSHADOW)
|
||||
continue;
|
||||
|
||||
const char *texname = Face_TextureName(bsp, face);
|
||||
// handle switchableshadow
|
||||
if (switchableshadow) {
|
||||
filterfaces.push_back(face);
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle glass
|
||||
if (model->alpha.floatValue() < 1.0f) {
|
||||
fencefaces.push_back(face);
|
||||
} else if (!Q_strncasecmp("sky", texname, 3)) {
|
||||
filterfaces.push_back(face);
|
||||
continue;
|
||||
}
|
||||
|
||||
// fence
|
||||
if (texname[0] == '{') {
|
||||
filterfaces.push_back(face);
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle sky
|
||||
if (!Q_strncasecmp("sky", texname, 3)) {
|
||||
skyfaces.push_back(face);
|
||||
} else if (texname[0] == '{') {
|
||||
fencefaces.push_back(face);
|
||||
} else if (texname[0] == '*') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// liquids
|
||||
if (texname[0] == '*') {
|
||||
if (!isWorld) {
|
||||
// world liquids never cast shadows; shadow casting bmodel liquids do
|
||||
solidfaces.push_back(face);
|
||||
}
|
||||
} else {
|
||||
solidfaces.push_back(face);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Self-shadow models */
|
||||
for (const modelinfo_t *model : selfshadowlist) {
|
||||
for (int i=0; i<model->model->numfaces; i++) {
|
||||
const bsp2_dface_t *face = BSP_GetFace(bsp, model->model->firstface + i);
|
||||
selfshadowfaces.push_back(face);
|
||||
}
|
||||
}
|
||||
// solid faces
|
||||
|
||||
/* Dynamic-shadow models */
|
||||
for (const modelinfo_t *model : switchableshadowlist) {
|
||||
for (int i=0; i<model->model->numfaces; i++) {
|
||||
const bsp2_dface_t *face = BSP_GetFace(bsp, model->model->firstface + i);
|
||||
switchableshadowfaces.push_back(face);
|
||||
if (isWorld || shadow){
|
||||
solidfaces.push_back(face);
|
||||
} else {
|
||||
// shadowself or shadowworldonly
|
||||
Q_assert(shadowself || shadowworldonly);
|
||||
filterfaces.push_back(face);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -605,29 +649,19 @@ Embree_TraceInit(const bsp2_t *bsp)
|
|||
scene = rtcDeviceNewScene(device, RTC_SCENE_STATIC | RTC_SCENE_COHERENT, RTC_INTERSECT1 | RTC_INTERSECT_STREAM);
|
||||
skygeom = CreateGeometry(bsp, scene, skyfaces);
|
||||
solidgeom = CreateGeometry(bsp, scene, solidfaces);
|
||||
fencegeom = CreateGeometry(bsp, scene, fencefaces);
|
||||
selfshadowgeom = CreateGeometry(bsp, scene, selfshadowfaces);
|
||||
switchableshadowgeom = CreateGeometry(bsp, scene, switchableshadowfaces);
|
||||
filtergeom = CreateGeometry(bsp, scene, filterfaces);
|
||||
CreateGeometryFromWindings(scene, skipwindings);
|
||||
|
||||
rtcSetIntersectionFilterFunctionN(scene, fencegeom.geomID, Embree_FilterFuncN<filtertype_t::INTERSECTION>);
|
||||
rtcSetOcclusionFilterFunctionN(scene, fencegeom.geomID, Embree_FilterFuncN<filtertype_t::OCCLUSION>);
|
||||
|
||||
rtcSetIntersectionFilterFunctionN(scene, selfshadowgeom.geomID, Embree_FilterFuncN<filtertype_t::INTERSECTION>);
|
||||
rtcSetOcclusionFilterFunctionN(scene, selfshadowgeom.geomID, Embree_FilterFuncN<filtertype_t::OCCLUSION>);
|
||||
|
||||
rtcSetIntersectionFilterFunctionN(scene, switchableshadowgeom.geomID, Embree_FilterFuncN<filtertype_t::INTERSECTION>);
|
||||
rtcSetOcclusionFilterFunctionN(scene, switchableshadowgeom.geomID, Embree_FilterFuncN<filtertype_t::OCCLUSION>);
|
||||
rtcSetIntersectionFilterFunctionN(scene, filtergeom.geomID, Embree_FilterFuncN<filtertype_t::INTERSECTION>);
|
||||
rtcSetOcclusionFilterFunctionN(scene, filtergeom.geomID, Embree_FilterFuncN<filtertype_t::OCCLUSION>);
|
||||
|
||||
rtcCommit (scene);
|
||||
|
||||
logprint("Embree_TraceInit: %d skyfaces %d solidfaces %d fencefaces %d selfshadowfaces %d switchableshadowfaces %d skipwindings\n",
|
||||
(int)skyfaces.size(),
|
||||
(int)solidfaces.size(),
|
||||
(int)fencefaces.size(),
|
||||
(int)selfshadowfaces.size(),
|
||||
(int)switchableshadowfaces.size(),
|
||||
(int)skipwindings.size());
|
||||
logprint("Embree_TraceInit:\n");
|
||||
logprint("\t%d sky faces\n", (int)skyfaces.size());
|
||||
logprint("\t%d solid faces\n", (int)solidfaces.size());
|
||||
logprint("\t%d filtered faces\n", (int)filterfaces.size());
|
||||
logprint("\t%d shadow-casting skip faces\n", (int)skipwindings.size());
|
||||
|
||||
FreeWindings(skipwindings);
|
||||
}
|
||||
|
|
@ -646,12 +680,21 @@ static RTCRay SetupRay(unsigned rayindex, const vec3_t start, const vec3_t dir,
|
|||
// NOTE: we are not using the ray masking feature of embree, but just using
|
||||
// this field to store whether the ray is coming from self-shadow geometry
|
||||
ray.mask = 0;
|
||||
if (modelinfo && modelinfo->shadowself.boolValue()) {
|
||||
ray.mask |= 1;
|
||||
|
||||
if (modelinfo) {
|
||||
ray.mask |= RAYMASK_HASMODEL_MASK;
|
||||
|
||||
// Hacky..
|
||||
const int modelindex = (modelinfo->model - bsp_static->dmodels);
|
||||
Q_assert(modelindex >= 0 && modelindex < bsp_static->nummodels);
|
||||
Q_assert(modelindex <= 65535);
|
||||
|
||||
ray.mask |= (static_cast<unsigned>(modelindex) << RAYMASK_MODELINDEX_SHIFT);
|
||||
}
|
||||
|
||||
// pack the ray index into the rest of the mask
|
||||
ray.mask |= (rayindex << 1);
|
||||
Q_assert(rayindex <= 32767);
|
||||
ray.mask |= (rayindex << RAYMASK_RAYINDEX_SHIFT);
|
||||
|
||||
ray.time = 0.f;
|
||||
return ray;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
// entity 1
|
||||
{
|
||||
"classname" "light"
|
||||
"origin" "-40 8 104"
|
||||
"origin" "-40 8 152"
|
||||
"angle" "-0"
|
||||
"delay" "2"
|
||||
"light" "500"
|
||||
|
|
@ -80,45 +80,53 @@
|
|||
"_shadowself" "1"
|
||||
// brush 0
|
||||
{
|
||||
( -72 -136 96 ) ( 24 -136 112 ) ( 24 -136 96 ) narrow -8 80 -0 1 1
|
||||
( -40 -152 96 ) ( -40 -88 112 ) ( -40 -152 112 ) narrow -8 80 -0 1 1
|
||||
( -72 -152 48 ) ( 24 -88 48 ) ( -72 -88 48 ) narrow -8 8 -0 1 1
|
||||
( -72 -152 112 ) ( 24 -88 112 ) ( 24 -152 112 ) narrow -8 8 -0 1 1
|
||||
( -72 -120 96 ) ( 24 -120 112 ) ( -72 -120 112 ) narrow -8 80 -0 1 1
|
||||
( 48 -152 96 ) ( 48 -88 112 ) ( 48 -88 96 ) narrow -8 80 -0 1 1
|
||||
( -64 -176 72 ) ( -64 -112 72 ) ( -80 -192 72 ) narrow -0 -0 -0 1 1
|
||||
( -80 -96 88 ) ( -80 -192 88 ) ( -80 -96 72 ) narrow -0 56 -0 1 1
|
||||
( -80 -192 88 ) ( -64 -176 88 ) ( -80 -192 72 ) narrow 0 0 0 1 1
|
||||
( -80 -96 88 ) ( -64 -112 88 ) ( -80 -192 88 ) narrow -0 -0 -0 1 1
|
||||
( -64 -176 88 ) ( -64 -112 88 ) ( -64 -176 72 ) narrow 16 56 -0 1 1
|
||||
( -64 -112 72 ) ( -64 -112 88 ) ( -80 -96 72 ) narrow 0 0 0 1 1
|
||||
}
|
||||
// brush 1
|
||||
{
|
||||
( -80 -192 72 ) ( 80 -192 72 ) ( -64 -176 72 ) narrow -0 -0 -0 1 1
|
||||
( -64 -176 88 ) ( -80 -192 88 ) ( -64 -176 72 ) narrow 0 0 0 1 1
|
||||
( 64 -176 72 ) ( 64 -176 88 ) ( -64 -176 72 ) narrow -16 56 -0 1 1
|
||||
( -80 -192 88 ) ( 80 -192 88 ) ( -80 -192 72 ) narrow -0 56 -0 1 1
|
||||
( 80 -192 72 ) ( 80 -192 88 ) ( 64 -176 72 ) narrow 0 0 0 1 1
|
||||
( 64 -176 88 ) ( 80 -192 88 ) ( -64 -176 88 ) narrow -0 -0 -0 1 1
|
||||
}
|
||||
// brush 2
|
||||
{
|
||||
( -80 -96 72 ) ( -80 -96 88 ) ( -64 -112 72 ) narrow 0 0 0 1 1
|
||||
( -64 -112 88 ) ( 64 -112 88 ) ( -64 -112 72 ) narrow -16 56 -0 1 1
|
||||
( 64 -112 72 ) ( 80 -96 72 ) ( -64 -112 72 ) narrow -0 -0 -0 1 1
|
||||
( -80 -96 88 ) ( 80 -96 88 ) ( -64 -112 88 ) narrow -0 -0 -0 1 1
|
||||
( 64 -112 88 ) ( 80 -96 88 ) ( 64 -112 72 ) narrow 0 0 0 1 1
|
||||
( 80 -96 72 ) ( 80 -96 88 ) ( -80 -96 72 ) narrow -0 56 -0 1 1
|
||||
}
|
||||
// brush 3
|
||||
{
|
||||
( 80 -192 72 ) ( 80 -96 72 ) ( 64 -176 72 ) narrow -0 -0 -0 1 1
|
||||
( 64 -112 88 ) ( 64 -176 88 ) ( 64 -112 72 ) narrow 16 56 -0 1 1
|
||||
( 64 -176 88 ) ( 80 -192 88 ) ( 64 -176 72 ) narrow 0 0 0 1 1
|
||||
( 64 -112 88 ) ( 80 -96 88 ) ( 64 -176 88 ) narrow -0 -0 -0 1 1
|
||||
( 80 -192 88 ) ( 80 -96 88 ) ( 80 -192 72 ) narrow -0 56 -0 1 1
|
||||
( 80 -96 72 ) ( 80 -96 88 ) ( 64 -112 72 ) narrow 0 0 0 1 1
|
||||
}
|
||||
// brush 4
|
||||
{
|
||||
( -64 -176 64 ) ( 64 -176 80 ) ( 64 -176 64 ) narrow 0 0 0 1 1
|
||||
( -64 -176 64 ) ( -64 -112 80 ) ( -64 -176 80 ) narrow 0 0 0 1 1
|
||||
( -64 -176 64 ) ( 64 -112 64 ) ( -64 -112 64 ) narrow 0 0 0 1 1
|
||||
( -64 -176 80 ) ( 64 -112 80 ) ( 64 -176 80 ) narrow 0 0 0 1 1
|
||||
( -64 -112 64 ) ( 64 -112 80 ) ( -64 -112 80 ) narrow 0 0 0 1 1
|
||||
( 64 -176 64 ) ( 64 -112 80 ) ( 64 -112 64 ) narrow 0 0 0 1 1
|
||||
}
|
||||
}
|
||||
// entity 4
|
||||
{
|
||||
"classname" "func_wall"
|
||||
"_shadowself" "1"
|
||||
// brush 0
|
||||
{
|
||||
( -80 -144 88 ) ( 16 -144 104 ) ( 16 -144 88 ) narrow -0 72 -0 1 1
|
||||
( -64 -160 88 ) ( -64 -96 104 ) ( -64 -160 104 ) narrow -0 72 -0 1 1
|
||||
( -80 -160 56 ) ( 16 -96 56 ) ( -80 -96 56 ) narrow -0 -0 -0 1 1
|
||||
( -80 -160 104 ) ( 16 -96 104 ) ( 16 -160 104 ) narrow -0 -0 -0 1 1
|
||||
( -80 -112 88 ) ( 16 -112 104 ) ( -80 -112 104 ) narrow -0 72 -0 1 1
|
||||
( 64 -160 88 ) ( 64 -96 104 ) ( 64 -96 88 ) narrow -0 72 -0 1 1
|
||||
}
|
||||
}
|
||||
// entity 5
|
||||
{
|
||||
"classname" "func_wall"
|
||||
"_shadowself" "1"
|
||||
// brush 0
|
||||
{
|
||||
( -80 -160 72 ) ( 16 -160 88 ) ( 16 -160 72 ) narrow -0 56 -0 1 1
|
||||
( -80 -160 72 ) ( -80 -96 88 ) ( -80 -160 88 ) narrow -0 56 -0 1 1
|
||||
( -80 -160 72 ) ( 16 -96 72 ) ( -80 -96 72 ) narrow -0 -0 -0 1 1
|
||||
( -80 -160 88 ) ( 16 -96 88 ) ( 16 -160 88 ) narrow -0 -0 -0 1 1
|
||||
( -80 -96 72 ) ( 16 -96 88 ) ( -80 -96 88 ) narrow -0 56 -0 1 1
|
||||
( 80 -160 72 ) ( 80 -96 88 ) ( 80 -96 72 ) narrow -0 56 -0 1 1
|
||||
}
|
||||
}
|
||||
// entity 6
|
||||
{
|
||||
"classname" "func_wall"
|
||||
"_shadow" "1"
|
||||
// brush 0
|
||||
{
|
||||
|
|
@ -130,7 +138,7 @@
|
|||
( -32 -80 16 ) ( -32 -64 32 ) ( -32 -64 16 ) narrow -112 -0 -0 1 1
|
||||
}
|
||||
}
|
||||
// entity 7
|
||||
// entity 5
|
||||
{
|
||||
"classname" "func_illusionary"
|
||||
// brush 0
|
||||
|
|
@ -143,7 +151,7 @@
|
|||
( 144 -320 16 ) ( 144 -256 80 ) ( 144 -256 16 ) narrow -0 16 -0 1 1
|
||||
}
|
||||
}
|
||||
// entity 8
|
||||
// entity 6
|
||||
{
|
||||
"classname" "func_wall"
|
||||
"_shadowworldonly" "1"
|
||||
|
|
@ -157,3 +165,53 @@
|
|||
( -0 -80 16 ) ( -0 -64 32 ) ( -0 -64 16 ) narrow -112 -0 -0 1 1
|
||||
}
|
||||
}
|
||||
// entity 7
|
||||
{
|
||||
"classname" "func_wall"
|
||||
"_shadowself" "1"
|
||||
// brush 0
|
||||
{
|
||||
( -32 -152 144 ) ( -96 -152 144 ) ( -16 -152 160 ) narrow 80 80 270 1 -1
|
||||
( -112 -136 160 ) ( -16 -136 160 ) ( -112 -152 160 ) narrow -80 -40 180 1 -1
|
||||
( -16 -136 160 ) ( -32 -136 144 ) ( -16 -152 160 ) narrow 96 -96 270 1 1
|
||||
( -112 -136 160 ) ( -96 -136 144 ) ( -16 -136 160 ) narrow 80 80 270 1 -1
|
||||
( -32 -136 144 ) ( -96 -136 144 ) ( -32 -152 144 ) narrow -64 -40 180 1 -1
|
||||
( -96 -152 144 ) ( -96 -136 144 ) ( -112 -152 160 ) narrow -0 -96 90 1 -1
|
||||
}
|
||||
// brush 1
|
||||
{
|
||||
( -16 -152 160 ) ( -16 -152 -0 ) ( -32 -152 144 ) narrow 80 80 270 1 -1
|
||||
( -32 -136 144 ) ( -16 -136 160 ) ( -32 -152 144 ) narrow 96 -96 270 1 1
|
||||
( -32 -152 16 ) ( -32 -136 16 ) ( -32 -152 144 ) narrow 64 -40 270 1 1
|
||||
( -16 -136 160 ) ( -16 -136 -0 ) ( -16 -152 160 ) narrow 80 -40 270 1 1
|
||||
( -16 -152 -0 ) ( -16 -136 -0 ) ( -32 -152 16 ) narrow -64 -96 90 1 -1
|
||||
( -32 -136 16 ) ( -16 -136 -0 ) ( -32 -136 144 ) narrow 80 80 270 1 -1
|
||||
}
|
||||
// brush 2
|
||||
{
|
||||
( -112 -152 160 ) ( -112 -136 160 ) ( -96 -152 144 ) narrow -0 -96 90 1 -1
|
||||
( -96 -136 144 ) ( -96 -136 16 ) ( -96 -152 144 ) narrow 64 -40 270 1 1
|
||||
( -96 -152 16 ) ( -112 -152 -0 ) ( -96 -152 144 ) narrow 80 80 270 1 -1
|
||||
( -112 -136 160 ) ( -112 -136 -0 ) ( -96 -136 144 ) narrow 80 80 270 1 -1
|
||||
( -96 -136 16 ) ( -112 -136 -0 ) ( -96 -152 16 ) narrow 32 -96 270 1 1
|
||||
( -112 -152 -0 ) ( -112 -136 -0 ) ( -112 -152 160 ) narrow 80 -40 270 1 1
|
||||
}
|
||||
// brush 3
|
||||
{
|
||||
( -16 -152 -0 ) ( -112 -152 -0 ) ( -32 -152 16 ) narrow 80 80 270 1 -1
|
||||
( -96 -136 16 ) ( -32 -136 16 ) ( -96 -152 16 ) narrow -64 -40 180 1 -1
|
||||
( -32 -136 16 ) ( -16 -136 -0 ) ( -32 -152 16 ) narrow -64 -96 90 1 -1
|
||||
( -96 -136 16 ) ( -112 -136 -0 ) ( -32 -136 16 ) narrow 80 80 270 1 -1
|
||||
( -16 -136 -0 ) ( -112 -136 -0 ) ( -16 -152 -0 ) narrow -80 -40 180 1 -1
|
||||
( -112 -152 -0 ) ( -112 -136 -0 ) ( -96 -152 16 ) narrow 32 -96 270 1 1
|
||||
}
|
||||
// brush 4
|
||||
{
|
||||
( -32 -160 144 ) ( -32 -144 16 ) ( -32 -160 16 ) narrow 80 -96 270 1 1
|
||||
( -32 -160 144 ) ( -96 -144 144 ) ( -32 -144 144 ) narrow -80 -96 180 1 -1
|
||||
( -32 -160 144 ) ( -96 -160 16 ) ( -96 -160 144 ) narrow 80 80 270 1 -1
|
||||
( -32 -144 144 ) ( -96 -144 16 ) ( -32 -144 16 ) narrow 80 80 270 1 -1
|
||||
( -96 -160 144 ) ( -96 -144 16 ) ( -96 -144 144 ) narrow 80 -96 270 1 1
|
||||
( -32 -160 16 ) ( -96 -144 16 ) ( -96 -160 16 ) narrow -80 -96 180 1 -1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue