Game Development Community

dev|Pro Game Development Curriculum

Alpha-Transparency support for Interiors

by Christian M Weber · 10/06/2003 (8:53 am) · 45 comments

Download Code File

Working transparent polys in TGE

This works with current HEAD (9/30/2003)

--------------------
BACK UP YOUR CODE
--------------------

First, d/l the ZIP file and place interiorTrans.* files in your interior folder

Open your vc6 project, and add interiorTrans.cc to your Torque Demo files
Also add it you Torque Lib files

Now for the fun part!

Goto your engine\interior folder

Open interior.cc

Find: const Surface& rSurface = mSurfaces[output[i]];
after it add
if(bool(rSurface.surfaceFlags & SurfaceTrans))
			continue;
This will keep our trans polys out of the active poly list

Repeat the above step 5 more times (till you can't find any more matching strings)

Save & close file.

Open interior.h

find: class InteriorInstance;
add after it
class InteriorTrans;

find: friend class EditGeometry;
add after "friend class InteriorInstance;"
friend class InteriorTrans;

Find: SurfaceOutsideVisible = BIT(4),
after it add
SurfaceTrans = BIT(5),

change SurfaceFlagMask to look like this
SurfaceFlagMask       = (SurfaceDetail      |
                               SurfaceAmbiguous   |
                               SurfaceOrphan      |
                               SurfaceSharedLMaps |
                               SurfaceOutsideVisible |
					 SurfaceTrans) // Transparent

Find: U32 fanMask;
add above it
// transparent
      U8 alpha;
      U32 alphaSrc;
      U32 alphaDst;

Save & close file.

open interiorInstance.cc

after the #includes
add
#include "interior/InteriorTrans.h"

Goto line 577~

add above "addToScene();"
( under those { } near by )

// now loop thru the interior and get all transparent polys
	if (isClientObject()) {

		Interior* pInterior = mInteriorRes->getDetailLevel(0);

		for (i = 0; i < pInterior->mSurfaces.size(); i++) {

			const Interior::Surface& rSurface = pInterior->mSurfaces[i];

			if(rSurface.surfaceFlags & Interior::SurfaceTrans) {

				InteriorTrans *transPolys = new InteriorTrans;

				transPolys->pInteriorInstance = this;
				transPolys->pInterior = pInterior;

				transPolys->surfaceIndex = i;

				transPolys->textureName = mMaterialMaps[0]->getMaterial(rSurface.textureIndex).getGLName();

				transPolys->Update();

				interiorTransPolys.link(transPolys);
			}
		}
	}

Find: removeFromScene();
add above it
interiorTransPolys.free();

Find: sri->mDetailLevel = detailLevel;
add above "PROFILE_END();"

// TODO - transpolys are not checked against zones
	// ALL trans polys render when interior is in view
	InteriorTrans *transPolys = NULL;
	while( bool(transPolys = interiorTransPolys.next(transPolys)) ) {

		SceneRenderImage* image = new SceneRenderImage;
		image->obj = transPolys;
		image->isTranslucent = true;
		image->sortType = SceneRenderImage::Point;
		image->poly[0] = transPolys->sortPoint;

		// Insert it into the scene images.
		state->insertRenderImage(image);
	}

Find: void InteriorInstance::setTransform(const MatrixF & mat)
add above "if (isServerObject())"
InteriorTrans *transPolys = NULL;
	while( bool(transPolys = interiorTransPolys.next(transPolys)) ) {
		transPolys->Update();
	}

Save & close file.

Open interiorInstance.h

after the #includes
add
#ifndef _LLIST_H_
#include "core/llist.h"
#endif

Find: class AudioEnvironment;
add after it
class InteriorTrans;

Find: Convex* mConvexList;
add after it
LList <InteriorTrans> interiorTransPolys;

Save & close file.

open interiorIO.cc

Find: stream.read(&mSurfaces[i].surfaceFlags);
add after it
if(bool(mSurfaces[i].surfaceFlags & SurfaceFlags::SurfaceTrans)) {

		stream.read(&mSurfaces[i].alpha);
		stream.read(&mSurfaces[i].alphaSrc);
		stream.read(&mSurfaces[i].alphaDst);
	}

Find: stream.write(mSurfaces[i].surfaceFlags);
add after it
if(bool(mSurfaces[i].surfaceFlags & SurfaceFlags::SurfaceTrans)) {

		stream.write(mSurfaces[i].alpha);
		stream.write(mSurfaces[i].alphaSrc);
		stream.write(mSurfaces[i].alphaDst);
	}

Save & close file.

Goto your tools\map2dif folder

Open editGeometry.cc

After the #includes and extern
add
extern U32 gTrans;

find: case DetailBrush:
after "break;"
add
case TransparentBrush: // TransparentBrushs are detail brushes
                  mDetailBrushes.push_back(gBrushArena.allocateBrush());
                  pBrush = mDetailBrushes.last();
                  pBrush->mBrushType = TransparentBrush;

                  pBrush->materialType = 0;
                  pBrush->brushId      = mCurrBrushId++;
						gTrans++;
                  break;

find: if (pToker->getToken()[0] != '}')
add above it
switch (pEntity->getBrushType()) {

			case TransparentBrush:

				if(pBrush->mPlanes[0].owningEntity == NULL)
					pBrush->mPlanes[0].owningEntity = static_cast<TransEntity*>(mEntities.last());

			break;
		}

find: pEntity = new DetailEntity;
add after it
else if (pToker->tokenICmp(TransEntity::getClassName()))
      pEntity = new TransEntity;



find: rSurface.winding.brushId = brush.brushId;
add after it
if(brush.mBrushType == TransparentBrush) {

				TransEntity* Trans = static_cast<TransEntity*>(brush.mPlanes[0].owningEntity);

				rSurface.alpha = Trans->mAlpha;
				rSurface.alphaSrc = Trans->mAlphaSrc;
				rSurface.alphaDst = Trans->mAlphaDst;
			}

Scroll down to: rSurface.flags = (brush.mBrushType == DetailBrush) ? Interior::SurfaceDetail : 0;
add after it
rSurface.flags |= (brush.mBrushType == TransparentBrush) ? (Interior::SurfaceTrans | Interior::SurfaceDetail) : 0;

Scroll down some more to: ce.flags = (brush.mBrushType == DetailBrush) ? Interior::SurfaceDetail : 0;
add after it
rSurface.flags |= (brush.mBrushType == TransparentBrush) ? Interior::SurfaceDetail : 0;
Null Surface don't need trans support

Save & close file.

Open editGeometry.h

find: class DoorEntity;
add after it
class  TransEntity;

find: U32 flags;
add after it
U8 alpha;
      U32 alphaSrc;
      U32 alphaDst;

Save & close file.

Open entityTypes.cc

Goto line 211
add
TransEntity::TransEntity() {
}

TransEntity::~TransEntity() {
}

#ifndef GL_ZERO

/* BlendingFactorSrc */
#define GL_ZERO                           0
#define GL_ONE                            1
#define GL_DST_COLOR                      0x0306
#define GL_ONE_MINUS_DST_COLOR            0x0307
#define GL_SRC_ALPHA_SATURATE             0x0308
#define GL_SRC_ALPHA                      0x0302
#define GL_ONE_MINUS_SRC_ALPHA            0x0303
#define GL_DST_ALPHA                      0x0304
#define GL_ONE_MINUS_DST_ALPHA            0x0305

/* BlendingFactorDest */
/*      GL_ZERO */
/*      GL_ONE */
#define GL_SRC_COLOR                      0x0300
#define GL_ONE_MINUS_SRC_COLOR            0x0301
/*      GL_SRC_ALPHA */
/*      GL_ONE_MINUS_SRC_ALPHA */
/*      GL_DST_ALPHA */
/*      GL_ONE_MINUS_DST_ALPHA */

#endif // !GL_ZERO

U32 getAlphaValByName(Tokenizer* pToker) {

	U32 blend;

	if(pToker->tokenICmp("GL_ZERO")) {
		blend = GL_ZERO;
	}
	else if(pToker->tokenICmp("GL_ONE")) {
		blend = GL_ONE;
	}
	else if(pToker->tokenICmp("GL_DST_COLOR")) {
		blend = GL_DST_COLOR;
	}
	else if(pToker->tokenICmp("GL_ONE_MINUS_DST_COLOR")) {
		blend = GL_ONE_MINUS_DST_COLOR;
	}
	else if(pToker->tokenICmp("GL_SRC_ALPHA_SATURATE")) {
		blend = GL_SRC_ALPHA_SATURATE;
	}
	else if(pToker->tokenICmp("GL_SRC_ALPHA")) {
		blend = GL_SRC_ALPHA;
	}
	else if(pToker->tokenICmp("GL_DST_ALPHA")) {
		blend = GL_DST_ALPHA;
	}
	else if(pToker->tokenICmp("GL_ONE_MINUS_DST_ALPHA")) {
		blend = GL_ONE_MINUS_DST_ALPHA;
	}
	else if(pToker->tokenICmp("GL_SRC_COLOR")) {
		blend = GL_SRC_COLOR;
	}
	else if(pToker->tokenICmp("GL_ONE_MINUS_SRC_COLOR")) {
		blend = GL_ONE_MINUS_SRC_COLOR;
	}
	else if(pToker->tokenICmp("GL_ONE_MINUS_SRC_ALPHA")) {
		blend = GL_ONE_MINUS_SRC_ALPHA;
	}
	else {
		dPrintf("\nAlpha Blend invalid: %s\n", pToker->getToken());
		blend = GL_ZERO;
	}

	return blend;
}

bool TransEntity::parseEntityDescription(Tokenizer* pToker) {

	// Tokenizer comes in pointing to the classname.  We'll check that, just to be
	//  thorough.
	AssertFatal(pToker->tokenICmp(getClassName()),
		avar("Wrong class name? (expected %s, got %s)", getClassName(), pToker->getToken()));

	pToker->advanceToken(true);
	while (pToker->getToken()[0] != '{' && pToker->getToken()[0] != '}') {

		if (pToker->tokenICmp("alpha")) {

			pToker->advanceToken(false, true);

			mAlpha = dAtoi(pToker->getToken());
		}
		else if (pToker->tokenICmp("alphaSrc")) {

			pToker->advanceToken(false, true);
			AssertISV(dStrlen(pToker->getToken()) < 255, avar("Error: Name %s must be less than 255 chars!", pToker->getToken()));

			mAlphaSrc = getAlphaValByName(pToker);
		}
		else if (pToker->tokenICmp("alphaDst")) {

			pToker->advanceToken(false, true);
			AssertISV(dStrlen(pToker->getToken()) < 255, avar("Error: Name %s must be less than 255 chars!", pToker->getToken()));

			mAlphaDst = getAlphaValByName(pToker);
		}
		else
			pToker->advanceToken(false);

		pToker->advanceToken(true);
	}

	return true;
}

BrushType TransEntity::getBrushType() {
   return TransparentBrush;
}

const char* TransEntity::getClassName() {
   return "trans";
}

bool TransEntity::isPointClass() const {
   return false;
}

const char* TransEntity::getName() const {
   static char bogoChar = '[[60c1e6e273ed5]]';
   return &bogoChar;
}
const Point3D& TransEntity::getOrigin() const {
   static Point3D bogoPoint(0, 0, 0);
   return bogoPoint;
}

Save & close file.

Open entityTypes.h

Goto line 71
add
class TransEntity : public EditGeometry::Entity
{
public:
	TransEntity();
	~TransEntity();

	U8 mAlpha;
	U32 mAlphaSrc;
	U32 mAlphaDst;

	static const char* getClassName();
	bool               parseEntityDescription(Tokenizer* pToker);
	const char*        getName()   const;
	const Point3D&     getOrigin() const;
	BrushType          getBrushType();

	// ok, not really, but as far as the parser is concered, yes.
	bool isPointClass() const;
};

Save & close file.

Open exportGeometry.cc

find: rSurface.surfaceFlags = editSurface.flags & Interior::SurfaceFlagMask;
add after it
rSurface.alpha = editSurface.alpha;
   rSurface.alphaSrc = editSurface.alphaSrc;
   rSurface.alphaDst = editSurface.alphaDst;

Save & close file.

Open main.cc

find: EditInteriorResource* gWorkingResource = NULL;
add after it
U32 gTrans = 0; // Used for the statistics screen

find: // Give status

replace
dPrintf("\n  STATISTICS\n"
              "   - Total brushes:      %d\n"
              "     + structural:       %d\n"
              "     + detail:           %d\n"
              "     + portal:           %d\n"
              "   - Number of zones:    %d\n"
              "   - Number of surfaces: %d\n", gWorkingGeometry->getTotalNumBrushes(),
              gWorkingGeometry->getNumStructuralBrushes(),
              gWorkingGeometry->getNumDetailBrushes(),
              gWorkingGeometry->getNumPortalBrushes(),
              gWorkingGeometry->getNumZones(),
              gWorkingGeometry->getNumSurfaces());
with
dPrintf("\n  STATISTICS\n"
              "   - Total brushes:      %d\n"
              "     + structural:       %d\n"
              "     + detail:           %d\n"
              "     + portal:           %d\n"
              "     + transparent:      %d\n"
              "   - Number of zones:    %d\n"
              "   - Number of surfaces: %d\n", gWorkingGeometry->getTotalNumBrushes(),
              gWorkingGeometry->getNumStructuralBrushes(),
              gWorkingGeometry->getNumDetailBrushes() - gTrans,
              gWorkingGeometry->getNumPortalBrushes(),
              gTrans,
              gWorkingGeometry->getNumZones(),
              gWorkingGeometry->getNumSurfaces());

Save & close file.

Open morianBasics.h

find: VehicleCollisionBrush = 4
change so it looks like this
VehicleCollisionBrush = 4,
   TransparentBrush = 5

Save & close file.


Do a FULL compile of Torque Lib, the Demo and last map2dif

For WorldCraft, open your .fgd file
Scroll down some and add after the detail entity
@SolidClass = trans : "Trans Detail Brush Entity"
[
  alpha(string) : "alpha" : "100"
  alphaSrc(string) : "alphaSrc" : "GL_SRC_ALPHA"
  alphaDst(string) : "alphaDst" : "GL_ONE_MINUS_SRC_ALPHA"
]

For QuArK, Goto addons\Torque folder
Open DataTorque.qrk

Find: detail:b =
add after the detail entity
trans:b =
        {
          ;incl = "brush64"
          ;desc = "Transparent Brush Entity"
          alpha = "100"
          alphaSrc = "GL_SRC_ALPHA"
          alphaDst = "GL_ONE_MINUS_SRC_ALPHA"
        }


I've included a test.map test.dif and the 2 textures it uses.

Some code based off of James "Corvidae" William's interior trans http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=3704
Page«First 1 2 3 Next»
#41
12/27/2005 (1:16 am)
Does anyone know if this resource will compile into the map2dif_plus tool? Just asking as I was over at a mates place (he just loves mapping) had the new 3d game studio or somthing, and it was using the map2dif_plus.exe. I replaced it with a fresh map2dif.exe and the maps wouldn't compile, I'm sure there was an error but my FPS relexes on the pause/break key were no match for the speed of a closing console window.

Its not a biggy but thought I see if anyone has done it.

I just had a thought that it could be something to do with map220 format which is what 3d world studio (hehe got the right name this time) exports.

****
Just got home and merged the resource into map3dif_plus , looks good so far. Just need a transparent images now....

I can't believe how dumb I am. Got it to compile and link ok. thinking it was fine started, to run it and what do you know nothing happened. My DIFs didn'[t have transparency. I found out why because I was using an old version of dif2map_plus I hadn't copied the new version to my working folder. After I used the correct version it didn't like it.. Went back to map2dif.exe as it works fine......
#42
01/17/2007 (4:01 pm)
anyone who adapts this should make sure to use a Vector instead of the LList.
the way the LList is used really shows up as a cpu culprit when you start getting into complicated scenes with these. the indexing was causing my InteriorInstance::preprenderimage to take 15% of my cpu time, converting it to a vector and looping through that normally dropped it down to 0.75% of cpu time. But Like I said you won't notice it until you get some really complex scenes using lots of these.

thanks so much for the resource by the way, it was a great place to start getting this to work for us.
#43
02/28/2007 (2:42 am)
Anybody got a working 1.5 version of this? The old way I was doing this is just not going to work anymore and this seems like the best way to go.
#44
03/14/2008 (12:03 pm)
This would be a good thing to get working in 1.5.2 otherwise I'll have to "upgrade" to 1.4 - Anyone have info on the status? Any reason this wasn't included in the engine ?
#45
05/02/2009 (3:38 am)
"Transparency in DIF's is not supported out of the box. You can use the method that Morrock mentioned, though it will still cast shadows since they are calculated by collision hulls. You can add in transparency to Torque through a resource, but it can have bad effects on zoning and portaling your areas."

www.garagegames.com/community/forums/viewthread/74434
Page«First 1 2 3 Next»