/* * 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/pseffectobjspire.h" #include "effects/pseffectanchor.h" #include "util/log.h" #include "util/pscssetup.h" psEffectObjSpire::psEffectObjSpire(iView * parentView) : psEffectObj(parentView) { vert = 0; texel = 0; colour = 0; vertCount = 0; meshControl.AttachNew(new MeshAnimControl(this)); } psEffectObjSpire::~psEffectObjSpire() { delete [] vert; delete [] texel; delete [] colour; } bool psEffectObjSpire::Load(iDocumentNode *node) { // get the attributes name = ""; materialName = ""; shape = SPI_CIRCLE; segments = 5; 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 == "shape") { csString sshape = attr->GetValue(); sshape.Downcase(); if (sshape == "circle") shape = SPI_CIRCLE; else if (sshape == "asterix") shape = SPI_ASTERIX; else if (sshape == "star") shape = SPI_STAR; else if (sshape == "layered") shape = SPI_LAYERED; } else if (attrName == "segments") segments = 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 psEffectObjSpire::Render(const csVector3 &up) { static unsigned long nextUniqueID = 0; csString effectID = "effect_spire_"; 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); mesh->GetMeshObject()->SetColor(csColor(1,1,1)); // to check //genState->SetColor(csColor(1,1,1)); was not working with latest CS if (mixmode != CS_FX_ALPHA) mesh->GetMeshObject()->SetMixMode(mixmode); // to check //genState->SetMixMode(mixmode); was not working with latest CS genState->SetAnimationControl(meshControl); vert = new csVector3[vertCount]; texel = new csVector2[vertCount]; colour = new csColor4[vertCount]; for (int a=0; aIsReady()) // wait for anchor to be ready return true; if (!psEffectObj::Update(elapsed)) return false; //float scale = 1; float topScale = 1; float height = 1; float padding = 1; if (keyFrames->Length() > 0) { // COLOUR csVector3 lerpColour = LERP_VEC_KEY(KA_COLOUR); float lerpAlpha = LERP_KEY(KA_ALPHA); for (int a=0; ashape = shape; newObj->segments = segments; newObj->vertCount = vertCount; return newObj; } void psEffectObjSpire::CalculateData(int shape, int segments, csVector3 * verts, csVector2 * texels, float topScale, float height, float padding) { switch (shape) { case SPI_CIRCLE: for (int b=0; b<=segments; ++b) { float currAng = b * 2.0f*3.14159f / segments; float cosCurr = (float)cos(currAng); float sinCurr = (float)sin(currAng); // vertex data verts[b*2 ].Set(cosCurr * topScale, height, sinCurr * topScale); verts[b*2+1].Set(cosCurr, 0, sinCurr); // texture coordinates float u1 = (float)b / (float)segments; texels[b*2 ].Set(u1, 0.01f); texels[b*2+1].Set(u1, 0.99f); } break; case SPI_ASTERIX: for (int b=0; bCreateMeshFactory ("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); // 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); // ensure the minimum number of segments for the shape switch (shape) { case SPI_CIRCLE: segments = (segments >= 3 ? segments : 3); facState->SetVertexCount(2 * segments + 2); break; case SPI_ASTERIX: segments = (segments >= 3 ? segments : 3); facState->SetVertexCount(4 * segments); break; case SPI_STAR: segments = (segments >= 3 ? segments : 3); facState->SetVertexCount(6 * segments); break; case SPI_LAYERED: segments = (segments >= 1 ? segments : 1); facState->SetVertexCount(4 * segments); break; } vertCount = facState->GetVertexCount(); CalculateData(shape, segments, facState->GetVertices(), facState->GetTexels()); animLength = 10; if (keyFrames->Length() > 0) animLength += keyFrames->Get(keyFrames->Length()-1)->time; // create the tris switch (shape) { case SPI_CIRCLE: facState->SetTriangleCount(4*segments); for (int q=0; qGetTriangles()[q*4 ].Set(q*2, q*2+1, q*2+2); facState->GetTriangles()[q*4+1].Set(q*2+1, q*2+3, q*2+2); facState->GetTriangles()[q*4+2].Set(q*2, q*2+2, q*2+1); facState->GetTriangles()[q*4+3].Set(q*2+1, q*2+2, q*2+3); } break; case SPI_ASTERIX: facState->SetTriangleCount(4*segments); for (int q=0; qGetTriangles()[q*4 ].Set(q*4, q*4+2, q*4+1); facState->GetTriangles()[q*4+1].Set(q*4, q*4+2, q*4+3); facState->GetTriangles()[q*4+2].Set(q*4+2, q*4, q*4+1); facState->GetTriangles()[q*4+3].Set(q*4+2, q*4, q*4+3); } break; case SPI_STAR: facState->SetTriangleCount(8*segments); for (int q=0; qGetTriangles()[q*8 ].Set(q*8, q*8+1, q*8+3); facState->GetTriangles()[q*8+1].Set(q*8, q*8+1, q*8+4); facState->GetTriangles()[q*8+2].Set(q*8+1, q*8+2, q*8+4); facState->GetTriangles()[q*8+3].Set(q*8+1, q*8+2, q*8+5); facState->GetTriangles()[q*8+4].Set(q*8, q*8+3, q*8+1); facState->GetTriangles()[q*8+5].Set(q*8, q*8+4, q*8+1); facState->GetTriangles()[q*8+6].Set(q*8+1, q*8+4, q*8+2); facState->GetTriangles()[q*8+7].Set(q*8+1, q*8+5, q*8+2); } break; case SPI_LAYERED: facState->SetTriangleCount(4*segments); for (int q=0; qGetTriangles()[q*4 ].Set(q*4, q*4+2, q*4+1); facState->GetTriangles()[q*4+1].Set(q*4, q*4+2, q*4+3); facState->GetTriangles()[q*4+2].Set(q*4, q*4+4, q*4+1); facState->GetTriangles()[q*4+3].Set(q*4, q*4+4, q*4+3); } break; } return true; } const csVector3 * psEffectObjSpire::MeshAnimControl::UpdateVertices(csTicks current, const csVector3 * verts, int num_verts, uint32 version_id) { return parent->vert; } const csVector2 * psEffectObjSpire::MeshAnimControl::UpdateTexels(csTicks current, const csVector2 * texels, int num_texels, uint32 version_id) { return parent->texel; } const csColor4 * psEffectObjSpire::MeshAnimControl::UpdateColors(csTicks current, const csColor4 * colors, int num_colors, uint32 version_id) { return parent->colour; }