plDynamicTextMap *plLayerConverter::ICreateDynTextMap( const plString &layerName, uint32_t width, uint32_t height, bool includeAlphaChannel, plMaxNode *node ) { hsGuardBegin( "plPlasmaMAXLayer::ICreateDynTextMap" ); plKey key; plDynamicTextMap *map = nil; // Need a unique key name for every layer that uses one. We could also key // off of width and height, but layerName should be more than plenty plString texName = plFormat("{}_dynText", layerName); // Does it already exist? key = node->FindPageKey( plDynamicTextMap::Index(), texName ); if( key != nil ) { map = plDynamicTextMap::ConvertNoRef( key->GetObjectPtr() ); if( map != nil ) return map; } // Create map = new plDynamicTextMap(); map->SetNoCreate( width, height, includeAlphaChannel ); /// Add a key for it key = hsgResMgr::ResMgr()->NewKey( texName, map, node->GetLocation() ); // All done! return map; hsGuardEnd; }
hsVertexShader& hsVertexShader::Instance() { hsGuardBegin("hsVertexShader::Instance"); static hsVertexShader instance; return instance; hsGuardEnd; }
plLayerInterface* plLayerConverter::IConvertAngleAttenLayer(plPlasmaMAXLayer *layer, plMaxNode *maxNode, uint32_t blendFlags, bool preserveUVOffset, bool upperLayer) { hsGuardBegin( "plPlasmaMAXLayer::IConvertAngleAttenLayer" ); if( !upperLayer ) { fErrorMsg->Set(true, maxNode->GetName(), "Angle Attenuation layers can only be used as a top layer").Show(); fErrorMsg->Set(); return nil; } plAngleAttenLayer* aaLay = (plAngleAttenLayer*)layer; Box3 fade = aaLay->GetFade(); float tr0 = cosf(DegToRad(180.f - fade.Min().x)); float op0 = cosf(DegToRad(180.f - fade.Min().y)); float tr1 = cosf(DegToRad(180.f - fade.Max().x)); float op1 = cosf(DegToRad(180.f - fade.Max().y)); int loClamp = aaLay->GetLoClamp(); int hiClamp = aaLay->GetHiClamp(); int uvwSrc = aaLay->Reflect() ? plLayerInterface::kUVWReflect : plLayerInterface::kUVWNormal; plLayer* lut = ICreateAttenuationLayer(plString::FromUtf8(layer->GetName()), maxNode, uvwSrc, tr0, op0, tr1, op1, loClamp, hiClamp); return lut; hsGuardEnd; }
void hsVertexShader::Close() { hsGuardBegin("hsVertexShader::DeInitLights"); fLightMapGen = nil; hsGuardEnd; }
// // Create Bitmap // plMipmap *plBitmapCreator::ICreateBitmap(plBitmapData *bd) { hsGuardBegin("hsConverterUtils::CreateBitmap"); // Load the bitmap BitmapInfo bi; bi.SetName(bd->fileName.AsString().c_str()); #if 0 // This isn't really an issue since the textures are packed -Colin const int kMaxFileNameLength = 30; if (strlen(bi.Filename()) > kMaxFileNameLength) { // Allow to continue, But make it painful char errStr[256]; sprintf(errStr, "File name longer than %d, won't burn to CD (%s)", kMaxFileNameLength, bi.Filename());//bitmapTex->GetName()); MessageBox(GetActiveWindow(), errStr, bd->fileName, MB_OK|MB_ICONEXCLAMATION); } #endif bool notMipped = (bd->texFlags & plMipmap::kForceOneMipLevel) != 0; float sigma = bd->sig; // Load the bitmap Bitmap *bm = TheManager->Load(&bi); if (!bm) { // FIXME /* if (fErrorMsg->Set(!(fWarned & kWarnedNoMoreBitmapLoadErr), "Error loading bitmap", pathName).CheckAskOrCancel()) { fWarned |= kWarnedNoMoreBitmapLoadErr; } */ return nil; } BitmapStorage *storage = bm->Storage(); BitmapInfo *bInfo = &storage->bi; ICheckOutBitmap(bInfo, bm, bd->fileName); // // Create a plMipmap // plMipmap *hBitmap = new plMipmap; if( (bm->Width() ^ (bm->Width() & -bm->Width())) ||(bm->Height() ^ (bm->Height() & -bm->Height())) ) { IResampBitmap(bm, *hBitmap); } else if( ((bm->Width() >> 3) > bm->Height())||((bm->Height() >> 3) > bm->Width()) ) { IResampBitmap(bm, *hBitmap); } else {
plLayerConverter &plLayerConverter::Instance( void ) { hsGuardBegin( "plLayerConverter::Instance" ); static plLayerConverter instance; return instance; hsGuardEnd; }
hsVertexShader::hsVertexShader() : fConverterUtils(hsConverterUtils::Instance()), fInterface(nil), fLightMapGen(nil), fShaded(0) { hsGuardBegin("hsVertexShader::hsVertexShader"); fLocalToWorld.Reset(); hsGuardEnd; }
plLayerInterface *plLayerConverter::ConvertTexmap( Texmap *texmap, plMaxNode *maxNode, uint32_t blendFlags, bool preserveUVOffset, bool upperLayer ) { hsGuardBegin( "plLayerConverter::ConvertTexmap" ); fDbgNodeName = maxNode->GetName(); // We only convert plPlasmaMAXLayers plPlasmaMAXLayer *layer = plPlasmaMAXLayer::GetPlasmaMAXLayer( texmap ); if( layer == nil ) { fErrorMsg->Set( true, "Plasma Layer Error", "Cannot convert layer '%s'--unrecognized MAX layer type", texmap->GetName() ); fErrorMsg->Show(); fErrorMsg->Set(); return nil; } // KLUDGE - Some things don't set the name for their layers (ie projected // runtime lights). So that we don't end up with an empty keyname, set the // name to the nodes name if there isn't one. -Colin const char* layerName = layer->GetName(); if (!layerName || layerName[0] == '\0') layer->SetName(maxNode->GetName()); // Switch on the class ID plLayerInterface *plasmaLayer = nil; if( layer->ClassID() == LAYER_TEX_CLASS_ID ) plasmaLayer = IConvertLayerTex( layer, maxNode, blendFlags, preserveUVOffset, upperLayer ); else if( layer->ClassID() == STATIC_ENV_LAYER_CLASS_ID ) plasmaLayer = IConvertStaticEnvLayer( layer, maxNode, blendFlags, preserveUVOffset, upperLayer ); else if( layer->ClassID() == DYNAMIC_ENV_LAYER_CLASS_ID ) plasmaLayer = IConvertDynamicEnvLayer( layer, maxNode, blendFlags, preserveUVOffset, upperLayer ); else if( layer->ClassID() == DYN_TEXT_LAYER_CLASS_ID ) plasmaLayer = IConvertDynamicTextLayer( layer, maxNode, blendFlags, preserveUVOffset, upperLayer ); else if( layer->ClassID() == ANGLE_ATTEN_LAYER_CLASS_ID ) plasmaLayer = IConvertAngleAttenLayer( layer, maxNode, blendFlags, preserveUVOffset, upperLayer ); else if( layer->ClassID() == MAX_CAMERA_LAYER_CLASS_ID ) plasmaLayer = IConvertCameraLayer( layer, maxNode, blendFlags, preserveUVOffset, upperLayer ); IRegisterConversion( layer, plasmaLayer ); return plasmaLayer; hsGuardEnd; }
void hsVertexShader::Open() { hsGuardBegin("hsVertexShader::InitLights"); fLocalToWorld.Reset(); fInterface = ::GetCOREInterface(); fLightMapGen = &plLightMapGen::Instance(); hsGuardEnd; }
plLayer *plLayerConverter::ICreateLayer( const plString &name, bool upperLayer, plLocation &loc ) { hsGuardBegin( "plPlasmaMAXLayer::ICreateLayer" ); plLayer *layer = new plLayer; layer->InitToDefault(); hsgResMgr::ResMgr()->NewKey( name, layer, loc ); return layer; hsGuardEnd; }
void hsVertexShader::IShadeVertices( plGeometrySpan *span, hsBitVector *dirtyVector, INode* node, bool translucent ) { hsGuardBegin( "hsVertexShader::IShadeVertices" ); plMaxNode* maxNode = (plMaxNode*)node; if( maxNode->CanConvert() && (nil != maxNode->GetLightMapComponent()) ) return; int index; hsPoint3 position; hsVector3 normal; hsColorRGBA color, illum; plTmpVertex3 *vertices; /// Allocate temp vertex array vertices = new plTmpVertex3[ span->fNumVerts ]; for( index = 0; index < span->fNumVerts; index++ ) { span->ExtractVertex( index, &position, &normal, &color, &illum ); span->ExtractInitColor( index, &color, &illum ); /// fShadeColorTable is the shaded portion. fIllumColorTable is the illuminated portion; /// for more and less confusing details, see above. fShadeColorTable[ index ].Set( color.r, color.g, color.b, color.a ); fIllumColorTable[ index ].Set( illum.r, illum.g, illum.b, 1 ); position = fLocalToWorld * position; normal = fNormalToWorld * normal; vertices[ index ].fLocalPos = position; vertices[ index ].fNormal = normal; vertices[ index ].fNormal.Normalize(); } const char* dbgNodeName = node->GetName(); TimeValue t = fInterface->GetTime(); Box3 bbox; node->EvalWorldState(t).obj->GetDeformBBox(t, bbox, &node->GetObjectTM(t)); plMaxLightContext ctx(bbox, t); for( index = 0; index < span->fNumVerts; index++ ) INativeShadeVtx(fIllumColorTable[index], ctx, vertices[ index ], translucent); // Delete temp arrays delete [] vertices; hsGuardEnd; }
plLayerInterface *plLayerConverter::IConvertDynamicTextLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, uint32_t blendFlags, bool preserveUVOffset, bool upperLayer ) { hsGuardBegin( "plLayerConverter::IConvertDynamicTextLayer" ); plDynamicTextLayer *maxLayer; IParamBlock2 *bitmapPB; plLocation loc; maxLayer = (plDynamicTextLayer *)layer; loc = maxNode->GetLocation(); bitmapPB = maxLayer->GetParamBlockByID( plDynamicTextLayer::kBlkBitmap ); if( !bitmapPB ) { fErrorMsg->Set( !bitmapPB, "Plasma Layer Error", "Bitmap paramblock for Plasma Layer not found" ).Show(); fErrorMsg->Set(); return nil; } // Get a new layer to play with plLayer *plasmaLayer = ICreateLayer( plString::FromUtf8( maxLayer->GetName() ), upperLayer, loc ); /// UV Gen IProcessUVGen( maxLayer, plasmaLayer, nil, preserveUVOffset ); // Create the "texture" plDynamicTextMap *texture = ICreateDynTextMap( plasmaLayer->GetKeyName(), bitmapPB->GetInt( plDynamicTextLayer::kBmpExportWidth ), bitmapPB->GetInt( plDynamicTextLayer::kBmpExportHeight ), bitmapPB->GetInt( plDynamicTextLayer::kBmpIncludeAlphaChannel ), maxNode ); // Set the initial bitmap if necessary uint32_t *initBuffer = IGetInitBitmapBuffer( maxLayer ); if( initBuffer != nil ) { texture->SetInitBuffer( initBuffer ); delete [] initBuffer; } // Add the texture in hsgResMgr::ResMgr()->AddViaNotify( texture->GetKey(), new plLayRefMsg( plasmaLayer->GetKey(), plRefMsg::kOnCreate, 0, plLayRefMsg::kTexture ), plRefFlags::kActiveRef ); // All done! return (plLayerInterface *)plasmaLayer; hsGuardEnd; }
bool hsVertexShader::IsTranslucent( hsGMaterial *material ) { hsGuardBegin("hsVertexShader::IsTranslucent"); if( material ) { plLayerInterface* layer = material->GetLayer(0); if( layer && ( layer->GetShadeFlags() & hsGMatState::kShadeSoftShadow ) ) { return true; } } return false; hsGuardEnd; }
void plLayerConverter::IProcessUVGen( plPlasmaMAXLayer *srcLayer, plLayer *destLayer, plBitmapData *bitmapData, bool preserveUVOffset ) { hsGuardBegin( "plPlasmaMAXLayer::IProcessUVGen" ); StdUVGen *uvGen = (StdUVGen *)srcLayer->GetTheUVGen(); int tiling = uvGen->GetTextureTiling(); // If set this indicates the texture map is tiled in U if (!(tiling & U_WRAP)) { destLayer->SetClampFlags( destLayer->GetClampFlags() | hsGMatState::kClampTextureU ); if( bitmapData != nil ) bitmapData->clampFlags |= plBitmapData::kClampU; } // If set this indicates the texture map is tiled in V if (!(tiling & V_WRAP)) { destLayer->SetClampFlags( destLayer->GetClampFlags() | hsGMatState::kClampTextureV ); if( bitmapData != nil ) bitmapData->clampFlags |= plBitmapData::kClampV; } // UVW Src int32_t uvwSrc = srcLayer->GetMapChannel() - 1; if( fErrorMsg->Set( !( fWarned & kWarnedTooManyUVs ) && ( ( uvwSrc < 0 ) || ( uvwSrc >= plGeometrySpan::kMaxNumUVChannels ) ), destLayer->GetKeyName().c_str(), "Only %d UVW channels (1-%d) currently supported", plGeometrySpan::kMaxNumUVChannels, plGeometrySpan::kMaxNumUVChannels).CheckAskOrCancel() ) fWarned |= kWarnedTooManyUVs; fErrorMsg->Set( false ); destLayer->SetUVWSrc( uvwSrc ); // Get the actual texture transform hsMatrix44 hsTopX; if (uvGen && (hsControlConverter::Instance().StdUVGenToHsMatrix44(&hsTopX, uvGen, preserveUVOffset == true))) destLayer->SetTransform( hsTopX ); // All done! hsGuardEnd; }
plLayerInterface *plLayerConverter::IConvertCameraLayer(plPlasmaMAXLayer *layer, plMaxNode *maxNode, uint32_t blendFlags, bool preserveUVOffset, bool upperLayer) { hsGuardBegin( "plLayerConverter::IConvertCameraLayer" ); IParamBlock2 *pb; plLocation loc; loc = maxNode->GetLocation(); pb = layer->GetParamBlockByID(plMAXCameraLayer::kBlkMain); if (!pb) { fErrorMsg->Set(!pb, "Plasma Layer Error", "Paramblock for Plasma Camera Layer not found" ).Show(); fErrorMsg->Set(); return nil; } plLayer *plasmaLayer = ICreateLayer (plString::FromUtf8(layer->GetName()), upperLayer, loc); plMaxNode *rootNode = (plMaxNode*)pb->GetINode(ParamID(plMAXCameraLayer::kRootNode)); plDynamicCamMap *map = plEnvMapComponent::GetCamMap(rootNode ? rootNode : maxNode); if (map) { int32_t texFlags = 0; if (!pb->GetInt(ParamID(plMAXCameraLayer::kExplicitCam))) { plasmaLayer->SetUVWSrc(plLayerInterface::kUVWPosition); plasmaLayer->SetMiscFlags(hsGMatState::kMiscCam2Screen | hsGMatState::kMiscPerspProjection); hsgResMgr::ResMgr()->AddViaNotify(rootNode->GetSceneObject()->GetKey(), new plGenRefMsg(map->GetKey(), plRefMsg::kOnCreate, -1, plDynamicCamMap::kRefRootNode), plRefFlags::kActiveRef); hsgResMgr::ResMgr()->AddViaNotify(plasmaLayer->GetKey(), new plGenRefMsg(map->GetKey(), plRefMsg::kOnCreate, -1, plDynamicCamMap::kRefMatLayer), plRefFlags::kActiveRef); if (!pb->GetInt(ParamID(plMAXCameraLayer::kForce))) { plBitmap *disableTexture = hsMaterialConverter::Instance().GetStaticColorTexture(pb->GetColor(ParamID(plMAXCameraLayer::kDisableColor)), loc); hsgResMgr::ResMgr()->AddViaNotify(disableTexture->GetKey(), new plGenRefMsg(map->GetKey(), plRefMsg::kOnCreate, -1, plDynamicCamMap::kRefDisableTexture), plRefFlags::kActiveRef); } } else { plMaxNode *camNode = (plMaxNode*)pb->GetINode(ParamID(plMAXCameraLayer::kCamera)); if (camNode) { const plCameraModifier1 *mod = plCameraModifier1::ConvertNoRef(camNode->GetSceneObject()->GetModifierByType(plCameraModifier1::Index())); if (mod) hsgResMgr::ResMgr()->AddViaNotify(mod->GetKey(), new plGenRefMsg(map->GetKey(), plRefMsg::kOnCreate, -1, plDynamicCamMap::kRefCamera), plRefFlags::kActiveRef); } plasmaLayer->SetUVWSrc(pb->GetInt(ParamID(plMAXCameraLayer::kUVSource))); } hsTArray<plMaxNode*> nodeList; hsMaterialConverter::GetNodesByMaterial(maxNode->GetMtl(), nodeList); int i; for (i = 0; i < nodeList.GetCount(); i++) { hsgResMgr::ResMgr()->AddViaNotify(nodeList[i]->GetSceneObject()->GetKey(), new plGenRefMsg(map->GetKey(), plRefMsg::kOnCreate, -1, plDynamicCamMap::kRefTargetNode), plRefFlags::kActiveRef); } hsgResMgr::ResMgr()->AddViaNotify(map->GetKey(), new plLayRefMsg(plasmaLayer->GetKey(), plRefMsg::kOnCreate, -1, plLayRefMsg::kTexture), plRefFlags::kActiveRef); } return plasmaLayer; hsGuardEnd; }
plLayerInterface *plLayerConverter::IConvertDynamicEnvLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, uint32_t blendFlags, bool preserveUVOffset, bool upperLayer ) { hsGuardBegin( "plLayerConverter::IConvertDynamicEnvLayer" ); IParamBlock2 *bitmapPB; plLocation loc; loc = maxNode->GetLocation(); bitmapPB = layer->GetParamBlockByID( plDynamicEnvLayer::kBlkBitmap ); if( !bitmapPB ) { fErrorMsg->Set( !bitmapPB, "Plasma Layer Error", "Bitmap paramblock for Plasma Layer not found" ).Show(); fErrorMsg->Set(); return nil; } // Get a new layer to play with plLayer *plasmaLayer = ICreateLayer( plString::FromUtf8( layer->GetName() ), upperLayer, loc ); // Get the anchor node plMaxNode *anchor = (plMaxNode *)bitmapPB->GetINode( plDynamicEnvLayer::kBmpAnchorNode ); if( anchor == nil ) // Default to self as the anchor--just make sure we make unique versions of this material! anchor = maxNode; if( !anchor->CanConvert() || !( anchor->GetForceLocal() || anchor->GetDrawable() ) ) { fErrorMsg->Set( true, "Plasma Layer Error", "The dynamic envMap material %s has an invalid anchor specified. Please specify a valid Plasma scene object as an anchor.", plasmaLayer->GetKeyName().c_str() ).Show(); fErrorMsg->Set(); return (plLayerInterface *)plasmaLayer; } // Create texture and add it to list if unique int32_t texFlags = 0; /// Since we're a cubic environMap, we don't care about the UV transform nor the uvwSrc plasmaLayer->SetUVWSrc( 0 ); plasmaLayer->SetUVWSrc( plasmaLayer->GetUVWSrc() | plLayerInterface::kUVWReflect ); // Create the texture. If it works, assign it to the layer plString texName; if( anchor == maxNode ) { // Self-anchoring material, make sure the name is unique via the nodeName texName = plFormat("{}_cubicRT@{}", plasmaLayer->GetKeyName(), maxNode->GetName()); } else texName = plFormat("{}_cubicRT", plasmaLayer->GetKeyName()); plBitmap *texture = (plBitmap *)IMakeCubicRenderTarget( texName, maxNode, anchor ); if( texture ) hsgResMgr::ResMgr()->AddViaNotify( texture->GetKey(), new plLayRefMsg( plasmaLayer->GetKey(), plRefMsg::kOnCreate, 0, plLayRefMsg::kTexture ), plRefFlags::kActiveRef ); // Tag this layer as reflective cubic environmentmapping if( bitmapPB->GetInt(plDynamicEnvLayer::kBmpRefract) ) plasmaLayer->SetMiscFlags( plasmaLayer->GetMiscFlags() | hsGMatState::kMiscUseRefractionXform ); else plasmaLayer->SetMiscFlags( plasmaLayer->GetMiscFlags() | hsGMatState::kMiscUseReflectionXform ); return (plLayerInterface *)plasmaLayer; hsGuardEnd; }
plLayerInterface *plLayerConverter::IConvertStaticEnvLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, uint32_t blendFlags, bool preserveUVOffset, bool upperLayer ) { hsGuardBegin( "plLayerConverter::IConvertStaticEnvLayer" ); IParamBlock2 *bitmapPB; plLocation loc; loc = maxNode->GetLocation(); bitmapPB = layer->GetParamBlockByID( plStaticEnvLayer::kBlkBitmap ); if( !bitmapPB ) { fErrorMsg->Set( !bitmapPB, "Plasma Layer Error", "Bitmap paramblock for Plasma Layer not found" ).Show(); fErrorMsg->Set(); return nil; } // Get a new layer to play with plLayer *plasmaLayer = ICreateLayer( plString::FromUtf8( layer->GetName() ), upperLayer, loc ); // Get the texture info PBBitmap *pbbm = bitmapPB->GetBitmap( plStaticEnvLayer::kBmpFrontBitmap + 0 ); BitmapInfo *bi = nil; if( pbbm ) bi = &pbbm->bi; // If the texture had bad info, assert and return the empty layer if (!bi || !bi->Name() || !strcmp(bi->Name(), "")) { // Or don't assert since it can get annoying when you are using someone // elses file and don't have all the textures. return (plLayerInterface *)plasmaLayer; } // Setup the texture creation parameters plBitmapData bd; bd.fileName = bi->Name(); // Create texture and add it to list if unique int32_t texFlags = 0; // Texture Alpha/Color if( bitmapPB->GetInt( plStaticEnvLayer::kBmpInvertColor ) ) plasmaLayer->SetBlendFlags( plasmaLayer->GetBlendFlags() | hsGMatState::kBlendInvertColor ); if( bitmapPB->GetInt( plStaticEnvLayer::kBmpDiscardColor ) ) plasmaLayer->SetBlendFlags( plasmaLayer->GetBlendFlags() | hsGMatState::kBlendNoTexColor ); if( bitmapPB->GetInt( kBmpDiscardAlpha ) ) plasmaLayer->SetBlendFlags( plasmaLayer->GetBlendFlags() | hsGMatState::kBlendNoTexAlpha ); if( bitmapPB->GetInt( plStaticEnvLayer::kBmpInvertAlpha ) ) bd.invertAlpha = true; // Texture quality if( bitmapPB->GetInt( plStaticEnvLayer::kBmpNonCompressed ) ) texFlags |= plBitmap::kForceNonCompressed; switch( bitmapPB->GetInt( plStaticEnvLayer::kBmpScaling ) ) { case plStaticEnvLayer::kScalingHalf: texFlags |= plBitmap::kHalfSize; break; case plStaticEnvLayer::kScalingNone: texFlags |= plBitmap::kNoMaxSize; break; } bd.texFlags = texFlags; bd.isStaticCubicEnvMap = true; for( int i = 0; i < 6; i++ ) { PBBitmap *face = bitmapPB->GetBitmap( plStaticEnvLayer::kBmpFrontBitmap + i ); if( !face ) return (plLayerInterface *)plasmaLayer; bd.faceNames[ i ] = face->bi.Name(); } // Get detail parameters if( bitmapPB->GetInt( plStaticEnvLayer::kBmpUseDetail ) ) { // TODO: be smarter if( blendFlags & hsGMatState::kBlendAdd ) bd.createFlags = plMipmap::kCreateDetailAdd; else if( blendFlags & hsGMatState::kBlendMult ) bd.createFlags = plMipmap::kCreateDetailMult; else bd.createFlags = plMipmap::kCreateDetailAlpha; bd.detailDropoffStart = float( bitmapPB->GetInt( plStaticEnvLayer::kBmpDetailStartSize ) ) / 100.f; bd.detailDropoffStop = float( bitmapPB->GetInt( plStaticEnvLayer::kBmpDetailStopSize ) ) / 100.f; bd.detailMax = float( bitmapPB->GetInt( plStaticEnvLayer::kBmpDetailStartOpac ) ) / 100.f; bd.detailMin = float( bitmapPB->GetInt( plStaticEnvLayer::kBmpDetailStopOpac ) ) / 100.f; } /// Since we're a cubic environMap, we don't care about the UV transform nor the uvwSrc plasmaLayer->SetUVWSrc( 0 ); plasmaLayer->SetUVWSrc( plasmaLayer->GetUVWSrc() | plLayerInterface::kUVWReflect ); // Create the texture. If it works, assign it to the layer if( ( plasmaLayer = IAssignTexture( &bd, maxNode, plasmaLayer, upperLayer ) ) == nil ) return nil; // Tag this layer as reflective cubic environmentmapping if( bitmapPB->GetInt(plStaticEnvLayer::kBmpRefract) ) plasmaLayer->SetMiscFlags( plasmaLayer->GetMiscFlags() | hsGMatState::kMiscUseRefractionXform ); else plasmaLayer->SetMiscFlags( plasmaLayer->GetMiscFlags() | hsGMatState::kMiscUseReflectionXform ); return (plLayerInterface *)plasmaLayer; hsGuardEnd; }
void hsVertexShader::IShadeSpan( plGeometrySpan *span, INode* node ) { hsColorRGBA preDiffuse, rtDiffuse, matAmbient; hsBitVector dirtyVector; int i; bool translucent, shadeIt, addingIt; plLayerInterface *layer = nil; hsGuardBegin("hsVertexShader::ShadeSpan"); const char* dbgNodeName = node->GetName(); if( span->fNumVerts == 0 ) return; fShadeColorTable = new hsColorRGBA[ span->fNumVerts ]; fIllumColorTable = new hsColorRGBA[ span->fNumVerts ]; translucent = IsTranslucent( span->fMaterial ); /// Get material layer #0 addingIt = false; shadeIt = !( span->fProps & plGeometrySpan::kPropNoPreShade ); if( span->fMaterial->GetNumLayers() != 0 ) { layer = span->fMaterial->GetLayer( 0 ); if( layer->GetShadeFlags() & hsGMatState::kShadeNoShade ) shadeIt = false; if( layer->GetBlendFlags() & hsGMatState::kBlendAdd ) addingIt = true; } float opacity = 1.f; for( i = 0; i < span->fMaterial->GetNumLayers(); i++ ) { plLayerInterface* lay = span->fMaterial->GetLayer(i); if( (lay->GetBlendFlags() & hsGMatState::kBlendAlpha) && ( !i || (lay->GetMiscFlags() & hsGMatState::kMiscRestartPassHere) ) ) { opacity = span->fMaterial->GetLayer(i)->GetOpacity(); } } /// Generate color table if( shadeIt ) IShadeVertices( span, &dirtyVector, node, translucent ); else { for( i = 0; i < span->fNumVerts; i++ ) { /// This is good for the old way, but not sure about the new way. Test once new way is in again -mcn // fShadeColorTable[ i ].Set( 1, 1, 1, 1 ); // fIllumColorTable[ i ].Set( 0, 0, 0, 1 ); hsPoint3 position; hsVector3 normal; hsColorRGBA color, illum; span->ExtractVertex( i, &position, &normal, &color, &illum ); span->ExtractInitColor( i, &color, &illum ); fShadeColorTable[ i ].Set( color.r, color.g, color.b, color.a ); fIllumColorTable[ i ].Set( illum.r, illum.g, illum.b, 1 ); } } /// Get mat colors to modulate by if( layer == nil ) { preDiffuse.Set( 1, 1, 1, 1 ); rtDiffuse.Set( 1, 1, 1, 1 ); matAmbient.Set( 0, 0, 0, 0 ); } else { if( layer->GetShadeFlags() & hsGMatState::kShadeWhite ) { preDiffuse.Set( 1, 1, 1, 1 ); rtDiffuse.Set( 1, 1, 1, 1 ); matAmbient.Set( 0, 0, 0, 0 ); } else { preDiffuse = layer->GetPreshadeColor(); // This is for vertex-based lighting, which basically ignores preshading rtDiffuse = layer->GetRuntimeColor(); // This is for vertex-based lighting, which basically ignores preshading matAmbient = layer->GetAmbientColor(); matAmbient.a = 0; } preDiffuse.a = opacity; rtDiffuse.a = opacity; } #if 0 /// Multiply by the material color, and scale by opacity if we're additive blending /// Apply colors now, multiplying by the material color as we go for( i = 0; i < span->fNumVerts; i++ ) { fShadeColorTable[ i ] *= matDiffuse; fShadeColorTable[ i ] += matAmbient; fIllumColorTable[ i ] *= matDiffuse; fIllumColorTable[ i ] += matAmbient; } if( addingIt ) { for( i = 0; i < span->fNumVerts; i++ ) { float opacity = fShadeColorTable[ i ].a; fShadeColorTable[ i ] *= opacity; fIllumColorTable[ i ] *= opacity; } } #else /// Combine shade and illum together into the diffuse color if( ( span->fProps & plGeometrySpan::kLiteMask ) != plGeometrySpan::kLiteMaterial ) { /// The two vertex lighting formulas take in a vetex color pre-processed, i.e. in /// the form of: vtxColor = ( maxVtxColor * materialDiffuse + maxIllumColor ) span->fProps |= plGeometrySpan::kDiffuseFoldedIn; if( !shadeIt ) { for( i = 0; i < span->fNumVerts; i++ ) { fIllumColorTable[ i ].a = 0; fShadeColorTable[ i ] = (fShadeColorTable[ i ] * rtDiffuse) + fIllumColorTable[ i ]; fIllumColorTable[ i ].Set( 0, 0, 0, 0 ); } } else { for( i = 0; i < span->fNumVerts; i++ ) { fIllumColorTable[ i ].a = 1.f; // Following needs to be changed to allow user input vertex colors to modulate // the runtime light values. // fShadeColorTable[ i ] = fIllumColorTable[ i ] * rtDiffuse; fShadeColorTable[ i ] = fShadeColorTable[ i ] * fIllumColorTable[ i ] * rtDiffuse; fIllumColorTable[ i ].Set( 0, 0, 0, 0 ); } } } else { if( !shadeIt ) { // Not shaded, so runtime lit, so we want BLACK vertex colors for( i = 0; i < span->fNumVerts; i++ ) { fShadeColorTable[ i ].Set( 0, 0, 0, 0 ); fIllumColorTable[ i ].Set( 0, 0, 0, 0 ); } } else { for( i = 0; i < span->fNumVerts; i++ ) { fShadeColorTable[ i ] *= fIllumColorTable[ i ]; fIllumColorTable[ i ].Set( 0, 0, 0, 0 ); } } } #endif /// Loop and stuff for( i = 0; i < span->fNumVerts; i++ ) span->StuffVertex( i, fShadeColorTable + i, fIllumColorTable + i ); delete [] fShadeColorTable; delete [] fIllumColorTable; hsGuardEnd; }
plLayerInterface *plLayerConverter::IConvertLayerTex( plPlasmaMAXLayer *layer, plMaxNode *maxNode, uint32_t blendFlags, bool preserveUVOffset, bool upperLayer ) { hsGuardBegin( "plLayerConverter::IConvertLayerTex" ); IParamBlock2 *bitmapPB; plLocation loc; loc = maxNode->GetLocation(); bitmapPB = layer->GetParamBlockByID( plLayerTex::kBlkBitmap ); if( !bitmapPB ) { fErrorMsg->Set( !bitmapPB, "Plasma Layer Error", "Bitmap paramblock for Plasma Layer not found" ).Show(); fErrorMsg->Set(); return nil; } // Get a new layer to play with plLayer *plasmaLayer = ICreateLayer( plString::FromUtf8( layer->GetName() ), upperLayer, loc ); // We're using a texture, try and get its info PBBitmap *pbbm = nil; BitmapInfo *bi = nil; if( bitmapPB->GetInt( kBmpUseBitmap ) ) { if( bitmapPB ) pbbm = bitmapPB->GetBitmap( kBmpBitmap ); if( pbbm ) bi = &pbbm->bi; } // If the texture had bad info, assert and return the empty layer if( !bi || !bi->Name() || !strcmp(bi->Name(), "") ) { if( upperLayer ) { if( fErrorMsg->Set( !( fWarned & kWarnedNoUpperTexture ), "Plasma Export Error", sWarnNoUpperTexture, maxNode->GetName() ).CheckAskOrCancel() ) fWarned |= kWarnedNoUpperTexture; fErrorMsg->Set( false ); delete plasmaLayer; return nil; } else { return (plLayerInterface *)plasmaLayer; } } // Setup the texture creation parameters plBitmapData bd; bd.fileName = bi->Name(); // Create texture and add it to list if unique int32_t texFlags = 0;//hsGTexture::kMipMap; // Texture Alpha/Color if( bitmapPB->GetInt( kBmpInvertColor ) ) plasmaLayer->SetBlendFlags( plasmaLayer->GetBlendFlags() | hsGMatState::kBlendInvertColor ); if( bitmapPB->GetInt( kBmpDiscardColor ) ) plasmaLayer->SetBlendFlags( plasmaLayer->GetBlendFlags() | hsGMatState::kBlendNoTexColor ); if( bitmapPB->GetInt( kBmpDiscardAlpha ) ) plasmaLayer->SetBlendFlags( plasmaLayer->GetBlendFlags() | hsGMatState::kBlendNoTexAlpha ); if( bitmapPB->GetInt( kBmpInvertAlpha ) ) bd.invertAlpha = true; // Texture quality if( bitmapPB->GetInt( kBmpNonCompressed ) ) texFlags |= plBitmap::kForceNonCompressed; if( bitmapPB->GetInt( kBmpNoDiscard ) ) texFlags |= plBitmap::kDontThrowAwayImage; switch( bitmapPB->GetInt( kBmpScaling ) ) { case kScalingHalf: texFlags |= plBitmap::kHalfSize; break; case kScalingNone: texFlags |= plBitmap::kNoMaxSize; break; } // Mip map filtering. if( bitmapPB->GetInt( kBmpNoFilter ) ) texFlags |= plBitmap::kForceOneMipLevel; if( bitmapPB->GetInt( kBmpMipBias ) ) { plasmaLayer->SetZFlags( plasmaLayer->GetZFlags() | hsGMatState::kZLODBias ); plasmaLayer->SetLODBias( bitmapPB->GetFloat( kBmpMipBiasAmt, fConverterUtils.GetTime( fInterface ) ) ); } float sig = bitmapPB->GetFloat( kBmpMipBlur ); bd.texFlags = texFlags; bd.sig = sig; // Get detail parameters if( bitmapPB->GetInt( kBmpUseDetail ) ) { // TODO: be smarter if( blendFlags & hsGMatState::kBlendAdd ) bd.createFlags |= plMipmap::kCreateDetailAdd; else if( blendFlags & hsGMatState::kBlendMult ) bd.createFlags |= plMipmap::kCreateDetailMult; else bd.createFlags |= plMipmap::kCreateDetailAlpha; bd.detailDropoffStart = float(bitmapPB->GetInt(kBmpDetailStartSize)) / 100.f; bd.detailDropoffStop = float(bitmapPB->GetInt(kBmpDetailStopSize)) / 100.f; bd.detailMax = float(bitmapPB->GetInt(kBmpDetailStartOpac)) / 100.f; bd.detailMin = float(bitmapPB->GetInt(kBmpDetailStopOpac)) / 100.f; } // Get max export dimension (since the function we eventually call // expects the max of the two dimensions, we figure that out here and // pass it on) bd.maxDimension = bitmapPB->GetInt( kBmpExportWidth ); int expHt = bitmapPB->GetInt( kBmpExportHeight ); if( bd.maxDimension < expHt ) bd.maxDimension = expHt; int clipID = 0, w; for( clipID = 0, w = bi->Width(); w > bd.maxDimension; w >>= 1, clipID++ ); // Do the UV gen (before we do texture, since it could modify the bitmapData struct) IProcessUVGen( layer, plasmaLayer, &bd, preserveUVOffset ); // Create the texture. If it works, assign it to the layer if( ( plasmaLayer = IAssignTexture( &bd, maxNode, plasmaLayer, upperLayer, clipID ) ) == nil ) return nil; // All done! return (plLayerInterface *)plasmaLayer; hsGuardEnd; }
hsVertexShader::~hsVertexShader() { hsGuardBegin("hsVertexShader::~hsVertexShader"); hsGuardEnd; }