2155 lines
45 KiB
C++
2155 lines
45 KiB
C++
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Crytek Engine Source File.
|
|
// Copyright (C), Crytek Studios, 2002.
|
|
// -------------------------------------------------------------------------
|
|
// File name: brush.cpp
|
|
// Version: v1.00
|
|
// Created: 8/7/2002 by Timur.
|
|
// Compilers: Visual Studio.NET
|
|
// Description:
|
|
// -------------------------------------------------------------------------
|
|
// History: Based on Andrey's Indoor editor.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "StdAfx.h"
|
|
#include "Brush.h"
|
|
|
|
#include "BrushPlane.h"
|
|
#include "BrushPoly.h"
|
|
#include "BrushFace.h"
|
|
#include "Settings.h"
|
|
#include "Grid.h"
|
|
#include "list2.h"
|
|
#include "EdMesh.h"
|
|
|
|
#include <I3Dengine.h>
|
|
|
|
#define MIN_BOUNDS_SIZE 0.01f
|
|
|
|
#define SIDE_FRONT 0
|
|
#define SIDE_BACK 1
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SBrushSubSelection implementation.
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool SBrushSubSelection::AddPoint( Vec3 *pnt )
|
|
{
|
|
if (std::find(points.begin(),points.end(),pnt) != points.end())
|
|
return false;
|
|
|
|
points.push_back(pnt);
|
|
return true;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrushSubSelection::Clear()
|
|
{
|
|
points.clear();
|
|
}
|
|
|
|
SBrush::SBrush()
|
|
{
|
|
m_flags = 0;
|
|
m_prefabGeom = 0;
|
|
m_indoorGeom = 0;
|
|
// m_indoorGeom = GetIEditor()->Get3DEngine()->MakeObject();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Brush implementations.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
SBrush::~SBrush()
|
|
{
|
|
ClearFaces();
|
|
|
|
if (m_indoorGeom)
|
|
{
|
|
//m_indoorGeom->Release(); // May be will be deleted in Indoors.
|
|
m_indoorGeom = 0;
|
|
}
|
|
|
|
//TBrush *b = (TBrush *)this;
|
|
|
|
//b->Unlink();
|
|
//UnlinkFromObj();
|
|
}
|
|
|
|
SBrush& SBrush::operator = (const SBrush& b)
|
|
{
|
|
int i;
|
|
|
|
m_bounds.min = b.m_bounds.min;
|
|
m_bounds.max = b.m_bounds.max;
|
|
|
|
for (i=0; i<m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *f = m_Faces[i];
|
|
delete f;
|
|
}
|
|
m_Faces.clear();
|
|
for (i=0; i<b.m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *f = new SBrushFace;
|
|
m_Faces.push_back(f);
|
|
*f = *b.m_Faces[i];
|
|
}
|
|
m_flags = b.m_flags;
|
|
|
|
return *this;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::MakeFacePlanes()
|
|
{
|
|
for (int i = 0; i < m_Faces.size(); i++)
|
|
{
|
|
m_Faces[i]->MakePlane();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::ClearFaces()
|
|
{
|
|
for (int i = 0; i < m_Faces.size(); i++)
|
|
{
|
|
delete m_Faces[i];
|
|
}
|
|
m_Faces.clear();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
float SBrush::GetVolume()
|
|
{
|
|
int i;
|
|
SBrushPoly *p;
|
|
Vec3d corner;
|
|
float d, area, volume;
|
|
SBrushPlane *plane;
|
|
|
|
p = NULL;
|
|
for (i=0; i<m_Faces.size(); i++)
|
|
{
|
|
p = m_Faces[i]->m_Poly;
|
|
if (p)
|
|
break;
|
|
}
|
|
if (!p)
|
|
return 0;
|
|
corner = p->m_Pts[0].xyz;
|
|
|
|
volume = 0;
|
|
for ( ; i<m_Faces.size(); i++)
|
|
{
|
|
p = m_Faces[i]->m_Poly;
|
|
if (!p)
|
|
continue;
|
|
plane = &m_Faces[i]->m_Plane;
|
|
d = -((corner | plane->normal) - plane->dist);
|
|
area = p->Area();
|
|
volume += d*area;
|
|
}
|
|
|
|
volume /= 3.0f;
|
|
return volume;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::ClipPrefabModels(bool bClip)
|
|
{
|
|
//@ASK Andrey.
|
|
/*
|
|
SBrushFace *f;
|
|
int i, j;
|
|
TPrefabItem *pi;
|
|
|
|
for (i=0; i<m_Faces.size(); i++)
|
|
{
|
|
f = m_Faces[i];
|
|
for (pi=f->m_Prefabs; pi; pi=pi->Next)
|
|
{
|
|
if (!bClip)
|
|
{
|
|
if (pi->m_Model)
|
|
delete pi->m_Model;
|
|
pi->m_Model = NULL;
|
|
continue;
|
|
}
|
|
if (!pi->m_Geom || !pi->m_Geom->mModel)
|
|
continue;
|
|
for (j=0; j<m_Faces.size(); j++)
|
|
{
|
|
if (j == i)
|
|
continue;
|
|
m_Faces[j]->ClipPrefab(pi);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
SBrushPoly* SBrush::CreateFacePoly( SBrushFace *face )
|
|
{
|
|
SBrushPoly *p;
|
|
SBrushFace *clip;
|
|
SBrushPlane plane;
|
|
bool past;
|
|
|
|
p = face->m_Plane.CreatePoly();
|
|
|
|
int numFaces = m_Faces.size();
|
|
|
|
past = false;
|
|
for (int i = 0; i < numFaces; i++)
|
|
{
|
|
clip = m_Faces[i];
|
|
if (!p)
|
|
return p;
|
|
if (clip == face)
|
|
{
|
|
past = true;
|
|
continue;
|
|
}
|
|
if ((face->m_Plane.normal.Dot(clip->m_Plane.normal) > 0.999) &&
|
|
(fabs(face->m_Plane.dist - clip->m_Plane.dist) < DIST_EPSILON))
|
|
{
|
|
if (past)
|
|
{
|
|
delete p;
|
|
return NULL;
|
|
}
|
|
continue;
|
|
}
|
|
plane.Invert(&clip->m_Plane);
|
|
p = p->ClipByPlane(&plane, false);
|
|
}
|
|
if (!p)
|
|
return NULL;
|
|
|
|
if (p->m_Pts.size() < 3)
|
|
{
|
|
delete p;
|
|
p = NULL;
|
|
}
|
|
|
|
//@ASK Andrey.
|
|
//p->m_Pts.Shrink();
|
|
return p;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool SBrush::BuildSolid( bool bRemoveEmptyFaces,bool bBuildRE )
|
|
{
|
|
BBox box;
|
|
box.Reset();
|
|
|
|
int i,j;
|
|
|
|
// Clear render element valid flag.
|
|
m_flags &= ~BRF_RE_VALID;
|
|
|
|
MakeFacePlanes();
|
|
|
|
for (i = 0; i < m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *f = m_Faces[i];
|
|
|
|
if (f->m_Poly)
|
|
delete f->m_Poly;
|
|
|
|
f->m_Poly = CreateFacePoly(f);
|
|
|
|
//@ASK Andrey
|
|
/*
|
|
f->m_Shader = gcMapEf.mfForName( f->m_TexInfo.name );
|
|
*/
|
|
|
|
if (!f->m_Poly)
|
|
continue;
|
|
|
|
// Build geometry tiles if needed
|
|
f->BuildPrefabs();
|
|
|
|
// Add this polygon to bounding box.
|
|
int numPts = f->m_Poly->m_Pts.size();
|
|
for (j=0; j < numPts; j++)
|
|
{
|
|
box.Add( f->m_Poly->m_Pts[j].xyz );
|
|
}
|
|
|
|
for (j=0; j < numPts; j++)
|
|
{
|
|
//@ASK Andrey.
|
|
//f->CalcTexCoords(f->m_Poly->m_Pts[j], gNE[f->m_Shader->m_Id].m_Tex);
|
|
}
|
|
}
|
|
if (bRemoveEmptyFaces)
|
|
RemoveEmptyFaces();
|
|
|
|
|
|
// Rebuild render elements.
|
|
if (bBuildRE)
|
|
BuildRenderElements();
|
|
|
|
//@ASK Andrey
|
|
/*
|
|
ClipPrefabModels(gcpCryIndEd->m_wndTextureBar.m_bClipPrefab);
|
|
*/
|
|
m_bounds.min = box.min;
|
|
m_bounds.max = box.max;
|
|
|
|
// Check if valid.
|
|
if (m_bounds.min.x > m_bounds.max.x ||
|
|
m_bounds.min.y > m_bounds.max.y ||
|
|
m_bounds.min.z > m_bounds.max.z)
|
|
{
|
|
return false;
|
|
}
|
|
if (m_Faces.empty())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool SBrush::BuildRenderElements()
|
|
{
|
|
//@ HACK
|
|
m_flags |= BRF_RE_VALID;
|
|
return true;
|
|
|
|
if (m_indoorGeom && m_prefabGeom != NULL)
|
|
{
|
|
CLeafBuffer *srcBuf = m_prefabGeom->GetGeometry()->GetLeafBuffer();
|
|
CLeafBuffer *trgBuf = m_indoorGeom->GetLeafBuffer();
|
|
|
|
Vec3 omin = m_prefabGeom->GetGeometry()->GetBoxMin();
|
|
Vec3 omax = m_prefabGeom->GetGeometry()->GetBoxMax();
|
|
|
|
Vec3 bb = (m_bounds.max - m_bounds.min);
|
|
Vec3 ob = (omax - omin);
|
|
Vec3 scl;
|
|
scl.x = bb.x / ob.x;
|
|
scl.y = bb.y / ob.y;
|
|
scl.z = bb.z / ob.z;
|
|
|
|
Vec3 objofs = -(omax + omin)/2;
|
|
objofs = Vec3( objofs.x*scl.x,objofs.y*scl.y,objofs.z*scl.z );
|
|
|
|
Matrix44 stm;
|
|
stm.SetIdentity();
|
|
|
|
//SCALE_CHANGED_BY_IVO
|
|
//stm.ScaleMatrix(scl.x,scl.y,scl.z);
|
|
stm=Matrix33::CreateScale( Vec3d(scl.x,scl.y,scl.z) )*stm;
|
|
|
|
stm.SetTranslationOLD( objofs );
|
|
Matrix44 tm = stm * m_matrix;
|
|
// tm.SetTranslation( m_matrix.GetTranslation() );
|
|
|
|
int numv = srcBuf->m_SecVertCount;
|
|
int stride1,stride2;
|
|
unsigned char *src = srcBuf->GetPosPtr( stride1 );
|
|
unsigned char *trg = trgBuf->GetPosPtr( stride2 );
|
|
for (int i = 0; i < numv; i++)
|
|
{
|
|
Vec3 &sv = *(Vec3*)src;
|
|
Vec3 &tv = *(Vec3*)trg;
|
|
//Vec3 sv1 = stm.TransformPoint(sv);
|
|
tv = tm.TransformPointOLD( sv );
|
|
src += stride1;
|
|
trg += stride2;
|
|
}
|
|
|
|
trgBuf->InvalidateVideoBuffer();
|
|
m_flags |= BRF_RE_VALID;
|
|
|
|
return true;
|
|
}
|
|
// Clear render element valid flag.
|
|
m_flags &= ~BRF_RE_VALID;
|
|
|
|
// Make leaf buffer.
|
|
//CLeafBuffer *buf = GetIEditor()->GetRenderer()->CreateLeafBufferInitialized(
|
|
//m_indoorGeom->MakeLeafBuffer( m_prefabGeom->GetTriData(),false );
|
|
|
|
if (m_Faces.empty())
|
|
return false;
|
|
|
|
typedef struct_VERTEX_FORMAT_P3F_TEX2F VertexFormat;
|
|
|
|
VertexFormat vtx;
|
|
list2<VertexFormat> verts;
|
|
list2<ushort> indices;
|
|
|
|
int j;
|
|
int baseIndex = 0;
|
|
indices.reserve( 12*3 );
|
|
verts.reserve( 12 );
|
|
|
|
for (int i = 0; i < m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *f = m_Faces[i];
|
|
if (!f->m_Poly)
|
|
continue;
|
|
|
|
//m_bTesselated = false;
|
|
int numPts = f->m_Poly->m_Pts.size();
|
|
for (j = 0; j < numPts; j++)
|
|
{
|
|
SBrushVert *v = &f->m_Poly->m_Pts[numPts-j-1];
|
|
Vec3 p = m_matrix.TransformPointOLD( v->xyz );
|
|
vtx.xyz = p;
|
|
vtx.st[0] = v->st[0];
|
|
vtx.st[1] = v->st[1];
|
|
verts.push_back( vtx );
|
|
}
|
|
for (j = 0; j < numPts-2; j++)
|
|
{
|
|
indices.push_back( baseIndex );
|
|
indices.push_back( baseIndex+j+1 );
|
|
indices.push_back( baseIndex+j+2 );
|
|
}
|
|
baseIndex += numPts;
|
|
}
|
|
|
|
IRenderer *renderer = GetIEditor()->GetRenderer();
|
|
|
|
CLeafBuffer *pLeafBuffer = renderer->CreateLeafBufferInitialized(
|
|
&verts[0],verts.size(),VERTEX_FORMAT_P3F_TEX2F,&indices[0], indices.Count(), R_PRIMV_TRIANGLES,"Brush",eBT_Dynamic );
|
|
assert( pLeafBuffer );
|
|
CLeafBuffer *prevBuf = m_indoorGeom->GetLeafBuffer();
|
|
if (prevBuf)
|
|
{
|
|
renderer->DeleteLeafBuffer(prevBuf);
|
|
}
|
|
|
|
SInputShaderResources rc;
|
|
|
|
CMatInfo mt;
|
|
mt.m_Id = 0;
|
|
mt.nFirstIndexId = 0;
|
|
mt.nNumIndices = indices.size();
|
|
mt.nFirstVertId = 0;
|
|
mt.nNumVerts = verts.size();
|
|
mt.shaderItem = renderer->EF_LoadShaderItem( "Default",eSH_Indoor,true,NULL,0,&rc );
|
|
mt.pRE = (CREOcLeaf*)renderer->EF_CreateRE(eDATA_OcLeaf);
|
|
|
|
pLeafBuffer->m_pMats->Add(mt);
|
|
|
|
mt.pRE->m_pBuffer = pLeafBuffer;
|
|
mt.pRE->m_pChunk = &(*pLeafBuffer->m_pMats)[0];
|
|
|
|
|
|
m_indoorGeom->SetLeafBuffer( pLeafBuffer );
|
|
|
|
m_flags |= BRF_RE_VALID;
|
|
|
|
/*
|
|
for (int i = 0; i < m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *f = m_Faces[i];
|
|
if (f->m_Poly)
|
|
{
|
|
// Build render element for this face.
|
|
f->BuildRE( GetMatrix() );
|
|
// Set render element valid flag.
|
|
m_flags |= BRF_RE_VALID;
|
|
}
|
|
}
|
|
*/
|
|
return m_flags & BRF_RE_VALID;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::RemoveEmptyFaces()
|
|
{
|
|
int i;
|
|
std::vector<SBrushFace*> fc;
|
|
|
|
// delete faces that doesnt contain polygon.
|
|
for (i=0; i < m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *f = m_Faces[i];
|
|
if (f->m_Poly)
|
|
fc.push_back(f);
|
|
else
|
|
delete f;
|
|
}
|
|
|
|
m_Faces.clear();
|
|
|
|
// If less then 3 faces left, remove all faces.
|
|
if (fc.size() < 3)
|
|
{
|
|
for (i = 0; i < fc.size(); i++)
|
|
delete fc[i];
|
|
return;
|
|
}
|
|
// Copy left brushes to brush face.
|
|
m_Faces = fc;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::FitTexture(int nX, int nY)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<m_Faces.size(); i++)
|
|
{
|
|
m_Faces[i]->FitTexture(nX, nY);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
bool SBrush::IsIntersect(SBrush *Vol)
|
|
{
|
|
|
|
/*
|
|
for (int k=0;k<m_Faces.size();k++)
|
|
{
|
|
SBrushFace *f = &m_Faces[k];
|
|
if (f->IsIntersecting(Vol))
|
|
return (true);
|
|
} //k
|
|
|
|
return (false);
|
|
*/
|
|
|
|
//return (true);
|
|
|
|
int i;
|
|
|
|
Vec3d Cent = (m_bounds.min + m_bounds.max) * 0.5f;
|
|
|
|
for (i=0; i<Vol->m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *f = Vol->m_Faces[i];
|
|
if ((f->m_Plane.normal | Cent) > f->m_Plane.dist)
|
|
break;
|
|
}
|
|
if (i == Vol->m_Faces.size())
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool SBrush::IsInside(const Vec3d &vPoint)
|
|
{
|
|
for (int i=0;i<m_Faces.size();i++)
|
|
{
|
|
SBrushFace *f = m_Faces[i];
|
|
if ((f->m_Plane.normal.Dot(vPoint)) > f->m_Plane.dist)
|
|
return(false);
|
|
} //i
|
|
|
|
return(true);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool SBrush::Intersect(SBrush *Vol, std::vector<SBrush*>& List)
|
|
{
|
|
SBrush *front, *back;
|
|
int n = 0;
|
|
int i;
|
|
|
|
for (i=0 ; i<3 ; i++)
|
|
{
|
|
if (m_bounds.min[i] >= Vol->m_bounds.max[i] - DIST_EPSILON || m_bounds.max[i] <= Vol->m_bounds.min[i] + DIST_EPSILON)
|
|
break;
|
|
}
|
|
if (i != 3)
|
|
return false;
|
|
|
|
|
|
SBrush *b = Vol;
|
|
SBrush *Die = this;
|
|
float vol;
|
|
|
|
for (int j=0; j<b->m_Faces.size(); j++)
|
|
{
|
|
SBrushFace *f = b->m_Faces[j];
|
|
SBrushFace *fc = new SBrushFace;
|
|
*fc = *f;
|
|
|
|
fc->m_PlanePts[0] += f->m_Plane.normal * 16;
|
|
fc->m_PlanePts[1] += f->m_Plane.normal * 16;
|
|
fc->m_PlanePts[2] += f->m_Plane.normal * 16;
|
|
fc->MakePlane();
|
|
for (i=0; i<Die->m_Faces.size(); i++)
|
|
{
|
|
for (int k=0; k<Die->m_Faces[i]->m_Poly->m_Pts.size(); k++)
|
|
{
|
|
if ((fc->m_Plane.normal | Die->m_Faces[i]->m_Poly->m_Pts[k].xyz) > fc->m_Plane.dist)
|
|
break;
|
|
}
|
|
if (k!=Die->m_Faces[i]->m_Poly->m_Pts.size())
|
|
break;
|
|
}
|
|
delete fc;
|
|
if (i!=Die->m_Faces.size())
|
|
break;
|
|
}
|
|
if (j == b->m_Faces.size())
|
|
{
|
|
List.push_back( Die );
|
|
vol = Die->GetVolume();
|
|
return true;
|
|
}
|
|
|
|
Vec3d Mins = m_bounds.min;
|
|
Vec3d Maxs = m_bounds.max;
|
|
|
|
for (j=0; j<b->m_Faces.size() && Die; j++)
|
|
{
|
|
SBrushFace *f = b->m_Faces[j];
|
|
|
|
Die->SplitByFace(f, front, back);
|
|
if (back)
|
|
back->m_flags |= BRF_TEMP;
|
|
if (front)
|
|
delete front;
|
|
|
|
if (Die->m_flags & BRF_TEMP)
|
|
delete Die;
|
|
Die = back;
|
|
}
|
|
if (Die)
|
|
{
|
|
SBrush *b = Die;
|
|
List.push_back(b);
|
|
vol = b->GetVolume();
|
|
//gCurMap->m_ChoppedBrushes++;
|
|
n++;
|
|
}
|
|
|
|
if (n)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int SBrush::GetMemorySize()
|
|
{
|
|
int Size = sizeof(*this);
|
|
for (int i=0; i<m_Faces.size(); i++)
|
|
{
|
|
Size += sizeof(SBrushFace);
|
|
Size += sizeof(SBrushPoly);
|
|
Size += sizeof(SBrushVert) * m_Faces[i]->m_Poly->m_Pts.size();
|
|
}
|
|
|
|
return Size;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::SnapToGrid()
|
|
{
|
|
SBrushFace *f;
|
|
int i;
|
|
|
|
for (int nf=0; nf<m_Faces.size(); nf++)
|
|
{
|
|
f = m_Faces[nf];
|
|
for (i=0; i<3; i++)
|
|
{
|
|
f->m_PlanePts[i] = gSettings.pGrid->Snap( f->m_PlanePts[i] );
|
|
}
|
|
}
|
|
BuildSolid();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::SplitByFace (SBrushFace *f, SBrush* &front, SBrush* &back)
|
|
{
|
|
SBrush *b;
|
|
SBrushFace *nf;
|
|
Vec3d temp;
|
|
SBrush *sb;
|
|
|
|
b = new SBrush();
|
|
|
|
sb = b;
|
|
*sb = *this;
|
|
nf = new SBrushFace;
|
|
*nf = *f;
|
|
|
|
nf->m_TexInfo = b->m_Faces[0]->m_TexInfo;
|
|
b->m_Faces.push_back(nf);
|
|
|
|
b->BuildSolid();
|
|
b->RemoveEmptyFaces();
|
|
if ( !b->m_Faces.size() )
|
|
{
|
|
delete b;
|
|
back = NULL;
|
|
}
|
|
else
|
|
{
|
|
//@ASK Andrey.
|
|
/*
|
|
b->LinkToObj(m_Owner);
|
|
*/
|
|
back = b;
|
|
}
|
|
|
|
b = new SBrush;
|
|
sb = b;
|
|
*sb = *this;
|
|
nf = new SBrushFace;
|
|
*nf = *f;
|
|
|
|
temp = nf->m_PlanePts[0];
|
|
nf->m_PlanePts[0] = nf->m_PlanePts[1];
|
|
nf->m_PlanePts[1] = temp;
|
|
|
|
nf->m_TexInfo = b->m_Faces[0]->m_TexInfo;
|
|
b->m_Faces.push_back(nf);
|
|
|
|
b->BuildSolid();
|
|
b->RemoveEmptyFaces ();
|
|
if ( !b->m_Faces.size() )
|
|
{
|
|
delete b;
|
|
front = NULL;
|
|
}
|
|
else
|
|
{
|
|
//@ASK Andrey.
|
|
/*
|
|
b->LinkToObj(m_Owner);
|
|
*/
|
|
front = b;
|
|
}
|
|
}
|
|
|
|
int SBrush::OnSide (SBrushPlane *plane)
|
|
{
|
|
int i, j;
|
|
SBrushPoly *p;
|
|
float d, max;
|
|
int side;
|
|
|
|
max = 0;
|
|
side = SIDE_FRONT;
|
|
for (i=0;i<m_Faces.size(); i++)
|
|
{
|
|
p = m_Faces[i]->m_Poly;
|
|
if (!p)
|
|
continue;
|
|
for (j=0; j<p->m_Pts.size(); j++)
|
|
{
|
|
d = (p->m_Pts[j].xyz | plane->normal) - plane->dist;
|
|
if (d > max)
|
|
{
|
|
max = d;
|
|
side = SIDE_FRONT;
|
|
}
|
|
if (-d > max)
|
|
{
|
|
max = -d;
|
|
side = SIDE_BACK;
|
|
}
|
|
}
|
|
}
|
|
return side;
|
|
}
|
|
|
|
SBrush* SBrush::Clone( bool bBuildSoilid )
|
|
{
|
|
SBrush *sb = new SBrush;
|
|
*sb = *this;
|
|
|
|
if (bBuildSoilid)
|
|
sb->BuildSolid();
|
|
|
|
return sb;
|
|
}
|
|
|
|
void SBrush::SplitByPlane (SBrushPlane *plane, SBrush* &front, SBrush* &back)
|
|
{
|
|
SBrushPoly *tp = plane->CreatePoly();
|
|
SBrushFace fc;
|
|
ZeroStruct(fc);
|
|
fc.m_PlanePts[0] = tp->m_Pts[0].xyz;
|
|
fc.m_PlanePts[1] = tp->m_Pts[1].xyz;
|
|
fc.m_PlanePts[2] = tp->m_Pts[2].xyz;
|
|
SplitByFace(&fc, front, back);
|
|
delete tp;
|
|
return;
|
|
|
|
SBrush *b[2];
|
|
int i, j;
|
|
SBrushPoly *p, *cp[2], *midpoly;
|
|
SBrushPlane plane2;
|
|
SBrushFace *f;
|
|
float d, f_front, f_back;
|
|
|
|
front = back = NULL;
|
|
|
|
f_front = f_back = 0;
|
|
for (i=0; i<m_Faces.size(); i++)
|
|
{
|
|
p = m_Faces[i]->m_Poly;
|
|
if (!p)
|
|
continue;
|
|
for (j=0; j<p->m_Pts.size(); j++)
|
|
{
|
|
d = (p->m_Pts[j].xyz | plane->normal) - plane->dist;
|
|
if (d > 0 && d > f_front)
|
|
f_front = d;
|
|
if (d < 0 && d < f_back)
|
|
f_back = d;
|
|
}
|
|
}
|
|
if (f_front < 0.1)
|
|
{
|
|
SBrush *nb = Clone(true);
|
|
back = nb;
|
|
return;
|
|
}
|
|
if (f_back > -0.1)
|
|
{
|
|
SBrush *nb = Clone(true);
|
|
front = nb;
|
|
return;
|
|
}
|
|
|
|
p = plane->CreatePoly();
|
|
for (i=0; i<m_Faces.size() && p; i++)
|
|
{
|
|
SBrushPlane *pp = &m_Faces[i]->m_Plane;
|
|
plane2.Invert(pp);
|
|
p = p->ClipByPlane(&plane2, true);
|
|
}
|
|
|
|
if (!p)
|
|
{
|
|
int side;
|
|
|
|
side = OnSide (plane);
|
|
if (side == SIDE_FRONT)
|
|
{
|
|
SBrush *nb = Clone(true);
|
|
front = nb;
|
|
}
|
|
if (side == SIDE_BACK)
|
|
{
|
|
SBrush *nb = Clone(true);
|
|
back = nb;
|
|
}
|
|
return;
|
|
}
|
|
|
|
midpoly = p;
|
|
|
|
for (i=0; i<2; i++)
|
|
{
|
|
b[i] = Clone(false);
|
|
for (j=0; j<b[i]->m_Faces.size(); j++)
|
|
{
|
|
delete b[i]->m_Faces[j];
|
|
}
|
|
b[i]->m_Faces.clear();
|
|
}
|
|
|
|
for (i=0; i<m_Faces.size(); i++)
|
|
{
|
|
f = m_Faces[i];
|
|
p = f->m_Poly;
|
|
if (!p)
|
|
continue;
|
|
p->ClipByPlane(plane, 0, &cp[0], &cp[1]);
|
|
if (cp[0] == p)
|
|
{
|
|
cp[0] = new SBrushPoly;
|
|
*(cp[0]) = *p;
|
|
}
|
|
if (cp[1] == p)
|
|
{
|
|
cp[1] = new SBrushPoly;
|
|
*(cp[1]) = *p;
|
|
}
|
|
for (j=0; j<2; j++)
|
|
{
|
|
if (!cp[j])
|
|
continue;
|
|
SBrushFace *ff = new SBrushFace;
|
|
*ff = *f;
|
|
ff->m_Poly = cp[j];
|
|
b[j]->m_Faces.push_back(ff);
|
|
}
|
|
}
|
|
|
|
for (i=0; i<2; i++)
|
|
{
|
|
if (b[i]->m_Faces.size() < 3)
|
|
{
|
|
delete b[i];
|
|
b[i] = NULL;
|
|
}
|
|
}
|
|
|
|
if ( !(b[0] && b[1]) )
|
|
{
|
|
if (!b[0] && !b[1])
|
|
CLogFile::WriteLine("Split removed brush\n");
|
|
else
|
|
CLogFile::WriteLine("Split not on both sides\n");
|
|
if (b[0])
|
|
{
|
|
delete b[0];
|
|
SBrush *nb = Clone(true);
|
|
front = nb;
|
|
}
|
|
if (b[1])
|
|
{
|
|
delete b[1];
|
|
SBrush *nb = Clone(true);
|
|
back = nb;
|
|
}
|
|
return;
|
|
}
|
|
|
|
for (i=0; i<2; i++)
|
|
{
|
|
SBrushFace *ff = new SBrushFace;
|
|
if (!i)
|
|
ff->m_Plane = *plane;
|
|
else
|
|
{
|
|
plane2.Invert(plane);
|
|
ff->m_Plane = plane2;
|
|
}
|
|
// @FIXME ??
|
|
//b[i]->CreateFacePoly( ff );
|
|
ff->m_TexInfo = b[i]->m_Faces[0]->m_TexInfo;
|
|
b[i]->m_Faces.push_back(ff);
|
|
if (i==0)
|
|
{
|
|
SBrushPoly *pl = new SBrushPoly;
|
|
*pl = *midpoly;
|
|
ff->m_Poly = pl;
|
|
}
|
|
else
|
|
ff->m_Poly = midpoly;
|
|
}
|
|
|
|
front = b[0];
|
|
back = b[1];
|
|
}
|
|
|
|
/*
|
|
TBrush *SBrush::Parse()
|
|
{
|
|
TBrush *b;
|
|
SBrushFace *f;
|
|
int i,j;
|
|
|
|
gCurMap->m_ParsedBrushes++;
|
|
b = new TBrush;
|
|
|
|
do
|
|
{
|
|
if (!GetToken (true))
|
|
break;
|
|
if (!strcmp (token, "}") )
|
|
break;
|
|
|
|
if (strcmpi(token, "patchDef2") == 0 || strcmpi(token, "patchDef3") == 0)
|
|
{
|
|
delete b;
|
|
|
|
b = SPatch::Parse(strcmpi(token, "patchDef2") == 0);
|
|
if (b == NULL)
|
|
{
|
|
CLogFile::WriteLine ("Warning: parsing patch/brush\n");
|
|
return NULL;
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
f = new SBrushFace;
|
|
memset(f, 0, sizeof(SBrushFace));
|
|
|
|
for (i=0; i<3; i++)
|
|
{
|
|
if (i != 0)
|
|
GetToken (true);
|
|
if (strcmp (token, "(") )
|
|
{
|
|
CLogFile::WriteLine("Warning: Parsing brush error\n");
|
|
delete b;
|
|
return NULL;
|
|
}
|
|
|
|
for (j=0 ; j<3 ; j++)
|
|
{
|
|
GetToken (false);
|
|
f->m_PlanePts[i][j] = atof(token);
|
|
}
|
|
|
|
GetToken (false);
|
|
if (strcmp (token, ")") )
|
|
{
|
|
CLogFile::WriteLine("Warning: Parsing brush error\n");
|
|
delete b;
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
// read the TextureInfo
|
|
GetToken (false);
|
|
f->m_TexInfo.SetName(token);
|
|
GetToken (false);
|
|
f->m_TexInfo.shift[0] = atof(token);
|
|
GetToken (false);
|
|
f->m_TexInfo.shift[1] = atof(token);
|
|
GetToken (false);
|
|
f->m_TexInfo.rotate = atof(token);
|
|
GetToken (false);
|
|
f->m_TexInfo.scale[0] = atof(token);
|
|
GetToken (false);
|
|
f->m_TexInfo.scale[1] = atof(token);
|
|
|
|
// the flags and value field aren't necessarily present
|
|
f->m_Shader = gcMapEf.mfForName( f->m_TexInfo.name );
|
|
if (f->m_Shader->m_SM)
|
|
{
|
|
f->m_TexInfo.contents = f->m_Shader->m_SM->m_Contents;
|
|
f->m_TexInfo.flags = f->m_Shader->m_SM->m_SurfFlags;
|
|
}
|
|
else
|
|
{
|
|
f->m_TexInfo.contents = 0;
|
|
f->m_TexInfo.flags = 0;
|
|
}
|
|
|
|
if (TokenAvailable ())
|
|
{
|
|
GetToken (false);
|
|
f->m_TexInfo.contents = atoi(token);
|
|
GetToken (false);
|
|
f->m_TexInfo.flags = atoi(token);
|
|
GetToken (false);
|
|
f->m_TexInfo.value = atoi(token);
|
|
}
|
|
if (!f->m_TexInfo.value)
|
|
f->m_TexInfo.value = gcMapEf.mfGetVal(f->m_Shader, NULL);
|
|
b->m_Faces.push_back(f);
|
|
|
|
}
|
|
} while (1);
|
|
|
|
return b;
|
|
}
|
|
|
|
bool SBrush::ParseFromInd()
|
|
{
|
|
gCurMap->m_ParsedBrushes++;
|
|
GetToken(true);
|
|
GetToken(true);
|
|
if (token[0] != '[')
|
|
{
|
|
CLogFile::WriteLine("Error: Couldn't parsing IND file\n");
|
|
return false;
|
|
}
|
|
while (true)
|
|
{
|
|
GetToken(true);
|
|
if (token[0] == ']')
|
|
break;
|
|
if (!stricmp(token, "Face"))
|
|
{
|
|
SBrushFace *f = new SBrushFace;
|
|
memset(f, 0, sizeof(SBrushFace));
|
|
m_Faces.push_back(f);
|
|
f->m_Poly = new SBrushPoly;
|
|
GetToken(true);
|
|
int nv = atoi(token);
|
|
for (int i=0; i<nv; i++)
|
|
{
|
|
SBrushVert v;
|
|
GetToken(true);
|
|
for (int j=0; j<3; j++)
|
|
{
|
|
GetToken(true);
|
|
v.xyz[j] = atof(token);
|
|
}
|
|
for (j=0; j<2; j++)
|
|
{
|
|
GetToken(true);
|
|
v.st[j] = atof(token);
|
|
}
|
|
GetToken(true);
|
|
|
|
f->m_Poly->m_Pts.push_back(v);
|
|
|
|
}
|
|
f->m_PlanePts[0] = f->m_Poly->m_Pts[0].xyz;
|
|
f->m_PlanePts[1] = f->m_Poly->m_Pts[1].xyz;
|
|
f->m_PlanePts[2] = f->m_Poly->m_Pts[2].xyz;
|
|
|
|
// Parse TexInfo
|
|
GetToken(true);
|
|
GetToken(true);
|
|
strcpy(f->m_TexInfo.name, token);
|
|
GetToken(true);
|
|
f->m_TexInfo.shift[0] = atof(token);
|
|
GetToken(true);
|
|
f->m_TexInfo.shift[1] = atof(token);
|
|
GetToken(true);
|
|
f->m_TexInfo.rotate = atof(token);
|
|
GetToken(true);
|
|
f->m_TexInfo.scale[0] = atof(token);
|
|
GetToken(true);
|
|
f->m_TexInfo.scale[1] = atof(token);
|
|
GetToken(true);
|
|
f->m_TexInfo.flags = atoi(token);
|
|
GetToken(true);
|
|
}
|
|
else
|
|
{
|
|
CLogFile::WriteLine("Error: Couldn't parsing IND file\n");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
*/
|
|
|
|
void SBrush::Create( const Vec3& mins, const Vec3& maxs, SMapTexInfo *ti)
|
|
{
|
|
int i, j;
|
|
Vec3d pts[4][2];
|
|
SBrushFace *f;
|
|
|
|
ClearFaces();
|
|
|
|
for (i=0 ; i<3 ; i++)
|
|
{
|
|
if (maxs[i] < mins[i])
|
|
CLogFile::WriteLine ("Error: SBrush::Create: backwards");
|
|
}
|
|
|
|
pts[0][0][0] = mins[0];
|
|
pts[0][0][1] = mins[1];
|
|
|
|
pts[1][0][0] = mins[0];
|
|
pts[1][0][1] = maxs[1];
|
|
|
|
pts[2][0][0] = maxs[0];
|
|
pts[2][0][1] = maxs[1];
|
|
|
|
pts[3][0][0] = maxs[0];
|
|
pts[3][0][1] = mins[1];
|
|
|
|
for (i=0; i<4; i++)
|
|
{
|
|
pts[i][0][2] = mins[2];
|
|
pts[i][1][0] = pts[i][0][0];
|
|
pts[i][1][1] = pts[i][0][1];
|
|
pts[i][1][2] = maxs[2];
|
|
}
|
|
|
|
for (i=0; i<4; i++)
|
|
{
|
|
f = new SBrushFace;
|
|
ZeroStruct(*f);
|
|
f->m_TexInfo = *ti;
|
|
j = (i+1)%4;
|
|
|
|
f->m_PlanePts[0] = pts[j][1];
|
|
f->m_PlanePts[1] = pts[i][1];
|
|
f->m_PlanePts[2] = pts[i][0];
|
|
m_Faces.push_back(f);
|
|
}
|
|
|
|
f = new SBrushFace;
|
|
ZeroStruct(*f);
|
|
f->m_TexInfo = *ti;
|
|
f->m_PlanePts[0] = pts[0][1];
|
|
f->m_PlanePts[1] = pts[1][1];
|
|
f->m_PlanePts[2] = pts[2][1];
|
|
m_Faces.push_back(f);
|
|
|
|
f = new SBrushFace;
|
|
ZeroStruct(*f);
|
|
f->m_TexInfo = *ti;
|
|
f->m_PlanePts[0] = pts[2][0];
|
|
f->m_PlanePts[1] = pts[1][0];
|
|
f->m_PlanePts[2] = pts[0][0];
|
|
m_Faces.push_back(f);
|
|
}
|
|
|
|
//===================================================================
|
|
|
|
void SBrush::MakeSelFace (SBrushFace *f)
|
|
{
|
|
//@ASK Andrey.
|
|
/*
|
|
SBrushPoly *p;
|
|
int i;
|
|
int pnum[128];
|
|
|
|
p = f->CreatePoly(this);
|
|
if (!p)
|
|
return;
|
|
for (i=0; i<p->m_Pts.size(); i++)
|
|
{
|
|
pnum[i] = gCurMap->FindPoint(&p->m_Pts[i]);
|
|
}
|
|
for (i=0; i<p->m_Pts.size(); i++)
|
|
{
|
|
gCurMap->FindEdge (pnum[i], pnum[(i+1)%p->m_Pts.size()], f);
|
|
}
|
|
delete p;
|
|
*/
|
|
}
|
|
|
|
SBrushFace* SBrush::Ray( Vec3d Origin, Vec3d dir, float *dist )
|
|
{
|
|
SBrushFace *f, *FirstFace=0;
|
|
Vec3d p1, p2;
|
|
float frac, d1, d2;
|
|
int i, j;
|
|
|
|
p1 = Origin;
|
|
for (i=0 ; i<3 ; i++)
|
|
{
|
|
p2[i] = p1[i] + dir[i]*32768;
|
|
}
|
|
|
|
for (j=0; j<m_Faces.size(); j++)
|
|
{
|
|
f = m_Faces[j];
|
|
|
|
d1 = (p1 | f->m_Plane.normal) - f->m_Plane.dist;
|
|
d2 = (p2 | f->m_Plane.normal) - f->m_Plane.dist;
|
|
if (d1 >= 0 && d2 >= 0)
|
|
{
|
|
*dist = 0;
|
|
return NULL;
|
|
}
|
|
if (d1 <=0 && d2 <= 0)
|
|
continue;
|
|
frac = d1 / (d1 - d2);
|
|
if (d1 > 0)
|
|
{
|
|
FirstFace = f;
|
|
p1 = p1 + frac * (p2 - p1);
|
|
}
|
|
else
|
|
p2 = p1 + frac * (p2 - p1);
|
|
}
|
|
|
|
p1 -= Origin;
|
|
d1 = p1 | dir;
|
|
|
|
*dist = d1;
|
|
|
|
return FirstFace;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::SelectSide( Vec3d Origin,Vec3d Dir,bool shear,SBrushSubSelection &subSelection )
|
|
{
|
|
SBrushFace *f;
|
|
Vec3d p1, p2;
|
|
|
|
Vec3d Target = Origin + Dir * 10000.0f;
|
|
|
|
for (int j=0; j < m_Faces.size(); j++)
|
|
{
|
|
f = m_Faces[j];
|
|
p1 = Origin;
|
|
p2 = Target;
|
|
|
|
// Clip ray by every face of brush, except tested one.
|
|
for (int i=0; i < m_Faces.size(); i++)
|
|
{
|
|
if (m_Faces[i] != f)
|
|
m_Faces[i]->ClipLine(p1, p2);
|
|
}
|
|
|
|
//if (i != m_Faces.size())
|
|
//continue;
|
|
|
|
if (IsEquivalent(p1,Origin,0))
|
|
continue;
|
|
|
|
if (f->ClipLine(p1, p2))
|
|
continue;
|
|
|
|
SelectFace( f,shear,subSelection );
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::Move(Vec3d& Delta)
|
|
{
|
|
int i;
|
|
SBrushFace *f;
|
|
|
|
for (int j=0; j<m_Faces.size(); j++)
|
|
{
|
|
f = m_Faces[j];
|
|
for (i=0; i<3; i++)
|
|
{
|
|
f->m_PlanePts[i] += Delta;
|
|
}
|
|
}
|
|
BuildSolid();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::Transform( Matrix44 &tm,bool bBuild )
|
|
{
|
|
int i;
|
|
SBrushFace *f;
|
|
|
|
for (int j=0; j<m_Faces.size(); j++)
|
|
{
|
|
f = m_Faces[j];
|
|
for (i=0; i<3; i++)
|
|
{
|
|
f->m_PlanePts[i] = tm.TransformPointOLD(f->m_PlanePts[i]);
|
|
}
|
|
}
|
|
if (bBuild)
|
|
BuildSolid();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::SetShader (SMapTexInfo *ti)
|
|
{
|
|
for (int i=0; i<m_Faces.size(); i++)
|
|
{
|
|
m_Faces[i]->m_TexInfo = *ti;
|
|
}
|
|
BuildSolid();
|
|
}
|
|
|
|
/*
|
|
void SBrush::WriteToInd(FILE *f, char *st, int num)
|
|
{
|
|
pfprintf (st, f, "Brush '%d'\n", num);
|
|
pfprintf (st, f, "[\n");
|
|
|
|
for (int i=0; i<m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *fa = m_Faces[i];
|
|
|
|
pfprintf (st, f, " Face %d", fa->m_Poly->m_Pts.size());
|
|
for (int j=0; j<fa->m_Poly->m_Pts.size(); j++)
|
|
{
|
|
SBrushVert *v = &fa->m_Poly->m_Pts[j];
|
|
fprintf (f, " (");
|
|
if (v->xyz[0] - (int)v->xyz[0])
|
|
fprintf(f, " %f", v->xyz[0]);
|
|
else
|
|
fprintf(f, " %d", (int)v->xyz[0]);
|
|
|
|
if (v->xyz[1] - (int)v->xyz[1])
|
|
fprintf(f, " %f", v->xyz[1]);
|
|
else
|
|
fprintf(f, " %d", (int)v->xyz[1]);
|
|
|
|
if (v->xyz[2] - (int)v->xyz[2])
|
|
fprintf(f, " %f", v->xyz[2]);
|
|
else
|
|
fprintf(f, " %d", (int)v->xyz[2]);
|
|
|
|
fprintf(f, " %f", v->st[0]);
|
|
fprintf(f, " %f", v->st[1]);
|
|
|
|
fprintf (f, " )");
|
|
}
|
|
SMapTexInfo *ti= &fa->m_TexInfo;
|
|
fprintf(f, " ( %s %f %f %f %f %f %d )\n", ti->name, ti->shift[0], ti->shift[1], ti->rotate, ti->scale[0], ti->scale[1], ti->flags);
|
|
}
|
|
pfprintf (st, f, "]\n");
|
|
}
|
|
|
|
void SBrush::Select (void)
|
|
{
|
|
TBrush *b;
|
|
CMapObject *o;
|
|
|
|
gCurMap->m_SelectedFace = NULL;
|
|
if (gCurMap->m_SelectCount < 2)
|
|
gCurMap->m_SelectOrder[gCurMap->m_SelectCount] = this;
|
|
gCurMap->m_SelectCount++;
|
|
|
|
o = m_Owner;
|
|
if (o)
|
|
{
|
|
if (o != gCurMap->m_WorldObject)
|
|
{
|
|
for (b=gCurMap->m_SelectedBrushes; b; b=b->Next)
|
|
{
|
|
if (b->m_Owner == o)
|
|
goto ss;
|
|
}
|
|
for (b=o->m_Brushes.m_NextInObj; b != &o->m_Brushes; b=b->m_NextInObj)
|
|
{
|
|
b->Unlink();
|
|
b->Link(gCurMap->m_SelectedBrushes);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ss:
|
|
b = (TBrush *)this;
|
|
b->Unlink();
|
|
b->Link(gCurMap->m_SelectedBrushes);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SBrush::Deselect (void)
|
|
{
|
|
TBrush *b;
|
|
|
|
b = (TBrush *)this;
|
|
b->Unlink();
|
|
b->Link(gCurMap->m_ActiveBrushes);
|
|
}
|
|
*/
|
|
|
|
void SBrush::SelectFace( SBrushFace *f,bool shear,SBrushSubSelection &subSelection )
|
|
{
|
|
int i;
|
|
SBrushFace *f2;
|
|
SBrushPoly *p;
|
|
float d;
|
|
int c;
|
|
|
|
c = 0;
|
|
for (i = 0; i<3; i++)
|
|
{
|
|
if (subSelection.AddPoint(&f->m_PlanePts[i]))
|
|
c++;
|
|
}
|
|
if (c == 0)
|
|
return;
|
|
|
|
/*
|
|
TBrush *b2;
|
|
for (b2=gCurMap->m_SelectedBrushes; b2; b2=b2->Next)
|
|
{
|
|
if (b2 == this)
|
|
continue;
|
|
for (int j=0; j<b2->m_Faces.size(); j++)
|
|
{
|
|
f2 = b2->m_Faces[j];
|
|
for (i=0; i<3; i++)
|
|
{
|
|
if (fabs(f2->m_PlanePts[i] | f->m_Plane.normal) - f->m_Plane.dist > DIST_EPSILON)
|
|
break;
|
|
}
|
|
if (i == 3)
|
|
{
|
|
b2->SelectFaceForDragging (f2, shear);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
if (!shear)
|
|
return;
|
|
|
|
for (int j=0; j<m_Faces.size(); j++)
|
|
{
|
|
f2 = m_Faces[j];
|
|
if (f2 == f)
|
|
continue;
|
|
|
|
p = CreateFacePoly(f2);
|
|
if (!p)
|
|
continue;
|
|
|
|
for (i=0; i<p->m_Pts.size(); i++)
|
|
{
|
|
d = (p->m_Pts[i].xyz | f->m_Plane.normal) - f->m_Plane.dist;
|
|
if (d > -DIST_EPSILON && d < DIST_EPSILON)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i != p->m_Pts.size())
|
|
{
|
|
if (i == 0)
|
|
{
|
|
d = p->m_Pts[p->m_Pts.size()-1].xyz.Dot(f->m_Plane.normal) - f->m_Plane.dist;
|
|
if (d > -DIST_EPSILON && d < DIST_EPSILON)
|
|
i = p->m_Pts.size() - 1;
|
|
}
|
|
|
|
subSelection.AddPoint( &f2->m_PlanePts[0] );
|
|
f2->m_PlanePts[0] = p->m_Pts[i].xyz;
|
|
|
|
if (++i == p->m_Pts.size())
|
|
i = 0;
|
|
|
|
d = p->m_Pts[i].xyz.Dot(f->m_Plane.normal) - f->m_Plane.dist;
|
|
if (d > -DIST_EPSILON && d < DIST_EPSILON)
|
|
{
|
|
subSelection.AddPoint( &f2->m_PlanePts[1] );
|
|
}
|
|
f2->m_PlanePts[1] = p->m_Pts[i].xyz;
|
|
if (++i == p->m_Pts.size())
|
|
i = 0;
|
|
|
|
f2->m_PlanePts[2] = p->m_Pts[i].xyz;
|
|
}
|
|
|
|
delete p;
|
|
}
|
|
}
|
|
|
|
//void gDrawLightFrustum(CMapObject *o, Vec3d org);
|
|
|
|
bool SBrush::DrawModel(bool b)
|
|
{
|
|
//@ASK Andrey.
|
|
/*
|
|
CComModel *m = (CComModel *)m_Owner->m_Class->m_Model;
|
|
if (!m)
|
|
return false;
|
|
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
|
glEnable (GL_TEXTURE_2D);
|
|
// glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
|
|
Vec3d org = m_Owner->m_Brushes.m_NextInObj->m_bounds.min - m_Owner->m_Class->m_bounds.min;
|
|
|
|
glTranslatef(org[0], org[1], org[2]);
|
|
|
|
float a = m_Owner->FloatForKey("angle");
|
|
Vec3d angs;
|
|
angs[YAW] = a;
|
|
if (!a)
|
|
m_Owner->VectorForKey("angles", angs);
|
|
glRotatef(angs[YAW], 0, 0, 1);
|
|
glRotatef(angs[PITCH], 0, 1, 0);
|
|
glRotatef(angs[ROLL], 1, 0, 0);
|
|
|
|
glColor4f(1,1,1,1);
|
|
bool bRes = m->mfDraw(NULL, true);
|
|
|
|
glPopMatrix();
|
|
if (!strnicmp(m_Owner->m_Class->m_Name, "light", 5))
|
|
{
|
|
Vec3d dir;
|
|
m_Owner->VectorForKey("direction", dir);
|
|
if (dir != Vec3d(0,0,0))
|
|
gDrawLightFrustum(m_Owner, org);
|
|
}
|
|
glPopAttrib();
|
|
|
|
return bRes;
|
|
*/
|
|
return false;
|
|
}
|
|
|
|
void SBrush::Draw()
|
|
{
|
|
//@ASK Andrey.
|
|
/*
|
|
int i, j;
|
|
SShader *prev = 0;
|
|
SBrushPoly *p;
|
|
|
|
if (m_flags & BRF_HIDE)
|
|
return;
|
|
|
|
if (m_Patch)
|
|
{
|
|
m_Patch->Draw(1);
|
|
return;
|
|
}
|
|
|
|
EDrawMode dm = gcpMapPersp->m_eDrawMode;
|
|
|
|
if (m_Owner->m_Class->m_flags & OCF_NORESIZE)
|
|
{
|
|
bool bp = (m_flags & BRF_FAILMODEL) ? false : DrawModel(true);
|
|
|
|
if (bp)
|
|
return;
|
|
}
|
|
|
|
prev = NULL;
|
|
for (i=0; i<m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *f = m_Faces[i];
|
|
p = f->m_Poly;
|
|
if (!p)
|
|
continue;
|
|
|
|
if (f->m_Prefabs)
|
|
{
|
|
for (TPrefabItem *pi=f->m_Prefabs; pi; pi=pi->Next)
|
|
{
|
|
glPushMatrix();
|
|
glMultMatrixf(&pi->m_Matrix.m_values[0][0]);
|
|
if (pi->m_Model)
|
|
pi->m_Model->mfDraw(f->m_Shader, NULL);
|
|
else
|
|
pi->m_Geom->mfDraw(f->m_Shader, NULL);
|
|
glPopMatrix();
|
|
}
|
|
continue;
|
|
}
|
|
if ((dm == eDM_Textured || dm == eDM_Light) && f->m_Shader != prev)
|
|
{
|
|
prev = f->m_Shader;
|
|
glBindTexture(GL_TEXTURE_2D, gNE[f->m_Shader->m_Id].m_Tex->m_Bind);
|
|
}
|
|
|
|
if (!m_Patch)
|
|
glColor4fv(&f->m_Color[0]);
|
|
else
|
|
glColor4f (f->m_Color[0], f->m_Color[1], f->m_Color[2], 0.13 );
|
|
|
|
float a;
|
|
if ((a=gcMapEf.mfGetAlpha(f->m_Shader)) != 1.0f)
|
|
glColor4f (f->m_Color[0], f->m_Color[1], f->m_Color[2], a);
|
|
|
|
glBegin(GL_POLYGON);
|
|
|
|
for (j=0; j<p->m_Pts.size(); j++)
|
|
{
|
|
if (dm == eDM_Textured || dm == eDM_Light)
|
|
glTexCoord2fv( &p->m_Pts[j].st[0] );
|
|
glVertex3fv(&p->m_Pts[j].xyz[0]);
|
|
}
|
|
glEnd();
|
|
}
|
|
|
|
if ((m_Owner->m_Class->m_flags & OCF_NORESIZE) && (dm == eDM_Textured || dm == eDM_Light))
|
|
glEnable (GL_TEXTURE_2D);
|
|
|
|
glBindTexture( GL_TEXTURE_2D, 0 );
|
|
*/
|
|
}
|
|
|
|
bool SBrush::AddToListModel(bool b)
|
|
{
|
|
bool bRes = false;
|
|
//@ASK Andrey.
|
|
/*
|
|
if (!strnicmp(m_Owner->m_Class->m_Name, "light", 5))
|
|
return true;
|
|
|
|
Vec3d org = m_Owner->m_Brushes.m_NextInObj->m_bounds.min - m_Owner->m_Class->m_bounds.min;
|
|
|
|
CComModel *m = (CComModel *)m_Owner->m_Class->m_Model;
|
|
if (!m)
|
|
return false;
|
|
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
|
glEnable (GL_TEXTURE_2D);
|
|
// glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
|
|
glTranslatef(org[0], org[1], org[2]);
|
|
|
|
float a = m_Owner->FloatForKey("angle");
|
|
Vec3d angs;
|
|
angs[YAW] = a;
|
|
if (!a)
|
|
m_Owner->VectorForKey("angles", angs);
|
|
glRotatef(angs[YAW], 0, 0, 1);
|
|
glRotatef(angs[PITCH], 0, 1, 0);
|
|
glRotatef(angs[ROLL], 1, 0, 0);
|
|
|
|
glColor4f(1,1,1,1);
|
|
bRes = m->mfDraw(NULL, true);
|
|
|
|
glPopMatrix();
|
|
glPopAttrib();
|
|
*/
|
|
|
|
return bRes;
|
|
}
|
|
|
|
void SBrush::AddToList(CCObject *obj)
|
|
{
|
|
//@ASK Andrey.
|
|
/*
|
|
int i;
|
|
SShader *prev = 0;
|
|
SBrushPoly *p;
|
|
|
|
if (m_flags & BRF_HIDE)
|
|
return;
|
|
|
|
if (m_Patch)
|
|
{
|
|
m_Patch->Draw(1);
|
|
return;
|
|
}
|
|
|
|
EDrawMode dm = gcpMapPersp->m_eDrawMode;
|
|
|
|
if (m_Owner->m_Class->m_flags & OCF_NORESIZE)
|
|
{
|
|
bool bp = (m_flags & BRF_FAILMODEL) ? false : AddToListModel(true);
|
|
|
|
if (bp)
|
|
return;
|
|
}
|
|
|
|
prev = NULL;
|
|
for (i=0; i<m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *f = m_Faces[i];
|
|
p = f->m_Poly;
|
|
if (!p)
|
|
continue;
|
|
|
|
ECull cl = f->m_Shader->m_eCull;
|
|
if (cl != eCULL_None)
|
|
{
|
|
float d = f->m_Plane.normal * g_Globals.m_Origin;
|
|
if (cl == eCULL_Back)
|
|
{
|
|
if (d < f->m_Plane.dist-8.0f)
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (d > f->m_Plane.dist+8.0f)
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (f->m_Prefabs)
|
|
{
|
|
for (TPrefabItem *pi=f->m_Prefabs; pi; pi=pi->Next)
|
|
{
|
|
glPushMatrix();
|
|
glMultMatrixf(&pi->m_Matrix.m_values[0][0]);
|
|
if (pi->m_Model)
|
|
pi->m_Model->mfDraw(f->m_Shader, NULL);
|
|
else
|
|
pi->m_Geom->mfDraw(f->m_Shader, NULL);
|
|
glPopMatrix();
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (g_Globals.m_TemplateId < EFT_USER_FIRST)
|
|
f->m_Shader->AddTemplate(g_Globals.m_TemplateId);
|
|
else
|
|
f->m_Shader->AddTemplate(g_Globals.m_TemplateId, g_Globals.m_CustomTemplate.GetBuffer(0));
|
|
SShader *e = f->m_Shader->mfGetTemplate(g_Globals.m_TemplateId);
|
|
if ((gNE[e->m_Id].m_TessSize && !f->m_bTesselated) || (!gNE[e->m_Id].m_TessSize && f->m_bTesselated))
|
|
f->BuildRE();
|
|
|
|
if (obj)
|
|
gRenDev->EF_AddEf(0, f->m_RE, f->m_Shader, obj, g_Globals.m_TemplateId, NULL);
|
|
else
|
|
gRenDev->EF_AddEf(0, f->m_RE, f->m_Shader, g_Globals.m_TemplateId, NULL);
|
|
}
|
|
*/
|
|
}
|
|
|
|
//============================================================
|
|
|
|
/*
|
|
void SBrush::Write(CMemFile* pMemFile)
|
|
{
|
|
SBrushFace *fa;
|
|
const char *pname;
|
|
int i, j;
|
|
|
|
if (m_Patch)
|
|
{
|
|
m_Patch->Write(pMemFile);
|
|
return;
|
|
}
|
|
{
|
|
gCurMap->FPrintfToMem (pMemFile, "{\n");
|
|
for (j=0; j<m_Faces.size(); j++)
|
|
{
|
|
fa = m_Faces[j];
|
|
for (i=0; i<3; i++)
|
|
{
|
|
gCurMap->FPrintfToMem(pMemFile, "( ");
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
if (fa->m_PlanePts[i][j] == static_cast<int>(fa->m_PlanePts[i][j]))
|
|
gCurMap->FPrintfToMem(pMemFile, "%i ", static_cast<int>(fa->m_PlanePts[i][j]));
|
|
else
|
|
gCurMap->FPrintfToMem(pMemFile, "%f ", fa->m_PlanePts[i][j]);
|
|
}
|
|
gCurMap->FPrintfToMem(pMemFile, ") ");
|
|
}
|
|
|
|
{
|
|
pname = fa->m_TexInfo.name;
|
|
if (pname[0] == 0)
|
|
pname = "unnamed";
|
|
|
|
gCurMap->FPrintfToMem (pMemFile, "%s %i %i %i ", pname, (int)fa->m_TexInfo.shift[0], (int)fa->m_TexInfo.shift[1], (int)fa->m_TexInfo.rotate);
|
|
|
|
if (fa->m_TexInfo.scale[0] == (int)fa->m_TexInfo.scale[0])
|
|
gCurMap->FPrintfToMem (pMemFile, "%i ", (int)fa->m_TexInfo.scale[0]);
|
|
else
|
|
gCurMap->FPrintfToMem (pMemFile, "%f ", (float)fa->m_TexInfo.scale[0]);
|
|
if (fa->m_TexInfo.scale[1] == (int)fa->m_TexInfo.scale[1])
|
|
gCurMap->FPrintfToMem (pMemFile, "%i", (int)fa->m_TexInfo.scale[1]);
|
|
else
|
|
gCurMap->FPrintfToMem (pMemFile, "%f", (float)fa->m_TexInfo.scale[1]);
|
|
|
|
gCurMap->FPrintfToMem (pMemFile, " %i %i %i", fa->m_TexInfo.contents, fa->m_TexInfo.flags, fa->m_TexInfo.value);
|
|
}
|
|
gCurMap->FPrintfToMem (pMemFile, "\n");
|
|
}
|
|
gCurMap->FPrintfToMem (pMemFile, "}\n");
|
|
}
|
|
}
|
|
*/
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::Serialize( XmlNodeRef &xmlNode,bool bLoading )
|
|
{
|
|
if (bLoading)
|
|
{
|
|
// Loading.
|
|
// Load all faces.
|
|
int numFaces = xmlNode->getChildCount();
|
|
m_Faces.resize( numFaces );
|
|
for (int i = 0; i < numFaces; i++)
|
|
{
|
|
SBrushFace *fc = new SBrushFace;
|
|
m_Faces[i] = fc;
|
|
|
|
XmlNodeRef faceNode = xmlNode->getChild(i);
|
|
faceNode->getAttr( "p1",fc->m_PlanePts[0] );
|
|
faceNode->getAttr( "p2",fc->m_PlanePts[1] );
|
|
faceNode->getAttr( "p3",fc->m_PlanePts[2] );
|
|
|
|
Vec3 texScale( 1,1,1 );
|
|
Vec3 texShift( 0,0,0 );
|
|
faceNode->getAttr( "TexScale",texScale );
|
|
faceNode->getAttr( "TexShift",texShift );
|
|
fc->m_TexInfo.scale[0] = texScale.x;
|
|
fc->m_TexInfo.scale[1] = texScale.y;
|
|
fc->m_TexInfo.shift[0] = texShift.x;
|
|
fc->m_TexInfo.shift[1] = texShift.y;
|
|
}
|
|
BuildSolid(false);
|
|
}
|
|
else
|
|
{
|
|
// Saving.
|
|
//char str[1024];
|
|
// Save all faces.
|
|
for (int i = 0; i < m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *fc = m_Faces[i];
|
|
XmlNodeRef faceNode = xmlNode->newChild( "Face" );
|
|
faceNode->setAttr( "p1",fc->m_PlanePts[0] );
|
|
faceNode->setAttr( "p2",fc->m_PlanePts[1] );
|
|
faceNode->setAttr( "p3",fc->m_PlanePts[2] );
|
|
|
|
Vec3 texScale( fc->m_TexInfo.scale[0],fc->m_TexInfo.scale[1],0 );
|
|
Vec3 texShift( fc->m_TexInfo.shift[0],fc->m_TexInfo.shift[1],0 );
|
|
faceNode->setAttr( "TexScale",texScale );
|
|
faceNode->setAttr( "TexShift",texShift );
|
|
|
|
//sprintf(
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::SetMatrix( const Matrix44 &tm )
|
|
{
|
|
m_matrix = tm;
|
|
// clear RE valid flag.
|
|
m_flags &= ~BRF_RE_VALID;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::Render( IRenderer *renderer,const Vec3 &objectSpaceCamSrc )
|
|
{
|
|
assert( renderer );
|
|
|
|
if (m_prefabGeom)
|
|
{
|
|
Vec3 omin = m_prefabGeom->GetGeometry()->GetBoxMin();
|
|
Vec3 omax = m_prefabGeom->GetGeometry()->GetBoxMax();
|
|
|
|
Matrix44 mov1;
|
|
Matrix44 mov2;
|
|
mov1.SetIdentity();
|
|
mov2.SetIdentity();
|
|
mov1.SetTranslationOLD( -omin );
|
|
mov2.SetTranslationOLD( m_bounds.min );
|
|
|
|
Vec3 bb = (m_bounds.max - m_bounds.min);
|
|
Vec3 ob = (omax - omin);
|
|
Vec3 scl;
|
|
scl.x = bb.x / ob.x;
|
|
scl.y = bb.y / ob.y;
|
|
scl.z = bb.z / ob.z;
|
|
|
|
Matrix44 stm;
|
|
stm.SetIdentity();
|
|
|
|
stm=Matrix33::CreateScale( Vec3d(scl.x,scl.y,scl.z) )*stm;
|
|
|
|
Matrix44 tm = mov1 * stm * mov2;
|
|
tm = tm * m_matrix;
|
|
|
|
SRendParams rp;
|
|
rp.pMatrix = &tm;
|
|
rp.nShaderTemplate = -1;
|
|
rp.nDLightMask = 0xFFFFFFFF;
|
|
rp.dwFObjFlags |= FOB_TRANS_MASK;
|
|
//m_indoorGeom->Render( rp );
|
|
m_prefabGeom->Render( rp );
|
|
|
|
return;
|
|
}
|
|
|
|
if (!(m_flags&BRF_RE_VALID))
|
|
{
|
|
if (!BuildRenderElements())
|
|
return;
|
|
}
|
|
|
|
int i;
|
|
|
|
//CCObject *pObj = renderer->EF_GetObject(true);
|
|
//pObj->m_Matrix = m_matrix;
|
|
//pObj->m_ObjFlags |= FOB_USEMATRIX;
|
|
|
|
ECull cl = eCULL_Back;
|
|
|
|
for (i = 0; i < m_Faces.size(); i++)
|
|
{
|
|
SBrushFace *f = m_Faces[i];
|
|
SBrushPoly *p = f->m_Poly;
|
|
if (!p)
|
|
continue;
|
|
|
|
//ECull cl = f->m_Shader->m_eCull;
|
|
//if (cl != eCULL_None)
|
|
{
|
|
float d = f->m_Plane.normal * objectSpaceCamSrc;
|
|
if (cl == eCULL_Back)
|
|
{
|
|
if (d < f->m_Plane.dist-0.001f)
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (d > f->m_Plane.dist+0.001f)
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/*
|
|
if (f->m_Prefabs)
|
|
{
|
|
for (TPrefabItem *pi=f->m_Prefabs; pi; pi=pi->Next)
|
|
{
|
|
glPushMatrix();
|
|
glMultMatrixf(&pi->m_Matrix.m_values[0][0]);
|
|
if (pi->m_Model)
|
|
pi->m_Model->mfDraw(f->m_Shader, NULL);
|
|
else
|
|
pi->m_Geom->mfDraw(f->m_Shader, NULL);
|
|
glPopMatrix();
|
|
}
|
|
continue;
|
|
}
|
|
*/
|
|
|
|
/*
|
|
if (g_Globals.m_TemplateId < EFT_USER_FIRST)
|
|
f->m_Shader->AddTemplate(g_Globals.m_TemplateId);
|
|
else
|
|
f->m_Shader->AddTemplate(g_Globals.m_TemplateId, g_Globals.m_CustomTemplate.GetBuffer(0));
|
|
SShader *e = f->m_Shader->mfGetTemplate(g_Globals.m_TemplateId);
|
|
if ((gNE[e->m_Id].m_TessSize && !f->m_bTesselated) || (!gNE[e->m_Id].m_TessSize && f->m_bTesselated))
|
|
f->BuildRE();
|
|
*/
|
|
|
|
if (f->m_RE)
|
|
{
|
|
static IShader *pShader = 0;
|
|
if (!pShader)
|
|
pShader = renderer->EF_LoadShader( "Textures\\Detail.jpg",eSH_World );
|
|
|
|
/*
|
|
static CCObject *pObj = 0;
|
|
if (!pObj)
|
|
{
|
|
pObj = renderer->EF_GetObject(true);
|
|
pObj->m_Matrix.Identity();
|
|
pObj->m_ObjFlags |= FOB_USEMATRIX;
|
|
}
|
|
*/
|
|
|
|
renderer->EF_AddEf( 0,f->m_RE,pShader, NULL, NULL, -1 );
|
|
}
|
|
//else
|
|
//gRenDev->EF_AddEf(0, f->m_RE, f->m_Shader, g_Globals.m_TemplateId, NULL);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::SetPrefabGeom( CEdMesh *obj )
|
|
{
|
|
m_prefabGeom = obj;
|
|
|
|
if (m_indoorGeom)
|
|
{
|
|
//m_indoorGeom->Release();
|
|
//m_indoorGeom = 0;
|
|
}
|
|
|
|
if (!m_prefabGeom)
|
|
return;
|
|
|
|
bool bNewCreated = false;
|
|
if (m_Faces.empty())
|
|
{
|
|
BBox box;
|
|
m_prefabGeom->GetBounds(box);
|
|
|
|
if (box.max.x - box.min.x == 0)
|
|
box.max.x = box.min.x + MIN_BOUNDS_SIZE;
|
|
if (box.max.y - box.min.y == 0)
|
|
box.max.y = box.min.y + MIN_BOUNDS_SIZE;
|
|
if (box.max.z - box.min.z == 0)
|
|
box.max.z = box.min.z + MIN_BOUNDS_SIZE;
|
|
|
|
// Create brush with specified bounds.
|
|
SMapTexInfo ti;
|
|
Create( box.min,box.max,&ti );
|
|
bNewCreated = true;
|
|
}
|
|
|
|
/*
|
|
// Clone prefab geometry to make indoor geometry.
|
|
m_indoorGeom->MakeLeafBuffer( m_prefabGeom->GetTriData(),false );
|
|
|
|
m_indoorGeom->SetBBoxMin( box.min );
|
|
m_indoorGeom->SetBBoxMax( box.max );
|
|
*/
|
|
|
|
if (!bNewCreated)
|
|
{
|
|
SMapTexInfo ti;
|
|
Create( m_bounds.min,m_bounds.max,&ti );
|
|
}
|
|
|
|
BuildSolid(false);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SBrush::ResetToPrefabSize()
|
|
{
|
|
if (!m_prefabGeom)
|
|
return;
|
|
|
|
BBox box;
|
|
m_prefabGeom->GetBounds( box );
|
|
if (box.max.x - box.min.x == 0)
|
|
box.max.x = box.min.x + MIN_BOUNDS_SIZE;
|
|
if (box.max.y - box.min.y == 0)
|
|
box.max.y = box.min.y + MIN_BOUNDS_SIZE;
|
|
if (box.max.z - box.min.z == 0)
|
|
box.max.z = box.min.z + MIN_BOUNDS_SIZE;
|
|
|
|
// Create brush with specified bounds.
|
|
SMapTexInfo ti;
|
|
Create( box.min,box.max,&ti );
|
|
BuildSolid(false);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
IStatObj* SBrush::GetIndoorGeom()
|
|
{
|
|
if (!(m_flags&BRF_RE_VALID))
|
|
{
|
|
if (!BuildRenderElements())
|
|
return 0;
|
|
}
|
|
return m_indoorGeom;
|
|
};
|
|
|
|
/*
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CIndexedMesh* SBrush::CreateGeometry()
|
|
{
|
|
CIndexedMesh *mesh = 0;
|
|
if (m_prefabGeom)
|
|
{
|
|
CIndexedMesh *src = m_prefabGeom->GetTriData();
|
|
|
|
Vec3 omin = m_prefabGeom->GetBoxMin();
|
|
Vec3 omax = m_prefabGeom->GetBoxMax();
|
|
Vec3 bb = (m_bounds.max - m_bounds.min);
|
|
Vec3 ob = (omax - omin);
|
|
Vec3 scl;
|
|
scl.x = bb.x / ob.x;
|
|
scl.y = bb.y / ob.y;
|
|
scl.z = bb.z / ob.z;
|
|
|
|
Vec3 objofs = -(omax + omin)/2;
|
|
objofs = Vec3( objofs.x*scl.x,objofs.y*scl.y,objofs.z*scl.z );
|
|
Matrix stm;
|
|
stm.Identity();
|
|
stm.ScaleMatrix(scl.x,scl.y,scl.z);
|
|
stm.SetTranslation( objofs );
|
|
Matrix tm = stm * m_matrix;
|
|
|
|
// Allocated data in indexed mesh.
|
|
CryFace
|
|
mesh = new CIndexedMesh
|
|
//m_pFaces = (CObjFace*)malloc(sizeof(CObjFace)*nFaces);
|
|
//mesh->
|
|
|
|
int numv = srcBuf->m_SecVertCount;
|
|
int stride1,stride2;
|
|
unsigned char *src = srcBuf->GetPosPtr( stride1 );
|
|
unsigned char *trg = trgBuf->GetPosPtr( stride2 );
|
|
for (int i = 0; i < numv; i++)
|
|
{
|
|
Vec3 &sv = *(Vec3*)src;
|
|
Vec3 &tv = *(Vec3*)trg;
|
|
//Vec3 sv1 = stm.TransformPoint(sv);
|
|
tv = tm.TransformPoint( sv );
|
|
src += stride1;
|
|
trg += stride2;
|
|
}
|
|
|
|
trgBuf->InvalidateVideoBuffer();
|
|
m_flags |= BRF_RE_VALID;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
*/ |