123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- /* Copyright (c) 2002-2012 Croteam Ltd.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as published by
- the Free Software Foundation
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
- #include "stdh.h"
- #include <Engine/Brushes/Brush.h>
- #include <Engine/Math/Float.h>
- #include <Engine/Math/Object3D.h>
- #include <Engine/Templates/StaticArray.cpp>
- #include <Engine/Templates/DynamicContainer.cpp>
- #include <Engine/Templates/DynamicArray.cpp>
- #include <Engine/World/WorldEditingProfile.h>
- #include <Engine/Brushes/BrushTransformed.h>
- #include <Engine/Graphics/Color.h>
- #include <Engine/Math/Projection_DOUBLE.h>
- /*
- * Add 3d object as new mip brush.
- */
- void CBrush3D::AddMipBrushFromObject3D_t(CObject3D &ob, FLOAT fSwitchDistance) // throw char *
- {
- ASSERT(GetFPUPrecision()==FPT_53BIT);
- // create one brush mip
- CBrushMip *pbmBrushMip = new CBrushMip;
- // add it to the brush
- br_lhBrushMips.AddTail(pbmBrushMip->bm_lnInBrush);
- pbmBrushMip->bm_pbrBrush = this;
- pbmBrushMip->bm_fMaxDistance = fSwitchDistance;
- // add the object to the brush mip
- pbmBrushMip->AddFromObject3D_t(ob);
- }
- /*
- * Fill a brush from 3d object.
- */
- void CBrush3D::FromObject3D_t(CObject3D &ob) // throw char *
- {
- ASSERT(GetFPUPrecision()==FPT_53BIT);
- // clear this brush in case there is something in it
- Clear();
- // create one brush mip
- CBrushMip *pbmBrushMip = new CBrushMip;
- // add it to the brush
- br_lhBrushMips.AddTail(pbmBrushMip->bm_lnInBrush);
- pbmBrushMip->bm_pbrBrush = this;
- // add the object to the brush mip
- pbmBrushMip->AddFromObject3D_t(ob);
- }
- /*
- * Add an object3d to brush. (returns pointer to the first created sector)
- */
- CBrushSector *CBrushMip::AddFromObject3D_t(CObject3D &ob) // throw char *
- {
- CSetFPUPrecision sfp(FPT_53BIT);
- _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_ADDFROMOBJECT3D);
- // optimize the object, to remove replicated and unused elements and find edge inverses
- CBrush3D::OptimizeObject3D(ob);
- // turn this on to dump result of all CSG operations
- #ifndef NDEBUG
- // ob.DebugDump();
- #endif //NDEBUG
- // create as much new sectors in brush mip as there are sectors in object
- CBrushSector *pbscSectors = bm_abscSectors.New(ob.ob_aoscSectors.Count());
- CBrushSector *pbscFirstSector = pbscSectors;
- // for each sector in the object
- FOREACHINDYNAMICARRAY(ob.ob_aoscSectors, CObjectSector, itosc) {
- // set brush sector's pointer to the brush
- pbscSectors->bsc_pbmBrushMip = this;
- // fill one brush sector from it
- pbscSectors->FromObjectSector_t(*itosc);
- pbscSectors++;
- }
- _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_ADDFROMOBJECT3D);
- // return pointer to first created sector
- return pbscFirstSector;
- }
- /*
- * Fill a brush sector from a sector in object3d.
- */
- void CBrushSector::FromObjectSector_t(CObjectSector &osc) // throw char *
- {
- // copy sector color
- bsc_colColor = osc.osc_colColor;
- bsc_colAmbient = osc.osc_colAmbient;
- bsc_ulFlags = osc.osc_ulFlags[0] & ~(BSCF_SELECTED|BSCF_SELECTEDFORCSG);
- bsc_ulFlags2 = osc.osc_ulFlags[1];
- bsc_ulVisFlags = osc.osc_ulFlags[2];
- bsc_strName = osc.osc_strName;
- // lock the object elements
- osc.LockAll();
- // lock the brush elements
- LockAll();
- /* Copy vertices. */
- // get the number of vertices in object
- INDEX ctVertices = osc.osc_aovxVertices.Count();
- // create that much vertices in brush
- bsc_abvxVertices.New(ctVertices);
- bsc_awvxVertices.New(ctVertices);
- // copy all vertices and set their indices
- for(INDEX iVertex=0; iVertex<ctVertices; iVertex++) {
- bsc_abvxVertices[iVertex].bvx_vdPreciseRelative = osc.osc_aovxVertices[iVertex];
- bsc_abvxVertices[iVertex].bvx_pbscSector = this;
- osc.osc_aovxVertices[iVertex].ovx_Index = iVertex;
- }
- /* Copy planes. */
- // get the number of planes in object
- INDEX ctPlanes = osc.osc_aoplPlanes.Count();
- // create that much planes in brush
- bsc_abplPlanes.New(ctPlanes);
- bsc_awplPlanes.New(ctPlanes);
- // copy all planes and set their indices
- for(INDEX iPlane=0; iPlane<ctPlanes; iPlane++) {
- bsc_abplPlanes[iPlane].bpl_pldPreciseRelative = osc.osc_aoplPlanes[iPlane];
- osc.osc_aoplPlanes[iPlane].opl_Index = iPlane;
- }
- /* Copy edges. */
- // get the number of edges in object
- INDEX ctEdges = osc.osc_aoedEdges.Count();
- // create that much edges in brush
- bsc_abedEdges.New(ctEdges);
- bsc_awedEdges.New(ctEdges);
- // for all edges in object
- for(INDEX iEdge=0; iEdge<ctEdges; iEdge++) {
- CObjectEdge &oed = osc.osc_aoedEdges[iEdge]; // object edge alias
- CBrushEdge &bed = bsc_abedEdges[iEdge]; // brush edge alias
- CWorkingEdge &wed = bsc_awedEdges[iEdge];
- // set the brush edge
- bed.bed_pbvxVertex0 = &bsc_abvxVertices[oed.oed_Vertex0->ovx_Index];
- bed.bed_pbvxVertex1 = &bsc_abvxVertices[oed.oed_Vertex1->ovx_Index];
- // set the working edge
- bed.bed_pwedWorking = &wed;
- wed.wed_iwvx0 = oed.oed_Vertex0->ovx_Index;
- wed.wed_iwvx1 = oed.oed_Vertex1->ovx_Index;
- // set object edge index
- oed.oed_Index = iEdge;
- }
- /* Copy polygons. */
- // get the number of polygons in object
- INDEX ctPolygons = osc.osc_aopoPolygons.Count();
- // create that much polygons in brush
- bsc_abpoPolygons.New(ctPolygons);
- // copy all polygons and set their indices
- for(INDEX iPolygon=0; iPolygon<ctPolygons; iPolygon++) {
- CBrushPolygon &bpo = bsc_abpoPolygons[iPolygon]; // brush polygon alias
- CObjectPolygon &opo = osc.osc_aopoPolygons[iPolygon]; // object polygon alias
- // get plane
- bpo.bpo_pbplPlane = &bsc_abplPlanes[opo.opo_Plane->opl_Index];
- // get texture from object material
- bpo.bpo_abptTextures[0].bpt_toTexture.SetData_t(opo.opo_Material->omt_Name);
- bpo.bpo_abptTextures[1].bpt_toTexture.SetData_t(opo.opo_Material->omt_strName2);
- bpo.bpo_abptTextures[2].bpt_toTexture.SetData_t(opo.opo_Material->omt_strName3);
- // set polygon index
- opo.opo_Index = iPolygon;
- // set polygon color
- bpo.bpo_colColor = opo.opo_colorColor;
- // set polygon mapping
- bpo.bpo_abptTextures[0].bpt_mdMapping = opo.opo_amdMappings[0];
- bpo.bpo_abptTextures[1].bpt_mdMapping = opo.opo_amdMappings[1];
- bpo.bpo_abptTextures[2].bpt_mdMapping = opo.opo_amdMappings[2];
- bpo.bpo_mdShadow = opo.opo_amdMappings[3];
- // set sector pointer
- bpo.bpo_pbscSector = this;
- // copy polygon properties
- const int sizeTextureProperties = sizeof(bpo.bpo_abptTextures[0].bpt_auProperties);
- const int sizePolygonProperties = sizeof(CBrushPolygonProperties);
- ASSERT(sizeof(opo.opo_ubUserData)>=sizePolygonProperties+3*sizeTextureProperties);
- UBYTE *pubUserData = (UBYTE*)&opo.opo_ubUserData;
- memcpy(&bpo.bpo_bppProperties, pubUserData, sizePolygonProperties);
- memcpy(&bpo.bpo_abptTextures[0].bpt_auProperties,
- pubUserData+sizePolygonProperties+0*sizeTextureProperties,
- sizeTextureProperties);
- memcpy(&bpo.bpo_abptTextures[1].bpt_auProperties,
- pubUserData+sizePolygonProperties+1*sizeTextureProperties,
- sizeTextureProperties);
- memcpy(&bpo.bpo_abptTextures[2].bpt_auProperties,
- pubUserData+sizePolygonProperties+2*sizeTextureProperties,
- sizeTextureProperties);
- bpo.bpo_colShadow = *(ULONG*)(pubUserData+sizePolygonProperties+3*sizeTextureProperties),
- // set polygon flags
- bpo.bpo_ulFlags = opo.opo_ulFlags & ~(OPOF_IGNOREDBYCSG|BPOF_SELECTED);
- // if the polygon was just created
- if(!(bpo.bpo_ulFlags&BPOF_WASBRUSHPOLYGON)) {
- // initialize its textures and properties properly
- bpo.bpo_bppProperties.bpp_ubShadowBlend = 1;
- bpo.bpo_colShadow = C_WHITE|CT_OPAQUE;
- bpo.bpo_abptTextures[0].s.bpt_colColor = C_WHITE|CT_OPAQUE;
- bpo.bpo_abptTextures[0].s.bpt_ubFlags = BPTF_DISCARDABLE;
- bpo.bpo_abptTextures[0].s.bpt_ubScroll = 0;
- bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_OPAQUE;
- bpo.bpo_abptTextures[1].s.bpt_colColor = C_WHITE|CT_OPAQUE;
- bpo.bpo_abptTextures[1].s.bpt_ubFlags = BPTF_DISCARDABLE;
- bpo.bpo_abptTextures[1].s.bpt_ubScroll = 0;
- bpo.bpo_abptTextures[1].s.bpt_ubBlend = BPT_BLEND_SHADE;
- bpo.bpo_abptTextures[2].s.bpt_colColor = C_WHITE|CT_OPAQUE;
- bpo.bpo_abptTextures[2].s.bpt_ubFlags = BPTF_DISCARDABLE;
- bpo.bpo_abptTextures[2].s.bpt_ubScroll = 0;
- bpo.bpo_abptTextures[2].s.bpt_ubBlend = BPT_BLEND_SHADE;
- bpo.bpo_ulFlags|=BPOF_WASBRUSHPOLYGON;
- }
- // if it was a wall, but it became a portal now
- if (!(bpo.bpo_ulFlags&BPOF_WASPORTAL) && (bpo.bpo_ulFlags&OPOF_PORTAL)) {
- // turn on usual portal flags
- bpo.bpo_ulFlags |= (BPOF_PASSABLE|BPOF_PORTAL);
- // make its first texture translucent
- bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_BLEND;
- // make its shadow additive
- bpo.bpo_bppProperties.bpp_ubShadowBlend = BPT_BLEND_ADD;
- // if it was a portal, but it became a wall now
- } else if ((bpo.bpo_ulFlags&BPOF_WASPORTAL) && !(bpo.bpo_ulFlags&OPOF_PORTAL)) {
- // turn off usual portal flags
- bpo.bpo_ulFlags &= ~(BPOF_PASSABLE|BPOF_PORTAL);
- // make its first texture opaque
- bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_OPAQUE;
- // make its shadow shading
- bpo.bpo_bppProperties.bpp_ubShadowBlend = BPT_BLEND_SHADE;
- }
- // get the brush of this sector
- CBrush3D *pbr = bsc_pbmBrushMip->bm_pbrBrush;
- ASSERT(pbr!=NULL);
- // if the brush is field
- if (pbr->br_pfsFieldSettings!=NULL) {
- // set polygon flags for fields
- bpo.bpo_ulFlags|=BPOF_PORTAL|BPOF_PASSABLE;
- }
- // get the number of edges in object polygon
- INDEX ctPolygonEdges = opo.opo_PolygonEdges.Count();
- // create that much edges in brush polygon
- bpo.bpo_abpePolygonEdges.New(ctPolygonEdges);
- // for all edges in object polygon
- INDEX iPolygonEdge=0;
- FOREACHINDYNAMICARRAY(opo.opo_PolygonEdges, CObjectPolygonEdge, itope) {
- // get corresponding polygon edge in brush polygon
- CBrushPolygonEdge &bpe = bpo.bpo_abpePolygonEdges[iPolygonEdge];
- // set edge reference
- bpe.bpe_pbedEdge = &bsc_abedEdges[itope->ope_Edge->oed_Index];
- // set backward flag
- bpe.bpe_bReverse = itope->ope_Backward;
- iPolygonEdge++;
- }
- }
- // unlock the object elements
- osc.UnlockAll();
- // unlock the brush elements
- UnlockAll();
- // update changed sector's data after dragging vertices or importing
- UpdateSector();
- }
|