Dynamic Skins and Material Swap Issue
by game4Rest · in Torque 3D Professional · 10/30/2009 (11:20 pm) · 26 replies
I started discussion on this topic from here. But to catch with the changes, and as a response to a request, I decided to surmarize what I've been doing and ask some help.
Before I go any further, I'd like to make it clear that this worked OK just until T3D beta 4 release.Currently, according to the material instance's vertext format, it gives me different assertFatal messages.
In the TSMaterialList::setMaterial that I'm going to add below, when I chose to init matInst like this,
matInst->init(features, getGFXVertexFormat<GFXVertexPNT>()), it says that "Not enough room in the buffer for this data!".
But when I initilize it like this way, matInst->init(features, getGFXVertexFormat<GFXVertexPTTT>()),
it says that "Something went bad with ShaderGen. The normal should be already defined.".
If I comment out those assertFatal lines, I can see that skins are changed. But when I quit the game, as we can expect, it crashes my game hard.
It seems like it has something to do with shader thing. But I don't have enough knowledge about it. So anyone please let me know the cause of this problem and shed some light on me?
Thanks in advance.
Here goes code changes that I made to make original resource work in T3D 1.0.
In the source/ts/tsShapeInstance.h, after
And after
add this.
Next, at the end of source/ts/tsShapeInstance.cpp,
add this,
#ifndef _CUSTOMMATERIAL_H_
#include "materials/customMaterialDefinition.h"
#endif
//end:
[/code]
Still in the same file,after
Now let's move to the next file source/ts/tsMaterialList.cpp.
At first, add this line.
And then, add this problematic method.
In the source/T3D/shapeBase.h.
add this.
After
Add this,
Still in the same file, after
We're getting close to the end. Let's move to the source/T3D/shapeBase.cpp.
First of all, add this in the destructor of ShapeBase(ShapeBase::~ShapeBase()).
From now, we have to be cautious to make it work correctly.
Find the these lines in the packUpdate.
And find these lines.
In the same if clause, after
In the unpackUpdate, after
Add this.
At the end of file and these.
Now, open up file source/materials/materialList.h.
Find the member variable
It is protected. Move it to [bold]public[/bold].
Next, in the source/materials/materialDefinition.h.
After
Now, let's move to the correspondent source/materials/materialDefinition.cpp.
At the end of the file, add this.
We're almost at the end. Let's open up the file source/materials/customMaterialDefinition.h.
Add this
Finally, just one to add. Let's open up source/materials/customMaterialDefinition.cpp.
After
Add this.
That's all.
Before I go any further, I'd like to make it clear that this worked OK just until T3D beta 4 release.Currently, according to the material instance's vertext format, it gives me different assertFatal messages.
In the TSMaterialList::setMaterial that I'm going to add below, when I chose to init matInst like this,
matInst->init(features, getGFXVertexFormat<GFXVertexPNT>()), it says that "Not enough room in the buffer for this data!".
But when I initilize it like this way, matInst->init(features, getGFXVertexFormat<GFXVertexPTTT>()),
it says that "Something went bad with ShaderGen. The normal should be already defined.".
If I comment out those assertFatal lines, I can see that skins are changed. But when I quit the game, as we can expect, it crashes my game hard.
It seems like it has something to do with shader thing. But I don't have enough knowledge about it. So anyone please let me know the cause of this problem and shed some light on me?
Thanks in advance.
Here goes code changes that I made to make original resource work in T3D 1.0.
In the source/ts/tsShapeInstance.h, after
class SceneState;add this.
//HJ: dynamic skins and material swap
class DynamicSkinData
{
public :
Vector<StringTableEntry> mTextures; // texture layers to blend together
StringTableEntry mMaterialName;
StringTableEntry mSkinTag;
};
//end:And after
void reSkin( String newBaseName, String oldBaseName = String::EmptyString );
add this.
//HJ: dynamic skin and material swap void SetDynamicSkin(DynamicSkinData* data); //end:
Next, at the end of source/ts/tsShapeInstance.cpp,
add this,
//HJ: dynamic skins and material swap
void TSShapeInstance::SetDynamicSkin(DynamicSkinData* data)
{
//First, check if the skin tag(materialName) exsits in our matInstance list.
//if it doesn't we don't do anything as this is incorrect skin data.
//(can't replace a skin we don't have)
TSMaterialList* pMatList = getMaterialList();
S32 foundMatInstIndex = -1;
for(S32 j=0; j < pMatList->mMaterialNames.size(); j++)
{
const char* pName = pMatList->mMaterialNames[j];
if(pName == NULL)
continue;
if(0==dStricmp(pName, data->mSkinTag))
{
foundMatInstIndex = j;
break;
}
}
if(-1 == foundMatInstIndex)
return;
//Now check if the material mapped to this skin tag matches the one we want to map to it.
//if it does, then our work is already done and we can simply return
BaseMatInstance* matInst = pMatList->getMaterialInst(foundMatInstIndex);
Material* currentMat = NULL;
if (matInst) {
currentMat = dynamic_cast<Material*>(matInst->getMaterial());
}
Material *mat = dynamic_cast<Material*>( Sim::findObject(data->mMaterialName) );
if(mat)
{
//it's already mapped at the current material
if(mat == currentMat)
return;
//The material already exists. so lets just map it to this matInst/skin tag slot
pMatList->setMaterial(foundMatInstIndex, mat);
}
else
{
//Oh dear, the material doesn't exist. So we have to create it then map it to the matInst/skin
//tag slot.
//the trick to creating a new material is that we are going to copy the details of a
//"Template" material. The material we choose to copy is based on how many textures we are blending.
//If 3, then we choose the material that is set up to blend 3 textures, etc. That way designers can
//control EXACTLY how these materials operates without needing to recompile code.
S32 maxNumTextures = Con::getIntVariable("$pref::DynamicSkins::MaxBlendedTextures");
//Clamp the number of textures, for sanity sake
S32 numBlendedTextures = data->mTextures.size();
if(numBlendedTextures > maxNumTextures)
numBlendedTextures = maxNumTextures;
//Read the name of the desired material template from prefs
char materialTemplate[512];
dSprintf(materialTemplate, sizeof(materialTemplate), "$pref::DynamicSkins::MaterialTemplate_%d", numBlendedTextures);
const char* templateName = NULL;
templateName = Con::getVariable(materialTemplate);
//if we couldn't read the name, return
if(!templateName)
return;
//We're going for custom materials here. If players want normal materials that option will need to
//be added in code.
CustomMaterial* templateMat = dynamic_cast<CustomMaterial*>(Sim::findObject(templateName));
if(!templateMat)
return;
//We found it, so let's copy it
CustomMaterial* newMat = new CustomMaterial();
*newMat = *templateMat;
//Now change the variables we want on our copy.
newMat->assignName(data->mMaterialName);
//don't make the "mapTo" equal to the skin tag. We don't want all objects which have a "Head" texture(skin tag)
//using our dynamic material for instance. Then ALL of them would have the same material as "Head"
newMat->mMapTo = StringTable->insert(data->mMaterialName);
//replace textures
for(S32 i=0; i< data->mTextures.size(); i++)
newMat->mTexFilename[i] = data->mTextures[i];
AssertFatal(newMat->registerObject(), "Unable to register dynamic material!");
Sim::getRootGroup()->addObject(newMat);
pMatList->setMaterial(foundMatInstIndex, newMat);
}
}
Now open up file source/ts/tsShape.h.
Add this.
[code]
//HJ: dynamic skin and material swap
#ifndef _MATERIAL_H_
#include "materials/materialDefinition.h"
#endif #ifndef _CUSTOMMATERIAL_H_
#include "materials/customMaterialDefinition.h"
#endif
//end:
[/code]
Still in the same file,after
void push_back(const char * name, U32 flags, Material* mat);add this.
//HJ: dynamic skins and material swap bool setMaterial(U32 index, Material* newMat); //end:
Now let's move to the next file source/ts/tsMaterialList.cpp.
At first, add this line.
#include "materials/materialFeatureTypes.h" //HJ: beta 5. dynamic skins and material swap
And then, add this problematic method.
//HJ: dynamic skins and material swap
bool TSMaterialList::setMaterial(U32 index, Material* newMat)
{
if (index < 0 || index > mMaterials.size()) {
return false;
}
if ( newMat ) {
if (mMatInstList[index]->getMaterial() == newMat) {
return true;
}
// dump the old mat instance
if (mMatInstList[index]) {
delete mMatInstList[index];
}
mMatInstList[index] = NULL;
// change texture
CustomMaterial* cust = dynamic_cast<CustomMaterial*>(newMat);
String texPath;
if (cust) {
texPath = cust->mTexFilename[0];
} else{
texPath = newMat->mBaseTexFilename[0];
}
GFXTexHandle tex = GFXTexHandle(texPath, &GFXDefaultStaticDiffuseProfile, avar("%s() - NA (line %d)", __FUNCTION__, __LINE__));
if (!tex.isValid()) {
return false;
}
// change texture
mMaterials[index] = tex;
BaseMatInstance *matInst = newMat->createMatInstance();
mMatInstList[index] = matInst;
// GFX2_RENDER_MERGE
//HJ: changed from original to work with T3D
//fd.features[MFT_RTLighting] = true; //beta 5: commented out by deepscratch's solution
FeatureSet features = MATMGR->getDefaultFeatures();
//GFXVertexPNT *tsVertex = NULL;
features.addFeature( MFT_VertTransform );
features.addFeature( MFT_DiffuseMap );
features.addFeature( MFT_RTLighting);
features.addFeature(MFT_NormalMap);
features.addFeature( MFT_OverlayMap );
features.addFeature( MFT_DetailMap );
features.addFeature( MFT_DiffuseColor );
features.addFeature( MFT_ColorMultiply );
features.addFeature( MFT_AlphaTest );
features.addFeature( MFT_IsTranslucent );
//MaterialFeatureData fd;
//fd.features = features;
//fd.materialFeatures = features;
matInst->init(features, matInst->getVertexFormat());// getGFXVertexFormat<GFXVertexPTTT>() );
//end:
}
return true;
}
//end:I think the code right above is causing the problem that I have. But anyway, let's move to the next file.In the source/T3D/shapeBase.h.
add this.
//HJ: dynamic skins and material swap #ifndef _TSSHAPEINSTANCE_H_ #include "ts/tsShapeinstance.h" #endif //end: After this, [code] friend void physicalZoneFind(SceneObject*, void*);Add these.
//HJ: dynamic skins and material swap protected : Vector<DynamicSkinData> mDynamicSkins; void BuildDynamicSkins(); void ClearDynamicSkins(); //end:
After
SoundMaskN = Parent::NextFreeMask << 9,
Add this,
DynamicSkinMask = Parent::NextFreeMask << 10, //HJ: dynamic skins and material swap
Still in the same file, after
const char* getSkinName(); /// @}Add these methods.
//HJ: dyanmic skin and material swap void UpdateDynamicSkins(); bool AddDynamicSkinLayerTexture(const char* skinTag, const char* texture, const char* matName); bool ResetDynamicSkin(const char* skinTag, const char* texture, const char* matName); const char* getMeshTexture(StringTableEntry mesh); //HJ: get the texture name on the specified mesh. //end:
We're getting close to the end. Let's move to the source/T3D/shapeBase.cpp.
First of all, add this in the destructor of ShapeBase(ShapeBase::~ShapeBase()).
//HJ: Dynamic skins and material swap // make sure list cleaned up ClearDynamicSkins(); //end:
From now, we have to be cautious to make it work correctly.
Find the these lines in the packUpdate.
// mask off images that aren't updated
for(i = 0; i < MaxMountedImages; i++)
if(!mMountedImageList[i].dataBlock)
mask &= ~(ImageMaskN << i);Right after them, add these.//HJ: dynamic skins and material swap if(mDynamicSkins.size() == 0) mask &= ~DynamicSkinMask; else mask |= DynamicSkinMask; //end:
And find these lines.
// Group some of the uncommon stuff together. if (stream->writeFlag(mask & (NameMask | ShieldMask | HideCloakMask | InvincibleMask | SkinMask....Change it like this.
// Group some of the uncommon stuff together. if (stream->writeFlag(mask & (NameMask | ShieldMask | HideCloakMask | InvincibleMask | SkinMask | DynamicSkinMask //HJ: dynamic skins and material swap | MeshHiddenMask )))
In the same if clause, after
if (stream->writeFlag(mask & InvincibleMask)) {
stream->write(mInvincibleTime);
stream->write(mInvincibleSpeed);
}Add this.//HJ: dynamic skin and material swap
if(stream->writeFlag(mask & DynamicSkinMask))
{
// the number of dynamic skins
stream->writeInt(mDynamicSkins.size(), 10);
for(S32 x = 0; x < mDynamicSkins.size(); x++)
{
stream->writeString(mDynamicSkins[x].mSkinTag);
stream->writeString(mDynamicSkins[x].mMaterialName);
stream->writeInt(mDynamicSkins[x].mTextures.size(), 10);
for(S32 y = 0; y < mDynamicSkins[x].mTextures.size(); y++)
{
stream->writeString(mDynamicSkins[x].mTextures[y]);
}
}
}
//end:In the unpackUpdate, after
if (stream->readFlag())
{
// InvincibleMask
F32 time, speed;
stream->read(&time);
stream->read(&speed);
setupInvincibleEffect(time, speed);
}Add this.
//HJ: dynamic skins and material swapping
if(stream->readFlag())
{
ClearDynamicSkins();
// the number of dynamic skins
S32 numDynamicSkins = stream->readInt(10);
for(S32 x = 0; x < numDynamicSkins; x++)
{
DynamicSkinData data;
mDynamicSkins.push_back(data);
S32 index = mDynamicSkins.size() -1;
mDynamicSkins[index].mSkinTag = stream->readSTString();
mDynamicSkins[index].mMaterialName = stream->readSTString();
// the number of dynamic skins
S32 numDynamicTextures = stream->readInt(10);
for(S32 y = 0; y < numDynamicTextures; y++)
{
mDynamicSkins[index].mTextures.push_back(stream->readSTString());
}
}
BuildDynamicSkins();
}
//end:At the end of file and these.
//HJ: dynamic skins and material swap
const char* ShapeBase::getMeshTexture(StringTableEntry mesh) //HJ: Not included in the original resource. added for my special needs
{
if(!mesh)
{
return NULL;
}
//At first, we need to find the given mesh.
for(int i=0;i<mShapeInstance->getShape()->objects.size();i++)
{
S32 idx = mShapeInstance->getShape()->objects[i].nameIndex;
if(idx>=0)
{
if(0==dStricmp(mesh, mShapeInstance->getShape()->getName(idx))) //Found the mesh
{
TSMesh* iMesh = mShapeInstance->mMeshObjects[i].getMesh(0);
U32 material= iMesh->primitives[0].matIndex & TSDrawPrimitive::MaterialMask;
if(iMesh->primitives[0].matIndex & TSDrawPrimitive::NoMaterial)
{
Con::errorf("No material on this mesh");
return NULL;
}
else
{
TSMaterialList* materials = mShapeInstance->getShape()->materialList;
const char* matName = materials->getMaterialName(material);
return matName;
}
}
}
}
return NULL;
}
ConsoleMethod( ShapeBase, getMeshTexture, const char*, 3, 3, "(string meshname)")
{
return object->getMeshTexture(argv[2]);
}
void ShapeBase::BuildDynamicSkins()
{
for(S32 i = 0; i < mDynamicSkins.size(); i ++)
mShapeInstance->SetDynamicSkin( &mDynamicSkins[i]);
}
void ShapeBase::ClearDynamicSkins()
{
for(S32 i = 0; i < mDynamicSkins.size(); i++)
mDynamicSkins[i].mTextures.clear();
mDynamicSkins.clear();
}
void ShapeBase::UpdateDynamicSkins()
{
setMaskBits(DynamicSkinMask);
}
ConsoleMethod( ShapeBase, UpdateDynamicSkins, void, 2, 2, "")
{
object->UpdateDynamicSkins();
}
bool ShapeBase::AddDynamicSkinLayerTexture(const char* skinTag, const char* texture, const char* matName)
{
// for sanitys sake, lets prevent scripters from going crazy with skin layers.
if( mDynamicSkins.size() >= CustomMaterial::MAX_TEX_PER_PASS )
{
Con::errorf("AddDynamicSkinLayerTexture(): Max number of textures reached! (%d)", mDynamicSkins.size());
return false;
}
bool found = false;
for(S32 i = 0; i < mDynamicSkins.size(); i ++)
{
if(0 == dStricmp(mDynamicSkins[i].mSkinTag, skinTag))
{
found = true;
mDynamicSkins[i].mTextures.push_back( StringTable->insert(texture) );
mDynamicSkins[i].mMaterialName = StringTable->insert(matName);
}
}
if(!found)
{
DynamicSkinData data;
mDynamicSkins.push_back(data);
S32 index = mDynamicSkins.size() - 1;
mDynamicSkins[index].mTextures.clear();// redundant but lets just make sure.
mDynamicSkins[index].mTextures.push_back( StringTable->insert(texture) );
mDynamicSkins[index].mSkinTag = StringTable->insert(skinTag);
mDynamicSkins[index].mMaterialName = StringTable->insert(matName);
}
return true;
}
//--------------------------------------------------------------------------------------------------------
ConsoleMethod( ShapeBase, AddDynamicSkinLayerTexture, bool, 5, 5, "(string skinTag, string texture, string materialName)")
{
return object->AddDynamicSkinLayerTexture(argv[2],argv[3],argv[4]);
}
//--------------------------------------------------------------------------------------------------------
bool ShapeBase::ResetDynamicSkin(const char* skinTag, const char* texture, const char* matName)
{
if(!texture || !skinTag || !matName)
return false;
bool found = false;
for(S32 i = 0; i < mDynamicSkins.size(); i ++)
{
if(0 == dStricmp(mDynamicSkins[i].mSkinTag, skinTag))
{
found = true;
mDynamicSkins[i].mTextures.clear();
mDynamicSkins[i].mTextures.push_back( StringTable->insert(texture) );
mDynamicSkins[i].mMaterialName = StringTable->insert(matName);
}
}
if(!found)
{
DynamicSkinData data;
mDynamicSkins.push_back(data);
S32 index = mDynamicSkins.size() - 1;
mDynamicSkins[index].mTextures.clear();// redundant but lets just make sure.
mDynamicSkins[index].mTextures.push_back( StringTable->insert(texture) );
mDynamicSkins[index].mSkinTag = StringTable->insert(skinTag);
mDynamicSkins[index].mMaterialName = StringTable->insert(matName);
}
return true;
}
//--------------------------------------------------------------------------------------------------------
ConsoleMethod( ShapeBase, ResetDynamicSkin, bool, 5, 5, "(string skinTag, string texture, string materialName)")
{
return object->ResetDynamicSkin(argv[2], argv[3], argv[4]);
}
//end:Now, open up file source/materials/materialList.h.
Find the member variable
Vector<String> mMaterialNames;.
It is protected. Move it to [bold]public[/bold].
Next, in the source/materials/materialDefinition.h.
After
static void initPersistFields();Add this.
//HJ: dynamic skins and material swap Material &operator=(const Material &Material); //end:
Now, let's move to the correspondent source/materials/materialDefinition.cpp.
At the end of the file, add this.
//HJ: dynamic skins and material swap
Material & Material::operator =(const Material &material)
{
// tedious, but want to avoid copying simobject data, which a straight memcopy would do.
// if you do that you get the simobject ID and then it complains when you try to register it.
for (S32 i = 0; i < MAX_STAGES; i++) {
mBaseTexFilename[i] = material.mBaseTexFilename[i];
mDetailTexFilename[i] = material.mDetailTexFilename[i]; //HJ: mDetailFilename>>>mDetailTexFilename
mBumpTexFilename[i] = material.mBumpTexFilename[i]; //HJ: mBumpFileName>>>mBumpTexFilename
mEnvTexFilename[i] = material.mEnvTexFilename[i]; //HJ: mEnvFileName>>>mEnvTexFilename
mStages[i] = material.mStages[i];
mDiffuse[i] = material.mDiffuse[i];
mSpecular[i] = material.mSpecular[i];
mSpecularPower[i] = material.mSpecularPower[i];
mPixelSpecular[i] = material.mPixelSpecular[i];
//mVertexSpecular[i] = material.mVertexSpecular[i]; //HJ: commented out. deepscratch
mExposure[i] = material.mExposure[i];
mAnimFlags[i] = material.mAnimFlags[i];
mScrollDir[i] = material.mScrollDir[i];
mScrollSpeed[i] = material.mScrollSpeed[i];
mScrollOffset[i] = material.mScrollOffset[i];
mRotSpeed[i] = material.mRotSpeed[i];
mRotPivotOffset[i] = material.mRotPivotOffset[i];
mRotPos[i] = material.mRotPos[i];
mWavePos[i] = material.mWavePos[i];
mWaveFreq[i] = material.mWaveFreq[i];
mWaveAmp[i] = material.mWaveAmp[i];
mWaveType[i] = material.mWaveType[i];
mSeqFramePerSec[i] = material.mSeqFramePerSec[i];
mSeqSegSize[i] = material.mSeqSegSize[i];
mGlow[i] = material.mGlow[i];
mEmissive[i] = material.mEmissive[i];
mColorMultiply[i] = material.mColorMultiply[i];
}
mDoubleSided = material.isDoubleSided();
mCubemapName = material.mCubemapName;
mCubemapData = material.mCubemapData;
mDynamicCubemap = material.mDynamicCubemap;
mTranslucent = material.isTranslucent();
mTranslucentBlendOp = material.mTranslucentBlendOp;
mTranslucentZWrite = material.mTranslucentZWrite;
mAlphaTest = material.mAlphaTest;
mAlphaRef = material.mAlphaRef;
mPlanarReflection = material.mPlanarReflection;
mMapTo = material.mMapTo;
mIsIFL = material.isIFL();
mPath = material.getPath();
return *this;
}
//end:We're almost at the end. Let's open up the file source/materials/customMaterialDefinition.h.
Add this
//HJ: dynamic skins and material swap CustomMaterial &operator=( const CustomMaterial &Material); //end:just before this line.
DECLARE_CONOBJECT(CustomMaterial);
Finally, just one to add. Let's open up source/materials/customMaterialDefinition.cpp.
After
void CustomMaterial::onRemove().
Add this.
//HJ: dynamic skins and material swap
CustomMaterial & CustomMaterial::operator =(const CustomMaterial &material) {
Parent::operator =(material);
// custom material copy
for (S32 i = 0; i < MAX_TEX_PER_PASS; i++) {
mTexFilename[i] = material.mTexFilename[i];
mFlags[i] = material.mFlags[i];
}
if (NULL == material.mFallback) {
mFallback = NULL;
} else{
*mFallback = *material.mFallback;
}
//HJ: no need this
/*
if (NULL == material.mDynamicLightingMaterial) {
mDynamicLightingMaterial = NULL;
} else{
mDynamicLightingMaterial = material.mDynamicLightingMaterial;
}
if (NULL == material.mDynamicLightingMaskMaterial) {
mDynamicLightingMaskMaterial = NULL;
} else{
mDynamicLightingMaskMaterial = material.mDynamicLightingMaskMaterial;
}
*/
//end:
mVersion = material.mVersion;
mRefract = material.mRefract;
mMaxTex = material.mMaxTex;
ShaderData* sd = static_cast<ShaderData*>(Sim::findObject(material.mShaderDataName));
if ( sd ) {
mShaderData = sd;
}
mShaderDataName = material.mShaderDataName;
return *this;
}
//end:That's all.
About the author
Recent Threads
#2
That's the problem that I'm currently undergoing. Unfortunately, I cannot spend time at all on this as I'm too busy with another project these days. So, no progress has been made since I posted this.
But I promise to come back to this soon.
11/11/2009 (9:31 pm)
@Jeff,That's the problem that I'm currently undergoing. Unfortunately, I cannot spend time at all on this as I'm too busy with another project these days. So, no progress has been made since I posted this.
But I promise to come back to this soon.
#3
Implement of this code is ok on 1.0.1
No issue on Exit.
But I'm not able to get it working.
texture[X] = "$fog"; is not recognized in my custom material.
when I comment it, I crash in U32 GFXVertexFormat::getTexCoordCount() const function.
Any ideas?
thanks,
01/10/2010 (3:55 pm)
Hi,Implement of this code is ok on 1.0.1
No issue on Exit.
But I'm not able to get it working.
texture[X] = "$fog"; is not recognized in my custom material.
when I comment it, I crash in U32 GFXVertexFormat::getTexCoordCount() const function.
Any ideas?
thanks,
#4
The issue with...
... is that the vertex format can change on the TSShape based on what data was found on the DTS/DAE file. Try getting the vertex format from the TSShape::getVertexFormat() method.
01/10/2010 (11:38 pm)
@game4Rest -The issue with...
matInst->init(features, getGFXVertexFormat<GFXVertexPTTT>())
... is that the vertex format can change on the TSShape based on what data was found on the DTS/DAE file. Try getting the vertex format from the TSShape::getVertexFormat() method.
#5
I implement your change by calling the getVertexFormat in tssahpeinstance and sending to setmaterial function.
Now I have the message:
"Not enough room in the buffer for this data!".
Like game4rest
I will look deeper if I can find any clue on this... but your input can be helpfull.
I'm working on T3D 1.0.1
By the way, when I test the custom material alone, this is working fine.
01/12/2010 (3:51 am)
HI tom,I implement your change by calling the getVertexFormat in tssahpeinstance and sending to setmaterial function.
Now I have the message:
"Not enough room in the buffer for this data!".
Like game4rest
I will look deeper if I can find any clue on this... but your input can be helpfull.
I'm working on T3D 1.0.1
By the way, when I test the custom material alone, this is working fine.
#6
02/24/2010 (4:39 pm)
Well, I had a chance to look deep inside the engine codes. And came to a conclusion that all the features that we need to customize our player's look have been there. T3D now has show/hide meshes features. And to change players' texture material, T3D now has 4 layers system, which can be found in the material editor. The only thing for us is to enjoy those features.
#7
I'm not sure to understand how you manage customization with the current function. You have 4 layer, this is clearly helpful to have different diffuse/normal map to manage customization like Scars, tatoo & so on.
But how will you manage the changes? I mean on Layer 2 you will set Scars1 and you want to switch to Scars2. If you do that in the current material, all player will have Scars2.
So you need to have a unique material, and the "hard" part will be to properly create a cloned material.
Or maybe we can use IFL? but I don't know yet really how it's works.
If you can share the design you will put in place I will be very interesting.
Thanks,
02/24/2010 (11:44 pm)
Hi,I'm not sure to understand how you manage customization with the current function. You have 4 layer, this is clearly helpful to have different diffuse/normal map to manage customization like Scars, tatoo & so on.
But how will you manage the changes? I mean on Layer 2 you will set Scars1 and you want to switch to Scars2. If you do that in the current material, all player will have Scars2.
So you need to have a unique material, and the "hard" part will be to properly create a cloned material.
Or maybe we can use IFL? but I don't know yet really how it's works.
If you can share the design you will put in place I will be very interesting.
Thanks,
#8
It's not going to be so difficult. It is only a matter of naming convention and protocol between server and client. As a hint, look at this code example on server side.
It explains how to blend face textures together. Maybe you can start working based on this or you can wait until I come out with scrip resource on this.
02/26/2010 (8:52 pm)
@elvince,It's not going to be so difficult. It is only a matter of naming convention and protocol between server and client. As a hint, look at this code example on server side.
function GameConnection::updateFaceSkins(%this, %applyPart, %diffuse)
{
%currentMat = %this.currentMat;
%newMatName = "mat_face_" @ %diffuse;
if(%currentMat $= %newMatName)
return;
if(!isObject(%newMatName))
{
for(%i=0; %i < 4; %i++)
{
%texId = getSubStr(%diffuse,%i,1);
%tex[%i] = %this.getFaceTexture(%i, %texId);
}
singleton Material(%newMatName)
{
diffuseMap[0] = %tex[0];
diffuseMap[1] = %tex[1];
diffuseMap[2] = %tex[2];
diffuseMap[3] = %tex[3];
normalMap[0] = "art/shapes/actors/Gideon/head_n.png";
normalMap[1] = "";
specular[0] = "0.99 0.91 0.81 1";
specularPower[0] = "16";
pixelSpecular[0] = "0";
specularMap[0] = "art/shapes/actors/Gideon/head_s.png";
};
}
%player = %this.player;
%player.changeMaterial(%applyPart, %currentMat, %newMatName);
}
function GameConnection::getFaceTexture(%facePart, %texId)
{
%result="";
//Maybe we can save the texture info in DB, but for now
if(%facePart==0) //Eyes
{
if(%texId !$= "0")
%result = "art/shapes/actors/Gideon/face/eye" @ %texId;
}
if(%facePart==1) //Scar
{
if(%texId !$= "0")
%result = "art/shapes/actors/Gideon/face/scar" @ %texId;
}
if(%facePart==2) //Painting
{
if(%texId !$= "0")
%result = "art/shapes/actors/Gideon/face/img" @ %texId;
}
if(%facePart==3) //Mustache
{
if(%texId !$= "0")
%result = "art/shapes/actors/Gideon/face/mas" @ %texId;
}
return %result;
}It explains how to blend face textures together. Maybe you can start working based on this or you can wait until I come out with scrip resource on this.
#9
Look so simple compare to previous resources' implementation.
I will clearly start for this and compare to your resource at the end to see if I miss something or if what you will propose is better than my implementation :D
In term of texture size, I made some test and you can have different size on layer. I mean 512*512 for Face, 256*256 for a scar.
But I don't know at this end if I will save memory for the graphic card. I suspect that it will not be the case, as the shader will blend all those layer in 1, and I thing the biggest one.
In term of process, will it speed-up?
Thanks,
02/27/2010 (12:23 am)
You're right. It's pretty straight forward.Look so simple compare to previous resources' implementation.
I will clearly start for this and compare to your resource at the end to see if I miss something or if what you will propose is better than my implementation :D
In term of texture size, I made some test and you can have different size on layer. I mean 512*512 for Face, 256*256 for a scar.
But I don't know at this end if I will save memory for the graphic card. I suspect that it will not be the case, as the shader will blend all those layer in 1, and I thing the biggest one.
In term of process, will it speed-up?
Thanks,
#10
Need some help/testing?
For a Character selection screen, I'm not sure we can change the skin as we are not in a game and so you don't have a player, so not access to setskin and so on.
Any idea on this?
I looked at ObjectView and for the moment no skin function are available, so we might have to implement it.
Thanks,
03/07/2010 (11:56 pm)
I may start working on this for my game, any idea on when you will release a resource? Just to know if I jump in this part or I wait for your resource and start from it.Need some help/testing?
For a Character selection screen, I'm not sure we can change the skin as we are not in a game and so you don't have a player, so not access to setskin and so on.
Any idea on this?
I looked at ObjectView and for the moment no skin function are available, so we might have to implement it.
Thanks,
#11
Smaller texture may gain a little benefits in speed when loading and processing. As long as smaller texture guarantees enough quality, I believe that is better.
Maybe we can move and rotate textures without stretching, to locate it as we desire. But that will require additional time in adjusting. If that time can't give us enough benefits in performance, I think doing things just like now is not bad.
As for the progress for the resource, I already began. But as I can spend my time only after finishing my regular work, the progress is not steady and fast enough.
By now, I got rid of DB related things from my old code, finished camera movement, requests and answers for mesh and material changes between server and client. Even though I cannot guarantee, I expect I can test it next week.
03/08/2010 (7:20 am)
@elvince,Smaller texture may gain a little benefits in speed when loading and processing. As long as smaller texture guarantees enough quality, I believe that is better.
Maybe we can move and rotate textures without stretching, to locate it as we desire. But that will require additional time in adjusting. If that time can't give us enough benefits in performance, I think doing things just like now is not bad.
As for the progress for the resource, I already began. But as I can spend my time only after finishing my regular work, the progress is not steady and fast enough.
By now, I got rid of DB related things from my old code, finished camera movement, requests and answers for mesh and material changes between server and client. Even though I cannot guarantee, I expect I can test it next week.
#12
If you need help or feedback on your code before release plz tell me.
03/08/2010 (10:09 am)
It's clearly a good news and you have done a good part of the Job. I also only work on my game after regular work so 1week is pretty nothing. If you need help or feedback on your code before release plz tell me.
#13
Do you have any idea why is that so ?
Looking into the C++ code,changeMaterial is a console methods declared in InteriorInstance.cpp. So i guess %player is only inheriting from that class. Is it a part of the reason ?
Thanks a lot
03/17/2010 (9:30 pm)
@game4rest: I try your sample code for change player material, it worked when i play in local mode. But when i tried using Dedicated server, game crashes at "%player.changeMaterial();". And the game server can not be found any more (no connection).Do you have any idea why is that so ?
Looking into the C++ code,changeMaterial is a console methods declared in InteriorInstance.cpp. So i guess %player is only inheriting from that class. Is it a part of the reason ?
Thanks a lot
#14
I finished writing up character customization codes just yesterday. Now, I'm testing it. I'm going to test your issue too. But for now, I guess it is because the dedicated server cannot load the related textures when it tries to make new materials.
03/18/2010 (6:57 pm)
@Squall,I finished writing up character customization codes just yesterday. Now, I'm testing it. I'm going to test your issue too. But for now, I guess it is because the dedicated server cannot load the related textures when it tries to make new materials.
#15
03/20/2010 (10:21 am)
@game4Rest: thank for your reply, if there is any update regarding your testing, please let me know
#16
Before I come out with it to the public, I have to say this. "This cannot be a drag and drop and ready to go solution." This is because we have compleletly different character models, completely different textures on it. Still, I believe you'll save your time alot as I experienced all the possible problems instead of you and found solution for them.
03/21/2010 (5:54 pm)
I'm getting to the end. I just need two or three days to do additional test.Before I come out with it to the public, I have to say this. "This cannot be a drag and drop and ready to go solution." This is because we have compleletly different character models, completely different textures on it. Still, I believe you'll save your time alot as I experienced all the possible problems instead of you and found solution for them.
#17
I tested if mine supports network play. To tell you the result, I'm afraid to say this, but the changeMetrial method is not for network play. In other words, it doesn't send updated material change information to the clients connected. To make it work, I'm going to put my hands on engine codes. Before it, I will post the single play version.
03/24/2010 (3:10 am)
@Squall,I tested if mine supports network play. To tell you the result, I'm afraid to say this, but the changeMetrial method is not for network play. In other words, it doesn't send updated material change information to the clients connected. To make it work, I'm going to put my hands on engine codes. Before it, I will post the single play version.
#18
Depending of your implementation,for the network it might be just a question of sending the information across all client like chat message.
03/24/2010 (3:33 am)
Great update, I will be pleased to see the initial version.Depending of your implementation,for the network it might be just a question of sending the information across all client like chat message.
#19
The original resource uses the standard maskbits for replicating the changes over the network, it would probably be best to use the same method here.
03/24/2010 (4:45 am)
Sounds like your doing great work game4Rest.The original resource uses the standard maskbits for replicating the changes over the network, it would probably be best to use the same method here.
#20
I really appreciate your help, even with just single mode, it's already great work from you.
03/24/2010 (10:00 pm)
@game4rest: I really appreciate your help, even with just single mode, it's already great work from you.
Torque 3D Owner Jeff Kelsey
ArchieMD