/* * Author: Andrew Robberts * * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "effects/pseffectobjquad.h" #include "effects/pseffectanchor.h" #include "util/log.h" #include "util/pscssetup.h" psEffectObjQuad::psEffectObjQuad(iView * parentView) : psEffectObj(parentView) { meshControl.AttachNew(new MeshAnimControl(this)); } psEffectObjQuad::~psEffectObjQuad() { } bool psEffectObjQuad::Load(iDocumentNode *node) { // get the attributes name = ""; materialName = ""; xCells = 1; yCells = 1; csRef attribIter = node->GetAttributes(); while (attribIter->HasNext()) { csRef attr = attribIter->Next(); csString attrName = attr->GetName(); attrName.Downcase(); if (attrName == "name") name = attr->GetValue(); else if (attrName == "material") materialName = attr->GetValue(); else if (attrName == "xcells") xCells = attr->GetValueAsInt(); else if (attrName == "ycells") yCells = attr->GetValueAsInt(); } if (name == "") { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Attempting to create an effect obj with no name.\n"); return false; } if (materialName == "") { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Attempting to create an effect obj without a material.\n"); return false; } if (!psEffectObj::Load(node)) return false; return PostSetup(); } bool psEffectObjQuad::Render(const csVector3 &up) { static unsigned long nextUniqueID = 0; csString effectID = "effect_quad_"; effectID += nextUniqueID++; // create a mesh wrapper from the factory we just created mesh = engine->CreateMeshWrapper(meshFact, effectID.GetData()); // do the up vector objUp = up; csReversibleTransform rt; rt.LookAt(csVector3(up.x, up.z, up.y), csVector3(0,2,1)); matUp = rt.GetT2O(); matBase = matUp; // common flags mesh->GetFlags().Set(CS_ENTITY_NOHITBEAM); mesh->SetZBufMode(zFunc); mesh->SetRenderPriority(priority); // disable culling mesh->GetMeshObject()->GetObjectModel()->SetPolygonMeshViscull(0); // obj specific genState = SCF_QUERY_INTERFACE(mesh->GetMeshObject(), iGeneralMeshState); genState->SetLighting(false); if (mixmode != CS_FX_ALPHA) mesh->GetMeshObject()->SetMixMode(mixmode); // to check //genState->SetMixMode(mixmode); was not working with latest CS genState->SetAnimationControl((iGenMeshAnimationControl *)meshControl); // initialize the data we'll pass to the genmesh animation control vert[0].Set( 0.5f, 0, 0.5f); vert[1].Set(-0.5f, 0, 0.5f); vert[2].Set(-0.5f, 0, -0.5f); vert[3].Set( 0.5f, 0, -0.5f); for (int a=0; a<4; ++a) colour[a].Set(1, 1, 1); return true; } bool psEffectObjQuad::Update(csTicks elapsed) { if (!anchor || !anchor->IsReady()) // wait for anchor to be ready return true; if (!psEffectObj::Update(elapsed)) return false; int cell = 0; if (keyFrames->Length() > 0) { // COLOUR csVector3 lerpColour = LERP_VEC_KEY(KA_COLOUR); float lerpAlpha = LERP_KEY(KA_ALPHA); for (int a=0; a<4; ++a) colour[a].Set(lerpColour.x, lerpColour.y, lerpColour.z, lerpAlpha); // CELL cell = (int)keyFrames->Get(currKeyFrame)->actions[psEffectObjKeyFrame::KA_CELL]; } float u = (float)(cell % xCells) / (float)xCells; float v = (float)((int)(cell / yCells)) / (float)yCells; float width = 1.0f / (float)xCells; float height = 1.0f / (float)yCells; texel[0].Set(u+width, v); texel[1].Set(u, v); texel[2].Set(u, v+height); texel[3].Set(u+width, v+height); return true; } psEffectObj * psEffectObjQuad::Clone() const { psEffectObjQuad * newObj = new psEffectObjQuad(view); CloneBase(newObj); // quad specific newObj->xCells = xCells; newObj->yCells = yCells; return newObj; } bool psEffectObjQuad::PostSetup() { static unsigned int uniqueID = 0; csString facName = "effect_quad_fac_"; facName += uniqueID++; meshFact = engine->CreateMeshFactory ("crystalspace.mesh.object.genmesh", facName.GetData()); region->Add(meshFact->QueryObject()); // create the actual sprite3d data iMeshObjectFactory * fact = meshFact->GetMeshObjectFactory(); csRef facState = SCF_QUERY_INTERFACE(fact, iGeneralFactoryState); if (!facState) { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Couldn't create genmesh: %s\n", name.GetData()); return false; } // setup the material csRef mat = region->FindMaterial(materialName); if (!mat) { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Couldn't find effect material: %s\n", materialName.GetData()); return false; } fact->SetMaterialWrapper(mat); facState->SetVertexCount(4); // we have to set the vertices so that the quad actually gets rendered facState->GetVertices()[0].Set( 0.5f, 0, 0.5f); facState->GetVertices()[1].Set(-0.5f, 0, 0.5f); facState->GetVertices()[2].Set(-0.5f, 0, -0.5f); facState->GetVertices()[3].Set( 0.5f, 0, -0.5f); facState->GetNormals()[0].Set(0,1,0); facState->GetNormals()[1].Set(0,1,0); facState->GetNormals()[2].Set(0,1,0); facState->GetNormals()[3].Set(0,1,0); facState->SetTriangleCount(4); facState->GetTriangles()[0].Set(0, 2, 1); facState->GetTriangles()[1].Set(0, 2, 3); facState->GetTriangles()[2].Set(2, 0, 1); facState->GetTriangles()[3].Set(2, 0, 3); animLength = 10; if (keyFrames->Length() > 0) animLength += keyFrames->Get(keyFrames->Length()-1)->time; return true; } const csVector3 * psEffectObjQuad::MeshAnimControl::UpdateVertices(csTicks current, const csVector3 * verts, int num_verts, uint32 version_id) { return parent->vert; } const csVector2 * psEffectObjQuad::MeshAnimControl::UpdateTexels(csTicks current, const csVector2 * texels, int num_texels, uint32 version_id) { return parent->texel; } const csColor4 * psEffectObjQuad::MeshAnimControl::UpdateColors(csTicks current, const csColor4 * colors, int num_colors, uint32 version_id) { return parent->colour; }