void ClientGameObjectManagerAddon::createSoldierNPC(Event_CreateSoldierNPC *pTrueEvent) { PEINFO("CharacterControl: GameObjectManagerAddon: Creating CreateSoldierNPC\n"); PE::Handle hSoldierNPC("SoldierNPC", sizeof(SoldierNPC)); SoldierNPC *pSoldierNPC = new(hSoldierNPC) SoldierNPC(*m_pContext, m_arena, hSoldierNPC, pTrueEvent); pSoldierNPC->addDefaultComponents(); // add the soldier as component to the ObjecManagerComponentAddon // all objects of this demo live in the ObjecManagerComponentAddon addComponent(hSoldierNPC); }
void ClientGameObjectManagerAddon::do_CREATE_WAYPOINT(PE::Events::Event *pEvt) { PEINFO("GameObjectManagerAddon::do_CREATE_WAYPOINT()\n"); assert(pEvt->isInstanceOf<Event_CREATE_WAYPOINT>()); Event_CREATE_WAYPOINT *pTrueEvent = (Event_CREATE_WAYPOINT*)(pEvt); PE::Handle hWayPoint("WayPoint", sizeof(WayPoint)); WayPoint *pWayPoint = new(hWayPoint) WayPoint(*m_pContext, m_arena, hWayPoint, pTrueEvent); pWayPoint->addDefaultComponents(); addComponent(hWayPoint); }
int Effect::l_SetSpeTechniqueReady(lua_State *luaVM) { #if APIABSTRACTION_D3D11 const char *techName = lua_tostring(luaVM, -1); Handle h = EffectManager::Instance()->getEffectHandle(techName); if (h.isValid()) { Effect *pEffect = h.getObject<Effect>(); pEffect->setSpeShaderSatus(true); } else { PEINFO("PE: ERROR: l_setSpeTechniqueReady() : provided technique does not exist!"); } lua_pop(luaVM, 1); #else assert(!"Not Implemented"); #endif return 0; }
static bool loadFragmentShader_PSVita(PE::GameContext &ctx, const char *filename, const char *name, PEAlphaBlendState *pBlendState, const SceGxmProgram *gxmProgram, const SceGxmProgram *gxmVertexProgram, SceGxmShaderPatcherId &out_programId, SceGxmFragmentProgram * &out_program ) { PEString::generatePathname(ctx, filename, "Default", "GPUPrograms", PEString::s_buf, PEString::BUF_SIZE); PEINFO("PE: PROGRESS: loading shader: %s from %s\n", name, PEString::s_buf); if (strcmp("main", name)) { assert(!"Only shaders programs with name \"main()\" are supported"); } PSVitaRenderer *pPSVitaRenderer = static_cast<PSVitaRenderer *>(ctx.getGPUScreen()); SceGxmErrorCode err = sceGxmShaderPatcherRegisterProgram(pPSVitaRenderer->m_shaderPatcher, gxmProgram, &out_programId); PEASSERT(err == SCE_OK, "Error creating shader patcher id"); SceGxmFragmentProgram *clearFragmentProgram = NULL; err = sceGxmShaderPatcherCreateFragmentProgram( pPSVitaRenderer->m_shaderPatcher, out_programId, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, MSAA_MODE, pBlendState->m_blendEnabled ? &pBlendState->m_blendInfo : NULL, gxmVertexProgram, &out_program); checkErrCode(err); PEASSERT(err == SCE_OK, "Error creating shader"); return true; }
void AnimSetBufferGPU::releaseGPUBuffer() { #if !PE_API_IS_D3D11 PEINFO("Not implemented!"); #endif }
// Reads the specified buffer from file void IndexBufferCPU::ReadIndexBuffer(const char *filename, const char *package) { m_minVertexIndex = 0x7FFFFFFF; m_maxVertexIndex = 0x80000000; strcpy(&m_dbgName[0], filename); PEString::generatePathname(*m_pContext, filename, package, "IndexBuffers", PEString::s_buf, PEString::BUF_SIZE); // Path is now a full path to the file with the filename itself FileReader f(PEString::s_buf); char line[256]; f.nextNonEmptyLine(line, 255); // TODO : make sure it is "INDEX_BUFFER" f.nextInt32(m_verticesPerPolygon); PEASSERT(m_verticesPerPolygon == 3, "Non triangle index buffers not supported when reading from disk!"); m_verticesPerPolygon = 3; m_primitiveTopology = PEPrimitveTopology_TRIANGLES; PrimitiveTypes::Int32 totalPolygonCount; f.nextInt32(totalPolygonCount); PrimitiveTypes::Int32 numberOfSets; f.nextInt32(numberOfSets); m_indexRanges.reset(numberOfSets); m_vertsPerFacePerRange.reset(numberOfSets); // stores number of vertices in face for every range m_values.reset(totalPolygonCount * m_verticesPerPolygon); // verticesPerPolygon UInt16 per vertex //dbg //PrimitiveTypes::Int32 memoryAddress = (PrimitiveTypes::Int32)m_values.m_dataHandle.getObject(); PrimitiveTypes::Int32 curVertexIndexIndex = 0; // tracks number of vertices processed so far // Read all values for (int i = 0; i < numberOfSets; i++)// TODO : Right now, no distinction is really made once the different sets are loaded in { m_vertsPerFacePerRange.add(m_verticesPerPolygon); PrimitiveTypes::Int32 boneSegmentCount; f.nextInt32(boneSegmentCount); IndexRange range(*m_pContext, m_arena); // stores range of indices for material index range. it also stores separation bone segments range.m_start = curVertexIndexIndex; range.m_boneSegments.reset(boneSegmentCount); int minIndexInRange = 0x7FFFFFFF; int maxIndexInRange = 0x80000000; PrimitiveTypes::UInt32 rangePolygonCount = 0; for (int i = 0; i < boneSegmentCount; i++) { range.m_boneSegments.add(IndexRange::BoneSegment(*m_pContext, m_arena)); IndexRange::BoneSegment &boneSegment = range.m_boneSegments[range.m_boneSegments.m_size-1]; PrimitiveTypes::Int32 boneCountInSegment; f.nextInt32(boneCountInSegment); // number of bones used in the segment boneSegment.m_boneSegmentBones.reset(boneCountInSegment); boneSegment.m_start = curVertexIndexIndex; for (PrimitiveTypes::UInt32 ib = 0; ib < (PrimitiveTypes::UInt32)(boneCountInSegment); ib++) { PrimitiveTypes::Int32 boneId; f.nextInt32(boneId); // number of bones used in the segment boneSegment.m_boneSegmentBones.add(boneId); } PrimitiveTypes::Int32 boneSegmentPolygonCount; f.nextInt32(boneSegmentPolygonCount); if (boneSegmentPolygonCount > 0) { boneSegment.m_end = boneSegment.m_start + boneSegmentPolygonCount * m_verticesPerPolygon - 1; rangePolygonCount += boneSegmentPolygonCount; curVertexIndexIndex += boneSegmentPolygonCount * m_verticesPerPolygon; PrimitiveTypes::Int32 val; for (int j = 0; j < boneSegmentPolygonCount * m_verticesPerPolygon; j++) { f.nextInt32(val); m_values.add(val); if (val > maxIndexInRange) maxIndexInRange = val; if (val < minIndexInRange) minIndexInRange = val; } } else { // this bone segment has no polygons in it, so we need to skip it boneSegment.m_boneSegmentBones.reset(0); // make sure we release this memory, but there still is a spot in the array that will not be used i--; boneSegmentCount--; range.m_boneSegments.remove(range.m_boneSegments.m_size-1); PEINFO("PE: Warning: Empty bone segment was found in index buffer. This will lead to extra memory allocated for the segment that never is added"); } } range.m_end = range.m_start + rangePolygonCount * m_verticesPerPolygon - 1; range.m_minVertIndex = minIndexInRange; range.m_maxVertIndex = maxIndexInRange; if (maxIndexInRange > m_maxVertexIndex) m_maxVertexIndex = maxIndexInRange; if (minIndexInRange < m_minVertexIndex) m_minVertexIndex = minIndexInRange; if (range.m_boneSegments.m_size == 1 && range.m_boneSegments[0].m_boneSegmentBones.m_size == 0) { // we have only one bone segment in range and the are 0 bones - this is a static mesh case // we dont need to store list of bone segments then. the range will be drawn range.m_boneSegments.reset(0); } #if APIABSTRACTION_D3D11 // we are going to combine all bone segments into 1 if (range.m_boneSegments.m_size > 1) { IndexRange::BoneSegment &boneSegment = range.m_boneSegments[0]; boneSegment.m_start = range.m_start; boneSegment.m_end = range.m_end; range.m_boneSegments.m_size = 1; //release other bone segments for (int is = 1; is < range.m_boneSegments.m_size; ++is) { IndexRange::BoneSegment &boneSegment = range.m_boneSegments[is]; boneSegment.m_boneSegmentBones.reset(0); } } #endif if (range.m_end >= range.m_start) { m_indexRanges.add(range); } else { PEINFO("PE: Warning: Empty Index range (material) found. This will lead to extra memory allocated for the material taht is never used.\n"); range.m_boneSegments.reset(0); // we release this memory but there is still one spot in the array for unused index range } } }
// Reads the animation from file void AnimationCPU::ReadAnimation(FileReader &f, SkeletonCPU &skel, float positionFactor, int version) { // Read animation f.nextNonEmptyLine(m_name, 128); // Partial body animation PrimitiveTypes::Int32 numJoints; f.nextInt32(numJoints); m_numJoints = numJoints; m_startJoint = 0; // todo: partial body animation shouldnt be controlled by range, but rather by retargetting array that we have below m_endJoint = m_numJoints-1; int targetSkelNumJoints = skel.m_numJoints; int animJointToSkelJoint[512]; PEASSERT(m_endJoint < 512, "not enough buffer to retarget, increase 512"); int jointUsage[512]; memset(&jointUsage[0], 0, sizeof(jointUsage)); PEASSERT(skel.m_numJoints < 512, "need to increase buffer"); if (version < 3) { // no retargetting for (int i = 0; i < 512; ++i) animJointToSkelJoint[i] = i; } else { for (int i = 0; i < 512; ++i) animJointToSkelJoint[i] = -1; // fill in based on names of joints for (int iSrcJoint = 0; iSrcJoint < m_numJoints; ++iSrcJoint) { char fullJointName[256]; f.nextNonEmptyLine(fullJointName, 256); // need find same joint in skel // need to strip out maya napesapce in case the rig was referenced in, in which case joint name will be something like mixamorig:Spine int pos = StringOps::lfind(fullJointName, ':'); const char *jointName = fullJointName; if (pos != -1) { jointName = &fullJointName[pos+1]; } for (int iSkelJoint = 0; iSkelJoint < targetSkelNumJoints; ++iSkelJoint) { FastJoint &fj = skel.m_fastJoints[iSkelJoint]; if (StringOps::strcmp(fj.m_pJointCPU->m_name, jointName) == 0 || StringOps::strcmp(fj.m_pJointCPU->m_name, fullJointName) == 0) { animJointToSkelJoint[iSrcJoint] = iSkelJoint; break; } } } } PrimitiveTypes::Int32 numFrames; f.nextInt32(numFrames); m_frames.reset(numFrames); for (PrimitiveTypes::UInt32 iFrame = 0; iFrame < (PrimitiveTypes::UInt32)(numFrames); iFrame++) { m_frames.add(Array<TSQ>(*m_pContext, m_arena)); Array<TSQ> &curFrame = m_frames[iFrame]; curFrame.reset(targetSkelNumJoints); // fill in with default values for (int iJoint = 0; iJoint < targetSkelNumJoints; ++iJoint) { FastJoint &fj = skel.m_fastJoints[iJoint]; Matrix4x4 parentMatrix; parentMatrix.loadIdentity(); if (fj.m_parent) { float *mf = fj.m_parent->m_pJointCPU->m_matrix; int iFloat = 0; for (PrimitiveTypes::UInt32 row = 0; row < 4; row++) { for (PrimitiveTypes::UInt32 col = 0; col < 4; col++) { parentMatrix.m[col][row] = mf[iFloat++]; // i dont think we need to multiply since we already have a full matrix from bind pose //m.setPos(m.getPos() * positionFactor); } } } Matrix4x4 m; float *mf = fj.m_pJointCPU->m_matrix; int iFloat = 0; for (PrimitiveTypes::UInt32 row = 0; row < 4; row++) { for (PrimitiveTypes::UInt32 col = 0; col < 4; col++) { m.m[col][row] = mf[iFloat++]; // i dont think we need to multiply since we already have a full matrix from bind pose //m.setPos(m.getPos() * positionFactor); } } m = parentMatrix.inverse() * m; TSQ tsq(m); // this is experimental, not 100 sure it works properly curFrame.add(tsq); } // read the data in for (PrimitiveTypes::UInt32 iJoint = 0; iJoint < m_numJoints; iJoint++) { // read each frame == numJoints matrices int targetJoint = animJointToSkelJoint[iJoint]; // might be retargetting or skipping completely Matrix4x4 m; Vector3 scale(1.0f, 1.0f, 1.0f); if (version == 0) { for (PrimitiveTypes::UInt32 row = 0; row < 4; row++) { for (PrimitiveTypes::UInt32 col = 0; col < 4; col++) { PrimitiveTypes::Float32 val; f.nextFloat32(val); m.m[col][row] = val; } } scale = Vector3(1.f, 1.f, 1.f); } else if (version == 1 || version == 2 || version == 3) { // read translation, rotation, scale Vector3 pos; f.nextFloat32(pos.m_x); f.nextFloat32(pos.m_y); f.nextFloat32(pos.m_z); Matrix4x4 tm(pos); Matrix3x3 rm; if (version == 1) { Vector3 rot; f.nextFloat32(rot.m_x); f.nextFloat32(rot.m_y); f.nextFloat32(rot.m_z); rot *= -1.0f; rot *= (PrimitiveTypes::Constants::c_Pi_F32 / 180.0f); rm = Matrix3x3(Rotate, rot, RotateOrder_ZYX); } else { Quaternion q; f.nextFloat32(q.m_w); f.nextFloat32(q.m_x); f.nextFloat32(q.m_y); f.nextFloat32(q.m_z); rm = Matrix3x3(q); } if (iJoint == 0) { f.nextFloat32(scale.m_x); f.nextFloat32(scale.m_y); f.nextFloat32(scale.m_z); } else { Vector3 temp; f.nextFloat32(temp.m_x); f.nextFloat32(temp.m_y); f.nextFloat32(temp.m_z); } Matrix3x3 res3x3 = rm; Matrix4x4 res(res3x3, pos); m = res; } m.setPos(m.getPos() * positionFactor); TSQ tsq(m, scale); if (targetJoint != -1) { curFrame[targetJoint] = tsq; jointUsage[targetJoint]++; } else PEINFO("Skipping joint %d\n", iJoint); } } }
int Effect::l_SetSpeShaderData(lua_State *luaVM) { GameContext *pContext = (GameContext*)(lua_touserdata(luaVM, -1)); lua_pop(luaVM, 1); PrimitiveTypes::UInt32 size; lua_pushstring(luaVM, "size"); // lua_gettable(luaVM, -2); size = (PrimitiveTypes::UInt32)(lua_tonumber(luaVM, -1)); lua_pop(luaVM, 1); // pop size Array<float> vals(*pContext, MemoryArena_Client); vals.reset(size * (3+2)); float *pcur = vals.getFirstPtr(); int ival = 1; // start indices from 1 for (PrimitiveTypes::UInt32 i = 0; i < size; ++i) { for (PrimitiveTypes::UInt32 j = 0; j < 3; ++j) { lua_pushnumber(luaVM, ival++); lua_gettable(luaVM, -2); // PrimitiveTypes::Float32 val = (PrimitiveTypes::Float32)(lua_tonumber(luaVM, -1)); *pcur = val; pcur++; lua_pop(luaVM, 1); // pop value } *pcur = 100.0f; pcur++; *pcur = 100.0f; pcur++; } lua_pushstring(luaVM, "techName"); // lua_gettable(luaVM, -2); const char * techName = lua_tostring(luaVM, -1); lua_pop(luaVM, 1); // pop techName Handle h = EffectManager::Instance()->getEffectHandle(techName); if (h.isValid()) { Effect *pEffect = h.getObject<Effect>(); void * dest = pEffect->m_speData.getObject(); memcpy(dest, vals.getFirstPtr(), size * (3+2) * sizeof(float)); } else { PEINFO("PE: ERROR: l_setSpeTechniqueReady() : provided technique does not exist!"); } lua_pop(luaVM, 1); // pop the input table vals.reset(0); return 0; }
static bool loadVertexShader_PSVita(PE::GameContext &ctx, const char *filename, const char *name, EPEVertexFormat format, Effect *pEffect, const SceGxmProgram *gxmProgram, SceGxmShaderPatcherId &out_programId, SceGxmVertexProgram *out_programs[] ) { PEString::generatePathname(ctx, filename, "Default", "GPUPrograms", PEString::s_buf, PEString::BUF_SIZE); PEINFO("PE: PROGRESS: loading shader: %s from %s\n", name, PEString::s_buf); if (strcmp("main", name)) { assert(!"Only shaders programs with name \"main()\" are supported"); } PSVitaRenderer *pPSVitaRenderer = static_cast<PSVitaRenderer *>(ctx.getGPUScreen()); SceGxmErrorCode err = sceGxmShaderPatcherRegisterProgram(pPSVitaRenderer->m_shaderPatcher, gxmProgram, &out_programId); PEASSERT(err == SCE_OK, "Error creating shader patcher id"); pEffect->m_externalPerTechniqueData.initVertexAttributeBindings(pEffect); // need these to assign to vertex buffer infos for (int iBufferLayout = 0; iBufferLayout < PEVertexFormatLayout_Count; ++iBufferLayout) { PEVertexBufferInfo &bufferLayoutInfo = VertexBufferGPUManager::Instance()->m_vertexBufferInfos[iBufferLayout]; EPEVertexFormat iFormat = VertexBufferGPUManager::Instance()->m_layoutToFormatMap[iBufferLayout]; if (format == iFormat) { for (int iAttr = 0; iAttr < bufferLayoutInfo.m_apiVertexAttributes.m_size; ++iAttr) { bufferLayoutInfo.m_apiVertexAttributes[iAttr].regIndex = -1; } // set bindings in buffers infos, by going through raw api-abstract data of buffer infos // and figuring out which binding to use for destination api info int iApiAttrIndex = 0; for (int iBuf = 0; iBuf < bufferLayoutInfo.m_bufferInfos.m_size; ++iBuf) { PEVertexAttributeBufferInfo &bufInfo = bufferLayoutInfo.m_bufferInfos[iBuf]; for (int iSem = 0; iSem < bufInfo.m_numAttributes; ++iSem) { PEVertexAttributeInfo &attrInfo = bufInfo.m_attributeInfos[iSem]; // this does something like // for detailed_mesh's vertex attribute position, in this shader position is bound result of to sceGxmProgramParameterGetResourceIndex GLSLAttributeLocations::ApiBindingType resBinding = sceGxmProgramFindParameterBySemantic(gxmProgram, (SceGxmParameterSemantic)(attrInfo.m_apiSemantic), attrInfo.m_apiSemanticOrder); PEASSERT(resBinding && (sceGxmProgramParameterGetCategory(resBinding) == SCE_GXM_PARAMETER_CATEGORY_ATTRIBUTE), "Problem finding vertex attribute"); uint32_t regIndex = sceGxmProgramParameterGetResourceIndex(resBinding); PEASSERT(regIndex != -1, "Invalid Index\n"); bufferLayoutInfo.m_apiVertexAttributes[iApiAttrIndex].regIndex = regIndex; ++iApiAttrIndex; } } SceGxmVertexAttribute *pVertexAttribute = bufferLayoutInfo.m_apiVertexAttributes.getFirstPtr(); int numVertexAttrs = bufferLayoutInfo.m_apiVertexAttributes.m_size; SceGxmVertexStream *pVertexStream = bufferLayoutInfo.m_apiVertexStreams.getFirstPtr(); int numStreams = bufferLayoutInfo.m_apiVertexStreams.m_size; err = sceGxmShaderPatcherCreateVertexProgram( pPSVitaRenderer->m_shaderPatcher, out_programId, pVertexAttribute, numVertexAttrs, pVertexStream, numStreams, &out_programs[iBufferLayout]); checkErrCode(err); PEASSERT(err == SCE_OK, "Error creating shader"); } } return true; }
void Effect::loadTechniqueSync_PSVita() { lock(); PSVitaRenderer *pPSVitaRenderer = static_cast<PSVitaRenderer *>(m_pContext->getGPUScreen()); if (StringOps::length(m_spesFilename)){return;} if (StringOps::length(m_gsFilename)){return;} if (StringOps::length(m_csFilename)){return;} //D3DXMACRO Shader_Macros[3] = { {"HLSL_SEPARATE_LOAD", "1"} , {"APIABSTRACTION_D3D9", "1"} , {0, 0}}; if (StringOps::length(m_vsFilename)) { PEString::generatePathname(*m_pContext, m_vsFilename, "Default", "GPUPrograms", PEString::s_buf, PEString::BUF_SIZE); FileReader f(PEString::s_buf); char *data = NULL; PrimitiveTypes::UInt32 size; f.readIntoBuffer(data, size); m_pBasicVertexProgramGxp = (SceGxmProgram*)data; } if (StringOps::length(m_psFilename)) { /* todo: don't compile pixel shaders int existingIndex = EffectManager::Instance()->m_pixelShaders.findIndex(m_psName); if (existingIndex != -1) { pPixelShader = EffectManager::Instance()->m_pixelShaders.m_pairs[existingIndex]; } else */ { PEString::generatePathname(*m_pContext, m_psFilename, "Default", "GPUPrograms", PEString::s_buf, PEString::BUF_SIZE); FileReader f(PEString::s_buf); char *data = NULL; PrimitiveTypes::UInt32 size; f.readIntoBuffer(data, size); m_pBasicFragmentProgramGxp = (SceGxmProgram*)data; SceGxmErrorCode gxmErrorCode = sceGxmProgramCheck(m_pBasicFragmentProgramGxp); switch(gxmErrorCode) { case SCE_OK: PEINFO("sceGxmProgramCheck() : OK\n"); break; case SCE_GXM_ERROR_INVALID_POINTER: PEINFO("sceGxmProgramCheck() : SCE_GXM_ERROR_INVALID_POINTER\n"); break; case SCE_GXM_ERROR_INVALID_VALUE: PEINFO("sceGxmProgramCheck() : SCE_GXM_ERROR_INVALID_VALUE\n"); break; } PEASSERT(gxmErrorCode == SCE_OK, "check failed\n"); gxmErrorCode = sceGxmProgramCheck(m_pBasicVertexProgramGxp); switch(gxmErrorCode) { case SCE_OK: PEINFO("sceGxmProgramCheck() : OK\n"); break; case SCE_GXM_ERROR_INVALID_POINTER: PEINFO("sceGxmProgramCheck() : SCE_GXM_ERROR_INVALID_POINTER\n");break; case SCE_GXM_ERROR_INVALID_VALUE: PEINFO("sceGxmProgramCheck() : SCE_GXM_ERROR_INVALID_VALUE\n");break; } PEASSERT(gxmErrorCode == SCE_OK, "check failed\n"); if (!loadFragmentShader_PSVita(*m_pContext, m_psFilename, m_psName, m_pBlendState, m_pBasicFragmentProgramGxp, m_pBasicVertexProgramGxp, m_basicFragmentProgramId, m_basicFragmentProgram )) { assert(!"Could not compile fragment program"); unlock(); return; } } } if (m_pBasicVertexProgramGxp) { if (!loadVertexShader_PSVita(*m_pContext, m_vsFilename, m_vsName, m_vsVertexFormat, this, m_pBasicVertexProgramGxp, m_basicVertexProgramId, m_basicVertexProgram )) { assert(!"Could not compile vertex program"); unlock(); return; } } m_externalPerTechniqueData.init(this); m_isReady = true; unlock(); }