#include "wiLoader.h" #include "wiResourceManager.h" #include "wiHelper.h" #include "wiMath.h" #include "wiRenderer.h" #include "wiEmittedParticle.h" #include "wiHairParticle.h" #include "wiRenderTarget.h" #include "wiDepthTarget.h" #include "wiTextureHelper.h" #include "wiPHYSICS.h" void LoadWiArmatures(const string& directory, const string& name, const string& identifier, vector& armatures) { stringstream filename(""); filename<>line; if(line[0]=='/' && line.substr(2,8)=="ARMATURE") { armatures.push_back(new Armature(line.substr(11,strlen(line.c_str())-11),identifier) ); } else{ switch(line[0]){ case 'r': file>>trans[0]>>trans[1]>>trans[2]>>trans[3]; armatures.back()->rotation_rest = XMFLOAT4(trans[0],trans[1],trans[2],trans[3]); break; case 's': file>>trans[0]>>trans[1]>>trans[2]; armatures.back()->scale_rest = XMFLOAT3(trans[0], trans[1], trans[2]); break; case 't': file>>trans[0]>>trans[1]>>trans[2]; armatures.back()->translation_rest = XMFLOAT3(trans[0], trans[1], trans[2]); { XMMATRIX world = XMMatrixScalingFromVector(XMLoadFloat3(&armatures.back()->scale))*XMMatrixRotationQuaternion(XMLoadFloat4(&armatures.back()->rotation))*XMMatrixTranslationFromVector(XMLoadFloat3(&armatures.back()->translation)); XMStoreFloat4x4( &armatures.back()->world_rest,world ); } break; case 'b': { string boneName; file>>boneName; armatures.back()->boneCollection.push_back(new Bone(boneName)); //stringstream ss(""); //ss<name<<"_"<boneCollection.push_back(new Bone(ss.str())); //transforms.insert(pair(armatures.back()->boneCollection.back()->name,armatures.back()->boneCollection.back())); } break; case 'p': file>>armatures.back()->boneCollection.back()->parentName; break; case 'l': { float x=0,y=0,z=0,w=0; file>>x>>y>>z>>w; XMVECTOR quaternion = XMVectorSet(x,y,z,w); file>>x>>y>>z; XMVECTOR translation = XMVectorSet(x,y,z,0); XMMATRIX frame; frame= XMMatrixRotationQuaternion(quaternion) * XMMatrixTranslationFromVector(translation) ; XMStoreFloat3(&armatures.back()->boneCollection.back()->translation_rest,translation); XMStoreFloat4(&armatures.back()->boneCollection.back()->rotation_rest,quaternion); XMStoreFloat4x4(&armatures.back()->boneCollection.back()->world_rest,frame); XMStoreFloat4x4(&armatures.back()->boneCollection.back()->restInv,XMMatrixInverse(0,frame)); /*XMStoreFloat3( &armatures.back()->boneCollection.back().position,translationInverse ); XMStoreFloat4( &armatures.back()->boneCollection.back().rotation,quaternionInverse );*/ /*XMVECTOR sca,rot,tra; XMMatrixDecompose(&sca,&rot,&tra,XMMatrixInverse(0,XMMatrixTranspose(frame))*XMLoadFloat4x4(&armatures.back()->world)); XMStoreFloat3( &armatures.back()->boneCollection.back().position,tra ); XMStoreFloat4( &armatures.back()->boneCollection.back().rotation,rot );*/ } break; case 'c': armatures.back()->boneCollection.back()->connected=true; break; case 'h': file>>armatures.back()->boneCollection.back()->length; break; default: break; } } } } file.close(); //CREATE FAMILY for(Armature* armature : armatures){ for(Bone* i : armature->boneCollection){ if(i->parentName.length()>0){ for(Bone* j : armature->boneCollection){ if(i!=j){ if(!i->parentName.compare(j->name)){ i->parent=j; j->childrenN.push_back(i->name); j->childrenI.push_back(i); i->attachTo(j,1,1,1); } } } } else{ armature->rootbones.push_back(i); } } for (unsigned int i = 0; irootbones.size(); ++i){ RecursiveRest(armature,armature->rootbones[i]); } } } void RecursiveRest(Armature* armature, Bone* bone){ Bone* parent = (Bone*)bone->parent; if(parent!=nullptr){ XMMATRIX recRest = XMLoadFloat4x4(&bone->world_rest) * XMLoadFloat4x4(&parent->recursiveRest) //* //XMLoadFloat4x4(&armature->boneCollection[boneI].rest) ; XMStoreFloat4x4( &bone->recursiveRest, recRest ); XMStoreFloat4x4( &bone->recursiveRestInv, XMMatrixInverse(0,recRest) ); } else{ bone->recursiveRest = bone->world_rest ; XMStoreFloat4x4( &bone->recursiveRestInv, XMMatrixInverse(0,XMLoadFloat4x4(&bone->recursiveRest)) ); } for (unsigned int i = 0; ichildrenI.size(); ++i){ RecursiveRest(armature,bone->childrenI[i]); } } void LoadWiMaterialLibrary(const string& directory, const string& name, const string& identifier, const string& texturesDir,MaterialCollection& materials) { int materialI=materials.size()-1; Material* currentMat = NULL; stringstream filename(""); filename<>line; if(line[0]=='/' && !strcmp(line.substr(2,8).c_str(),"MATERIAL")) { if(currentMat) materials.insert(pair(currentMat->name,currentMat)); stringstream identified_name(""); identified_name<>currentMat->diffuseColor.x; file>>currentMat->diffuseColor.y; file>>currentMat->diffuseColor.z; break; case 'X': currentMat->cast_shadow=false; break; case 'r': { string resourceName=""; file>>resourceName; stringstream ss(""); ss<refMapName=ss.str(); currentMat->refMap = (TextureView)wiResourceManager::GetGlobal()->add(ss.str()); } if(currentMat->refMap!=0) currentMat->hasRefMap = true; break; case 'n': { string resourceName=""; file>>resourceName; stringstream ss(""); ss<normalMapName=ss.str(); currentMat->normalMap = (TextureView)wiResourceManager::GetGlobal()->add(ss.str()); } if(currentMat->normalMap!=0) currentMat->hasNormalMap = true; break; case 't': { string resourceName=""; file>>resourceName; stringstream ss(""); ss<textureName=ss.str(); currentMat->texture = (TextureView)wiResourceManager::GetGlobal()->add(ss.str()); } if(currentMat->texture!=0) currentMat->hasTexture=true; file>>currentMat->premultipliedTexture; break; case 'D': { string resourceName=""; file>>resourceName; stringstream ss(""); ss<displacementMapName=ss.str(); currentMat->displacementMap = (TextureView)wiResourceManager::GetGlobal()->add(ss.str()); } if(currentMat->displacementMap!=0) currentMat->hasDisplacementMap=true; break; case 'S': { string resourceName=""; file>>resourceName; stringstream ss(""); ss<specularMapName=ss.str(); currentMat->specularMap = (TextureView)wiResourceManager::GetGlobal()->add(ss.str()); } if(currentMat->specularMap!=0) currentMat->hasSpecularMap=true; break; case 'a': file>>currentMat->alpha; break; case 'h': currentMat->shadeless=true; break; case 'R': file>>currentMat->refraction_index; break; case 'e': file>>currentMat->enviroReflection; break; case 's': file>>currentMat->specular.x; file>>currentMat->specular.y; file>>currentMat->specular.z; file>>currentMat->specular.w; break; case 'p': file>>currentMat->specular_power; break; case 'k': currentMat->isSky=true; break; case 'm': file>>currentMat->movingTex.x; file>>currentMat->movingTex.y; file>>currentMat->movingTex.z; currentMat->framesToWaitForTexCoordOffset=currentMat->movingTex.z; break; case 'w': currentMat->water=true; break; case 'u': currentMat->subsurface_scattering=true; break; case 'b': { string blend; file>>blend; if(!blend.compare("ADD")) currentMat->blendFlag=BLENDMODE_ADDITIVE; } break; case 'i': { file>>currentMat->emissive; } break; default:break; } } } } file.close(); if(currentMat) materials.insert(pair(currentMat->name,currentMat)); } void LoadWiObjects(const string& directory, const string& name, const string& identifier, vector& objects , vector& armatures , MeshCollection& meshes, const MaterialCollection& materials) { int objectI=objects.size()-1; stringstream filename(""); filename<>line; if(line[0]=='/' && !strcmp(line.substr(2,6).c_str(),"OBJECT")) { stringstream identified_name(""); identified_name<>meshName; stringstream identified_mesh(""); identified_mesh<LoadFromFile(identified_mesh.str(),meshFileName.str(),materials,armatures,identifier); objects.back()->mesh=mesh; meshes.insert(pair(identified_mesh.str(),mesh)); } else{ objects.back()->mesh=iter->second; } } else{ if(iter!=meshes.end()) { objects.back()->mesh=iter->second; //objects.back()->mesh->usedBy.push_back(objects.size()-1); } } } break; case 'p': { string parentName=""; file>>parentName; stringstream identified_parentName(""); identified_parentName<parentName = identified_parentName.str(); //for(Armature* a : armatures){ // if(!a->name.compare(identified_parentName.str())){ // objects.back()->parentName=identified_parentName.str(); // objects.back()->parent=a; // objects.back()->attachTo(a,1,1,1); // objects.back()->armatureDeform=true; // } //} } break; case 'b': { string bone=""; file>>bone; objects.back()->boneParent = bone; //if(objects.back()->parent!=nullptr){ // for(Bone* b : ((Armature*)objects.back()->parent)->boneCollection){ // if(!bone.compare(b->name)){ // objects.back()->parent=b; // objects.back()->armatureDeform=false; // break; // } // } //} } break; case 'I': { XMFLOAT3 s,t; XMFLOAT4 r; file>>t.x>>t.y>>t.z>>r.x>>r.y>>r.z>>r.w>>s.x>>s.y>>s.z; XMStoreFloat4x4(&objects.back()->parent_inv_rest , XMMatrixScalingFromVector(XMLoadFloat3(&s)) * XMMatrixRotationQuaternion(XMLoadFloat4(&r)) * XMMatrixTranslationFromVector(XMLoadFloat3(&t)) ); } break; case 'r': file>>trans[0]>>trans[1]>>trans[2]>>trans[3]; objects.back()->Rotate(XMFLOAT4(trans[0], trans[1], trans[2],trans[3])); //objects.back()->rotation_rest = XMFLOAT4(trans[0],trans[1],trans[2],trans[3]); break; case 's': file>>trans[0]>>trans[1]>>trans[2]; objects.back()->Scale(XMFLOAT3(trans[0], trans[1], trans[2])); //objects.back()->scale_rest = XMFLOAT3(trans[0], trans[1], trans[2]); break; case 't': file>>trans[0]>>trans[1]>>trans[2]; objects.back()->Translate(XMFLOAT3(trans[0], trans[1], trans[2])); //objects.back()->translation_rest = XMFLOAT3(trans[0], trans[1], trans[2]); //XMStoreFloat4x4( &objects.back()->world_rest, XMMatrixScalingFromVector(XMLoadFloat3(&objects.back()->scale_rest)) // *XMMatrixRotationQuaternion(XMLoadFloat4(&objects.back()->rotation_rest)) // *XMMatrixTranslationFromVector(XMLoadFloat3(&objects.back()->translation_rest)) // ); //objects.back()->world=objects.back()->world_rest; break; case 'E': { string systemName,materialName; bool visibleEmitter; float size,randfac,norfac; float count,life,randlife; float scaleX,scaleY,rot; file>>systemName>>visibleEmitter>>materialName>>size>>randfac>>norfac>>count>>life>>randlife; file>>scaleX>>scaleY>>rot; if(visibleEmitter) objects.back()->emitterType=Object::EMITTER_VISIBLE; else if(objects.back()->emitterType ==Object::NO_EMITTER) objects.back()->emitterType =Object::EMITTER_INVISIBLE; if(wiRenderer::EMITTERSENABLED){ stringstream identified_materialName(""); identified_materialName<mesh){ objects.back()->eParticleSystems.push_back( new wiEmittedParticle(identified_systemName.str(),identified_materialName.str(),objects.back(),size,randfac,norfac,count,life,randlife,scaleX,scaleY,rot) ); } } } break; case 'H': { string name,mat,densityG,lenG; float len; int count; file>>name>>mat>>len>>count>>densityG>>lenG; if(wiRenderer::HAIRPARTICLEENABLED){ stringstream identified_materialName(""); identified_materialName<hParticleSystems.push_back(new wiHairParticle(name,len,count,identified_materialName.str(),objects.back(),densityG,lenG) ); } } break; case 'P': objects.back()->rigidBody = true; file>>objects.back()->collisionShape>>objects.back()->mass>> objects.back()->friction>>objects.back()->restitution>>objects.back()->damping>>objects.back()->physicsType>> objects.back()->kinematic; break; case 'T': file >> objects.back()->transparency; break; default: break; } } } } file.close(); //for (unsigned int i = 0; imesh){ // if(objects[i]->mesh->trailInfo.base>=0 && objects[i]->mesh->trailInfo.tip>=0){ // //objects[i]->trail.resize(MAX_RIBBONTRAILS); // D3D11_BUFFER_DESC bd; // ZeroMemory( &bd, sizeof(bd) ); // bd.Usage = D3D11_USAGE_DYNAMIC; // bd.ByteWidth = sizeof( RibbonVertex ) * 1000; // bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; // bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // wiRenderer::graphicsDevice->CreateBuffer( &bd, NULL, &objects[i]->trailBuff ); // objects[i]->trailTex = wiTextureHelper::getInstance()->getTransparent(); // objects[i]->trailDistortTex = wiTextureHelper::getInstance()->getNormalMapDefault(); // } // } //} //for (MeshCollection::iterator iter = meshes.begin(); iter != meshes.end(); ++iter){ // Mesh* iMesh = iter->second; // iMesh->CreateVertexArrays(); // iMesh->Optimize(); // iMesh->CreateBuffers(); //} } void LoadWiMeshes(const string& directory, const string& name, const string& identifier, MeshCollection& meshes, const vector& armatures, const MaterialCollection& materials) { int meshI=meshes.size()-1; Mesh* currentMesh = NULL; stringstream filename(""); filename<>line; if(line[0]=='/' && !line.substr(2,4).compare("MESH")) { stringstream identified_name(""); identified_name<(currentMesh->name,currentMesh) ); meshI++; } else{ switch(line[0]){ case 'p': { string parentArmature=""; file>>parentArmature; stringstream identified_parentArmature(""); identified_parentArmature<parent=identified_parentArmature.str(); for (unsigned int i = 0; iname.c_str(),currentMesh->parent.c_str())){ currentMesh->armature=armatures[i]; } } break; case 'v': currentMesh->vertices.push_back(SkinnedVertex()); file >> currentMesh->vertices.back().pos.x; file >> currentMesh->vertices.back().pos.y; file >> currentMesh->vertices.back().pos.z; break; case 'n': if (currentMesh->isBillboarded){ currentMesh->vertices.back().nor.x = currentMesh->billboardAxis.x; currentMesh->vertices.back().nor.y = currentMesh->billboardAxis.y; currentMesh->vertices.back().nor.z = currentMesh->billboardAxis.z; } else{ file >> currentMesh->vertices.back().nor.x; file >> currentMesh->vertices.back().nor.y; file >> currentMesh->vertices.back().nor.z; } break; case 'u': file >> currentMesh->vertices.back().tex.x; file >> currentMesh->vertices.back().tex.y; //texCoordFill++; break; case 'w': { string nameB; float weight=0; int BONEINDEX=0; file>>nameB>>weight; bool gotArmature=false; bool gotBone=false; int i=0; while(!gotArmature && i<(int)armatures.size()){ //SEARCH FOR PARENT ARMATURE if(!strcmp(armatures[i]->name.c_str(),currentMesh->parent.c_str())) gotArmature=true; else i++; } if(gotArmature){ int j=0; while(!gotBone && j<(int)armatures[i]->boneCollection.size()){ if(!armatures[i]->boneCollection[j]->name.compare(nameB)){ gotBone=true; BONEINDEX=j; //GOT INDEX OF BONE OF THE WEIGHT IN THE PARENT ARMATURE } j++; } } if(gotBone){ //ONLY PROCEED IF CORRESPONDING BONE WAS FOUND if(!currentMesh->vertices.back().wei.x) { currentMesh->vertices.back().wei.x=weight; currentMesh->vertices.back().bon.x=(float)BONEINDEX; } else if(!currentMesh->vertices.back().wei.y) { currentMesh->vertices.back().wei.y=weight; currentMesh->vertices.back().bon.y=(float)BONEINDEX; } else if(!currentMesh->vertices.back().wei.z) { currentMesh->vertices.back().wei.z=weight; currentMesh->vertices.back().bon.z=(float)BONEINDEX; } else if(!currentMesh->vertices.back().wei.w) { currentMesh->vertices.back().wei.w=weight; currentMesh->vertices.back().bon.w=(float)BONEINDEX; } } //(+RIBBONTRAIL SETUP)(+VERTEXGROUP SETUP) if(nameB.find("trailbase")!=string::npos) currentMesh->trailInfo.base = currentMesh->vertices.size()-1; else if(nameB.find("trailtip")!=string::npos) currentMesh->trailInfo.tip = currentMesh->vertices.size()-1; bool windAffection=false; if(nameB.find("wind")!=string::npos) windAffection=true; bool gotvg=false; for (unsigned int v = 0; vvertexGroups.size(); ++v) if(!nameB.compare(currentMesh->vertexGroups[v].name)){ gotvg=true; currentMesh->vertexGroups[v].addVertex( VertexRef(currentMesh->vertices.size()-1,weight) ); if(windAffection) currentMesh->vertices.back().tex.w=weight; } if(!gotvg){ currentMesh->vertexGroups.push_back(VertexGroup(nameB)); currentMesh->vertexGroups.back().addVertex( VertexRef(currentMesh->vertices.size()-1,weight) ); if(windAffection) currentMesh->vertices.back().tex.w=weight; } } break; case 'i': { int count; file>>count; for(int i=0;i>index; currentMesh->indices.push_back(index); } break; } case 'V': { XMFLOAT3 pos; file >> pos.x>>pos.y>>pos.z; currentMesh->physicsverts.push_back(pos); } break; case 'I': { int count; file>>count; for(int i=0;i>index; currentMesh->physicsindices.push_back(index); } break; } case 'm': { string mName=""; file>>mName; stringstream identified_material(""); identified_material<materialNames.push_back(identified_material.str()); MaterialCollection::const_iterator iter = materials.find(identified_material.str()); if(iter!=materials.end()) { currentMesh->renderable=true; currentMesh->materials.push_back(iter->second); currentMesh->materialIndices.push_back(currentMesh->materials.size()); //CONNECT meshes WITH MATERIALS } } break; case 'a': file>>currentMesh->vertices.back().tex.z; break; case 'B': for(int corner=0;corner<8;++corner){ file>>currentMesh->aabb.corners[corner].x; file>>currentMesh->aabb.corners[corner].y; file>>currentMesh->aabb.corners[corner].z; } break; case 'b': { currentMesh->isBillboarded=true; string read = ""; file>>read; transform(read.begin(), read.end(), read.begin(), toupper); if(read.find(toupper('y'))!=string::npos) currentMesh->billboardAxis=XMFLOAT3(0,1,0); else if(read.find(toupper('x'))!=string::npos) currentMesh->billboardAxis=XMFLOAT3(1,0,0); else if(read.find(toupper('z'))!=string::npos) currentMesh->billboardAxis=XMFLOAT3(0,0,1); else currentMesh->billboardAxis=XMFLOAT3(0,0,0); } break; case 'S': { currentMesh->softBody=true; string mvgi="",gvgi="",svgi=""; file>>currentMesh->mass>>currentMesh->friction>>gvgi>>mvgi>>svgi; for (unsigned int v = 0; vvertexGroups.size(); ++v){ if(!strcmp(mvgi.c_str(),currentMesh->vertexGroups[v].name.c_str())) currentMesh->massVG=v; if(!strcmp(gvgi.c_str(),currentMesh->vertexGroups[v].name.c_str())) currentMesh->goalVG=v; if(!strcmp(svgi.c_str(),currentMesh->vertexGroups[v].name.c_str())) currentMesh->softVG=v; } } break; default: break; } } } } file.close(); if(currentMesh) meshes.insert( pair(currentMesh->name,currentMesh) ); } void LoadWiActions(const string& directory, const string& name, const string& identifier, vector& armatures) { int armatureI=0; int boneI=0; int firstFrame=INT_MAX; stringstream filename(""); filename<>line; if(line[0]=='/' && !strcmp(line.substr(2,8).c_str(),"ARMATURE")) { stringstream identified_name(""); identified_name<name.compare(armaturename)){ armatureI=i; break; } } else{ switch(line[0]){ case 'C': armatures[armatureI]->actions.push_back(Action()); file>>armatures[armatureI]->actions.back().name; break; case 'A': file>>armatures[armatureI]->actions.back().frameCount; break; case 'b': { string boneName; file>>boneName; for (unsigned int i = 0; iboneCollection.size(); i++) if(!armatures[armatureI]->boneCollection[i]->name.compare(boneName)){ boneI=i; break; } //GOT BONE INDEX armatures[armatureI]->boneCollection[boneI]->actionFrames.resize(armatures[armatureI]->actions.size()); } break; case 'r': { int f = 0; float x=0,y=0,z=0,w=0; file>>f>>x>>y>>z>>w; armatures[armatureI]->boneCollection[boneI]->actionFrames.back().keyframesRot.push_back(KeyFrame(f,x,y,z,w)); } break; case 't': { int f = 0; float x=0,y=0,z=0; file>>f>>x>>y>>z; armatures[armatureI]->boneCollection[boneI]->actionFrames.back().keyframesPos.push_back(KeyFrame(f,x,y,z,0)); } break; case 's': { int f = 0; float x=0,y=0,z=0; file>>f>>x>>y>>z; armatures[armatureI]->boneCollection[boneI]->actionFrames.back().keyframesSca.push_back(KeyFrame(f,x,y,z,0)); } break; default: break; } } } } file.close(); } void LoadWiLights(const string& directory, const string& name, const string& identifier, vector& lights) { stringstream filename(""); filename<>line; switch(line[0]){ case 'P': { lights.push_back(new Light()); lights.back()->type=Light::POINT; string lname = ""; file>>lname>> lights.back()->shadow; stringstream identified_name(""); identified_name<name=identified_name.str(); lights.back()->shadowBias = 0.00001f; } break; case 'D': { lights.push_back(new Light()); lights.back()->type=Light::DIRECTIONAL; file>>lights.back()->name; lights.back()->shadow = true; lights.back()->shadowMaps_dirLight.resize(3); lights.back()->shadowBias = 9.99995464e-005f; //for (int i = 0; i < 3; ++i) //{ // lights.back()->shadowMaps_dirLight[i].Initialize( // wiRenderer::SHADOWMAPRES, wiRenderer::SHADOWMAPRES // , 0, true // ); //} } break; case 'S': { lights.push_back(new Light()); lights.back()->type=Light::SPOT; file>>lights.back()->name; file>>lights.back()->shadow>>lights.back()->enerDis.z; lights.back()->shadowBias = 0.00001f; } break; case 'p': { string parentName=""; file>>parentName; stringstream identified_parentName(""); identified_parentName<parentName=identified_parentName.str(); //for(map::iterator it=transforms.begin();it!=transforms.end();++it){ // if(!it->second->name.compare(lights.back()->parentName)){ // lights.back()->parent=it->second; // lights.back()->attachTo(it->second,1,1,1); // break; // } //} } break; case 'b': { string parentBone=""; file>>parentBone; lights.back()->boneParent = parentBone; //for(Bone* b : ((Armature*)lights.back()->parent)->boneCollection){ // if(!b->name.compare(parentBone)){ // lights.back()->parent=b; // lights.back()->attachTo(b,1,1,1); // } //} } break; case 'I': { XMFLOAT3 s,t; XMFLOAT4 r; file>>t.x>>t.y>>t.z>>r.x>>r.y>>r.z>>r.w>>s.x>>s.y>>s.z; XMStoreFloat4x4(&lights.back()->parent_inv_rest , XMMatrixScalingFromVector(XMLoadFloat3(&s)) * XMMatrixRotationQuaternion(XMLoadFloat4(&r)) * XMMatrixTranslationFromVector(XMLoadFloat3(&t)) ); } break; case 't': { float x,y,z; file>>x>>y>>z; lights.back()->Translate(XMFLOAT3(x, y, z)); //lights.back()->translation_rest=XMFLOAT3(x,y,z); break; } case 'r': { float x,y,z,w; file>>x>>y>>z>>w; lights.back()->Rotate(XMFLOAT4(x, y, z, w)); //lights.back()->rotation_rest=XMFLOAT4(x,y,z,w); break; } case 'c': { float r,g,b; file>>r>>g>>b; lights.back()->color=XMFLOAT4(r,g,b,0); break; } case 'e': file>>lights.back()->enerDis.x; break; case 'd': file>>lights.back()->enerDis.y; //lights.back()->enerDis.y *= XMVectorGetX( world.r[0] )*0.1f; break; case 'n': lights.back()->noHalo=true; break; case 'l': { string t=""; file>>t; stringstream rim(""); rim<add(rim.str())) != nullptr){ lights.back()->lensFlareRimTextures.push_back(tex); lights.back()->lensFlareNames.push_back(rim.str()); } } break; default: break; } } //for(MeshCollection::iterator iter=lightGwiRenderer.begin(); iter!=lightGwiRenderer.end(); ++iter){ // Mesh* iMesh = iter->second; // D3D11_BUFFER_DESC bd; // ZeroMemory( &bd, sizeof(bd) ); // bd.Usage = D3D11_USAGE_DYNAMIC; // bd.ByteWidth = sizeof( Instance )*iMesh->usedBy.size(); // bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; // bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // wiRenderer::graphicsDevice->CreateBuffer( &bd, 0, &iMesh->meshInstanceBuffer ); //} } file.close(); } void LoadWiHitSpheres(const string& directory, const string& name, const string& identifier, vector& spheres ,const vector& armatures) { stringstream filename(""); filename<>voidStr; while(!file.eof()){ string line=""; file>>line; switch(line[0]){ case 'H': { string name; float scale; XMFLOAT3 loc; string parentStr; string prop; file>>name>>scale>>loc.x>>loc.y>>loc.z>>parentStr>>prop; stringstream identified_parent(""),identified_name(""); identified_parent<name)){ // for(Bone* b:a->boneCollection){ // if(!parentBone.compare(b->name)){ // parentA=a; // parent=b; // } // } // } //} //spheres.push_back(new HitSphere(identified_name.str(),scale,loc,parentA,parent,prop)); // PARENTING DISABLED ON REFACTOR! CHECK! //Transform* parent = nullptr; //if(transforms.find(identified_parent.str())!=transforms.end()) //{ // parent = transforms[identified_parent.str()]; // spheres.push_back(new HitSphere(identified_name.str(),scale,loc,parent,prop)); // spheres.back()->attachTo(parent,1,1,1); // transforms.insert(pair(spheres.back()->name,spheres.back())); //} } break; case 'I': { XMFLOAT3 s,t; XMFLOAT4 r; file>>t.x>>t.y>>t.z>>r.x>>r.y>>r.z>>r.w>>s.x>>s.y>>s.z; XMStoreFloat4x4(&spheres.back()->parent_inv_rest , XMMatrixScalingFromVector(XMLoadFloat3(&s)) * XMMatrixRotationQuaternion(XMLoadFloat4(&r)) * XMMatrixTranslationFromVector(XMLoadFloat3(&t)) ); } break; case 'b': { string parentBone = ""; file>>parentBone; Armature* parentA = (Armature*)spheres.back()->parent; if(parentA!=nullptr){ for(Bone* b:parentA->boneCollection){ if(!parentBone.compare(b->name)){ spheres.back()->attachTo(b,1,1,1); } } } } break; default: break; }; } } file.close(); ////SET UP SPHERE INDEXERS //for(int i=0;iname.compare(spheres[i]->pA)){ // spheres[i]->parentArmature=armatures[j]; // for(int k=0;kboneCollection.size();k++) // if(!armatures[j]->boneCollection[k]->name.compare(spheres[i]->pB)){ // spheres[i]->parentBone=k; // break; // } // break; // } // } //} } void LoadWiWorldInfo(const string&directory, const string& name, WorldInfo& worldInfo, Wind& wind){ stringstream filename(""); filename<>read; switch(read[0]){ case 'h': file>>worldInfo.horizon.x>>worldInfo.horizon.y>>worldInfo.horizon.z; break; case 'z': file>>worldInfo.zenith.x>>worldInfo.zenith.y>>worldInfo.zenith.z; break; case 'a': file>>worldInfo.ambient.x>>worldInfo.ambient.y>>worldInfo.ambient.z; break; case 'W': { XMFLOAT4 r; float s; file>>r.x>>r.y>>r.z>>r.w>>s; XMStoreFloat3(&wind.direction, XMVector3Transform( XMVectorSet(0,s,0,0),XMMatrixRotationQuaternion(XMLoadFloat4(&r)) )); } break; case 'm': { float s,e,h; file>>s>>e>>h; worldInfo.fogSEH=XMFLOAT3(s,e,h); } break; default:break; } } } file.close(); } void LoadWiCameras(const string&directory, const string& name, const string& identifier, vector& cameras ,const vector& armatures){ stringstream filename(""); filename<>voidStr; while(!file.eof()){ string line=""; file>>line; switch(line[0]){ case 'c': { XMFLOAT3 trans; XMFLOAT4 rot; string name(""),parentA(""),parentB(""); file>>name>>parentA>>parentB>>trans.x>>trans.y>>trans.z>>rot.x>>rot.y>>rot.z>>rot.w; stringstream identified_parentArmature(""); identified_parentArmature<name.compare(identified_parentArmature.str())){ for (unsigned int j = 0; jboneCollection.size(); ++j){ if(!armatures[i]->boneCollection[j]->name.compare(parentB.c_str())) cameras.back().attachTo(armatures[i]->boneCollection[j]); } } } } break; case 'I': { XMFLOAT3 s,t; XMFLOAT4 r; file>>t.x>>t.y>>t.z>>r.x>>r.y>>r.z>>r.w>>s.x>>s.y>>s.z; XMStoreFloat4x4(&cameras.back().parent_inv_rest , XMMatrixScalingFromVector(XMLoadFloat3(&s)) * XMMatrixRotationQuaternion(XMLoadFloat4(&r)) * XMMatrixTranslationFromVector(XMLoadFloat3(&t)) ); } break; default:break; } } } file.close(); } void LoadWiDecals(const string&directory, const string& name, const string& texturesDir, list& decals){ stringstream filename(""); filename<>voidStr; while(!file.eof()){ string line=""; file>>line; switch(line[0]){ case 'd': { string name; XMFLOAT3 loc,scale; XMFLOAT4 rot; file>>name>>scale.x>>scale.y>>scale.z>>loc.x>>loc.y>>loc.z>>rot.x>>rot.y>>rot.z>>rot.w; Decal* decal = new Decal(); decal->name=name; decal->translation_rest=loc; decal->scale_rest=scale; decal->rotation_rest=rot; decals.push_back(new Decal(loc,scale,rot)); } break; case 't': { string tex=""; file>>tex; stringstream ss(""); ss<addTexture(ss.str()); } break; case 'n': { string tex=""; file>>tex; stringstream ss(""); ss<addNormal(ss.str()); } break; default:break; }; } } file.close(); } //void LoadFromDisk(const string& dir, const string& name, const string& identifier // , vector& armatures // , MaterialCollection& materials // , vector& objects // , MeshCollection& meshes // , vector& lights // , vector& spheres // , WorldInfo& worldInfo, Wind& wind // , vector& cameras // , map& transforms // , list& decals // ) //{ // MaterialCollection l_materials; // vector l_armatures; // vector l_objects; // MeshCollection l_meshes; // vector l_lights; // vector l_spheres; // WorldInfo l_worldInfo = worldInfo; // Wind l_wind = wind; // vector l_cameras; // map l_transforms; // list l_decals; // // stringstream directory(""),armatureFilePath(""),materialLibFilePath(""),meshesFilePath(""),objectsFilePath("") // ,actionsFilePath(""),lightsFilePath(""),worldInfoFilePath(""),enviroMapFilePath(""),hitSpheresFilePath("") // ,camerasFilePath(""),decalsFilePath(""); // // directory<& objects, int type){ if(type==SPTREE_GENERATE_QUADTREE) tree = new QuadTree(); else if(type==SPTREE_GENERATE_OCTREE) tree = new Octree(); tree->initialize(objects); } #pragma region SCENE Scene::Scene() { models.push_back(new Model); models.back()->name = "[WickedEngine-default]{WorldNode}"; } Scene::~Scene() { for (Model* x : models) { SAFE_DELETE(x); } } void Scene::ClearWorld() { Model* world = GetWorldNode(); for (unsigned int i = 1; i < models.size();++i) { SAFE_DELETE(models[i]); } models.clear(); models.push_back(world); } Model* Scene::GetWorldNode() { return models[0]; } void Scene::AddModel(Model* model) { models.push_back(model); model->attachTo(models[0]); } void Scene::Update() { models[0]->UpdateTransform(); for (Model* x : models) { x->UpdateModel(); } } #pragma endregion #pragma region CULLABLE Cullable::Cullable():bounds(AABB())/*,lastSquaredDistMulThousand(0)*/{} #pragma endregion #pragma region STREAMABLE Streamable::Streamable():directory(""),meshfile(""),materialfile(""),loaded(false){} #pragma endregion #pragma region MATERIAL Material::~Material() { wiResourceManager::GetGlobal()->del(refMapName); wiResourceManager::GetGlobal()->del(textureName); wiResourceManager::GetGlobal()->del(normalMapName); wiResourceManager::GetGlobal()->del(displacementMapName); wiResourceManager::GetGlobal()->del(specularMapName); refMap = nullptr; texture = nullptr; normalMap = nullptr; displacementMap = nullptr; specularMap = nullptr; } #pragma endregion #pragma region MESH thread_local vector Mesh::instances; BufferResource Mesh::meshInstanceBuffer = nullptr; void Mesh::LoadFromFile(const string& newName, const string& fname , const MaterialCollection& materialColl, vector armatures, const string& identifier) { name = newName; BYTE* buffer; size_t fileSize; if (wiHelper::readByteData(fname, &buffer, fileSize)) { int offset = 0; int VERSION; memcpy(&VERSION, buffer, sizeof(int)); offset += sizeof(int); if (VERSION >= 1001) { int doubleside; memcpy(&doubleside, buffer + offset, sizeof(int)); offset += sizeof(int); if (doubleside) { doubleSided = true; } } int billboard; memcpy(&billboard, buffer + offset, sizeof(int)); offset += sizeof(int); if (billboard) { char axis; memcpy(&axis, buffer + offset, 1); offset += 1; if (toupper(axis) == 'Y') billboardAxis = XMFLOAT3(0, 1, 0); else if (toupper(axis) == 'X') billboardAxis = XMFLOAT3(1, 0, 0); else if (toupper(axis) == 'Z') billboardAxis = XMFLOAT3(0, 0, 1); else billboardAxis = XMFLOAT3(0, 0, 0); isBillboarded = true; } int parented; //parentnamelength memcpy(&parented, buffer + offset, sizeof(int)); offset += sizeof(int); if (parented) { char* pName = new char[parented + 1](); memcpy(pName, buffer + offset, parented); offset += parented; parent = pName; delete[] pName; stringstream identified_parent(""); identified_parent << parent << identifier; for (Armature* a : armatures) { if (!a->name.compare(identified_parent.str())) { armature = a; } } } int materialCount; memcpy(&materialCount, buffer + offset, sizeof(int)); offset += sizeof(int); for (int i = 0; isecond); } materialNames.push_back(identified_matname.str()); delete[] matName; } int rendermesh, vertexCount; memcpy(&rendermesh, buffer + offset, sizeof(int)); offset += sizeof(int); memcpy(&vertexCount, buffer + offset, sizeof(int)); offset += sizeof(int); vertices.reserve(vertexCount); for (int i = 0; iboneCollection.size()) { if (!armature->boneCollection[b]->name.compare(nameB)) { gotBone = true; BONEINDEX = b; //GOT INDEX OF BONE OF THE WEIGHT IN THE PARENT ARMATURE } b++; } if (gotBone) { //ONLY PROCEED IF CORRESPONDING BONE WAS FOUND if (!vert.wei.x) { vert.wei.x = weightValue; vert.bon.x = (float)BONEINDEX; } else if (!vert.wei.y) { vert.wei.y = weightValue; vert.bon.y = (float)BONEINDEX; } else if (!vert.wei.z) { vert.wei.z = weightValue; vert.bon.z = (float)BONEINDEX; } else if (!vert.wei.w) { vert.wei.w = weightValue; vert.bon.w = (float)BONEINDEX; } } } //(+RIBBONTRAIL SETUP)(+VERTEXGROUP SETUP) if (nameB.find("trailbase") != string::npos) trailInfo.base = vertices.size(); else if (nameB.find("trailtip") != string::npos) trailInfo.tip = vertices.size(); bool windAffection = false; if (nameB.find("wind") != string::npos) windAffection = true; bool gotvg = false; for (unsigned int v = 0; vCreateBuffer(&bd, 0, &meshInstanceBuffer); } if (goalVG >= 0) { goalPositions.resize(vertexGroups[goalVG].vertices.size()); goalNormals.resize(vertexGroups[goalVG].vertices.size()); } ZeroMemory(&bd, sizeof(bd)); #ifdef USE_GPU_SKINNING bd.Usage = (softBody ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_IMMUTABLE); bd.CPUAccessFlags = (softBody ? D3D11_CPU_ACCESS_WRITE : 0); if (object->isArmatureDeformed() && !softBody) bd.ByteWidth = sizeof(SkinnedVertex) * vertices.size(); else bd.ByteWidth = sizeof(Vertex) * vertices.size(); #else bd.Usage = ((softBody || object->isArmatureDeformed()) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_IMMUTABLE); bd.CPUAccessFlags = ((softBody || object->isArmatureDeformed()) ? D3D11_CPU_ACCESS_WRITE : 0); bd.ByteWidth = sizeof(Vertex) * vertices.size(); #endif bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; D3D11_SUBRESOURCE_DATA InitData; ZeroMemory(&InitData, sizeof(InitData)); if (object->isArmatureDeformed() && !softBody) InitData.pSysMem = vertices.data(); else InitData.pSysMem = skinnedVertices.data(); wiRenderer::graphicsDevice->CreateBuffer(&bd, &InitData, &meshVertBuff); ZeroMemory(&bd, sizeof(bd)); bd.Usage = D3D11_USAGE_IMMUTABLE; bd.ByteWidth = sizeof(unsigned int) * indices.size(); bd.BindFlags = D3D11_BIND_INDEX_BUFFER; bd.CPUAccessFlags = 0; ZeroMemory(&InitData, sizeof(InitData)); InitData.pSysMem = indices.data(); wiRenderer::graphicsDevice->CreateBuffer(&bd, &InitData, &meshIndexBuff); if (renderable) { if (object->isArmatureDeformed() && !softBody) { ZeroMemory(&bd, sizeof(bd)); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof(Vertex) * vertices.size(); bd.BindFlags = D3D11_BIND_STREAM_OUTPUT | D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.StructureByteStride = 0; wiRenderer::graphicsDevice->CreateBuffer(&bd, NULL, &sOutBuffer); } //PHYSICALMAPPING if (!physicsverts.empty()) { for (unsigned int i = 0; i < vertices.size(); ++i) { for (unsigned int j = 0; j < physicsverts.size(); ++j) { if (fabs(vertices[i].pos.x - physicsverts[j].x) < FLT_EPSILON && fabs(vertices[i].pos.y - physicsverts[j].y) < FLT_EPSILON && fabs(vertices[i].pos.z - physicsverts[j].z) < FLT_EPSILON ) { physicalmapGP.push_back(j); break; } } } } } buffersComplete = true; } } void Mesh::CreateVertexArrays() { if (skinnedVertices.empty()) { skinnedVertices.resize(vertices.size()); for (unsigned int i = 0; i= (int)instances.size()) { instances.resize((instances.size() + 1) * 2); } instances[numerator] = instance; } void Mesh::UpdateRenderableInstances(int count, DeviceContext context) { wiRenderer::UpdateBuffer(meshInstanceBuffer, instances.data(), context, sizeof(Instance)*count); } #pragma endregion #pragma region MODEL Model::Model() { } Model::~Model() { CleanUp(); } void Model::CleanUp() { for (Armature* x : armatures) { SAFE_DELETE(x); } for (Object* x : objects) { for (wiEmittedParticle* y : x->eParticleSystems) { SAFE_DELETE(y); } for (wiHairParticle* y : x->hParticleSystems) { SAFE_DELETE(y); } SAFE_DELETE(x); } for (Light* x : lights) { SAFE_DELETE(x); } for (Decal* x : decals) { SAFE_DELETE(x); } } void Model::LoadFromDisk(const string& dir, const string& name, const string& identifier) { stringstream directory(""), armatureFilePath(""), materialLibFilePath(""), meshesFilePath(""), objectsFilePath("") , actionsFilePath(""), lightsFilePath(""), decalsFilePath(""); directory << dir; armatureFilePath << name << ".wia"; materialLibFilePath << name << ".wim"; meshesFilePath << name << ".wi"; objectsFilePath << name << ".wio"; actionsFilePath << name << ".wiact"; lightsFilePath << name << ".wil"; decalsFilePath << name << ".wid"; LoadWiArmatures(directory.str(), armatureFilePath.str(), identifier, armatures); LoadWiMaterialLibrary(directory.str(), materialLibFilePath.str(), identifier, "textures/", materials); LoadWiMeshes(directory.str(), meshesFilePath.str(), identifier, meshes, armatures, materials); LoadWiObjects(directory.str(), objectsFilePath.str(), identifier, objects, armatures, meshes, materials); LoadWiActions(directory.str(), actionsFilePath.str(), identifier, armatures); LoadWiLights(directory.str(), lightsFilePath.str(), identifier, lights); LoadWiDecals(directory.str(), decalsFilePath.str(), "textures/", decals); vector transforms(0); transforms.reserve(armatures.size() + objects.size() + lights.size() + decals.size()); for (Armature* x : armatures) { if (x->actions.size() > 1) { // If it has actions besides the identity, activate the first by default x->GetPrimaryAnimation()->ChangeAction(1); } transforms.push_back(x); } for (Object* x : objects) { transforms.push_back(x); for (wiEmittedParticle* e : x->eParticleSystems) { if (e->light != nullptr) { lights.push_back(e->light); } } } for (Light* x : lights) { x->SetUp(); transforms.push_back(x); } for (Decal* x : decals) { transforms.push_back(x); } // Match loaded parenting information for (Transform* x : transforms) { for (Transform* y : transforms) { if (x != y && x->parentName.length() > 0 && !x->parentName.compare(y->name)) { // Match parent XMFLOAT4X4 saved_parent_rest_inv = x->parent_inv_rest; x->attachTo(y); x->parent_inv_rest = saved_parent_rest_inv; break; } } if (x->parent != nullptr && x->parentName.length() > 0 && x->boneParent.length() > 0) { // Match Bone parent Armature* armature = dynamic_cast(x->parent); if (armature != nullptr) { // Only if the current parent is an Armature! for (Bone* b : armature->boneCollection) { if (!b->name.compare(x->boneParent)) { XMFLOAT4X4 saved_parent_rest_inv = x->parent_inv_rest; x->attachTo(b); x->parent_inv_rest = saved_parent_rest_inv; break; } } } } if (x->parent == nullptr) { x->attachTo(this); } } // Set up Render data for (Object* x : objects) { if (x->mesh) { // Ribbon trails if (x->mesh->trailInfo.base >= 0 && x->mesh->trailInfo.tip >= 0) { D3D11_BUFFER_DESC bd; ZeroMemory(&bd, sizeof(bd)); bd.Usage = D3D11_USAGE_DYNAMIC; bd.ByteWidth = sizeof(RibbonVertex) * 1000; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; wiRenderer::graphicsDevice->CreateBuffer(&bd, NULL, &x->trailBuff); x->trailTex = wiTextureHelper::getInstance()->getTransparent(); x->trailDistortTex = wiTextureHelper::getInstance()->getNormalMapDefault(); } // Mesh renderdata setup x->mesh->CreateVertexArrays(); x->mesh->Optimize(); x->mesh->CreateBuffers(x); } } } void Model::UpdateModel() { for (MaterialCollection::iterator iter = materials.begin(); iter != materials.end(); ++iter) { Material* iMat = iter->second; iMat->framesToWaitForTexCoordOffset -= 1.0f; if (iMat->framesToWaitForTexCoordOffset <= 0) { iMat->texMulAdd.z += iMat->movingTex.x*wiRenderer::GetGameSpeed(); iMat->texMulAdd.w += iMat->movingTex.y*wiRenderer::GetGameSpeed(); iMat->framesToWaitForTexCoordOffset = iMat->movingTex.z*wiRenderer::GetGameSpeed(); } } for (Armature* x : armatures) { x->UpdateArmature(); } for (Object* x : objects) { x->UpdateObject(); } for (Light*x : lights) { x->UpdateLight(); } list::iterator iter = decals.begin(); while (iter != decals.end()) { Decal* decal = *iter; decal->UpdateDecal(); if (decal->life>-2) { if (decal->life <= 0) { decal->detach(); decals.erase(iter++); delete decal; continue; } } ++iter; } } #pragma endregion #pragma region AABB AABB::AABB(){ for(int i=0;i<8;++i) corners[i]=XMFLOAT3(0,0,0); } AABB::AABB(const XMFLOAT3& min, const XMFLOAT3& max){ create(min,max); } void AABB::createFromHalfWidth(const XMFLOAT3& center, const XMFLOAT3& halfwidth){ XMFLOAT3 min = XMFLOAT3(center.x-halfwidth.x,center.y-halfwidth.y,center.z-halfwidth.z); XMFLOAT3 max = XMFLOAT3(center.x+halfwidth.x,center.y+halfwidth.y,center.z+halfwidth.z); create(min,max); } void AABB::create(const XMFLOAT3& min, const XMFLOAT3& max){ corners[0]=min; corners[1]=XMFLOAT3(min.x,max.y,min.z); corners[2]=XMFLOAT3(min.x,max.y,max.z); corners[3]=XMFLOAT3(min.x,min.y,max.z); corners[4]=XMFLOAT3(max.x,min.y,min.z); corners[5]=XMFLOAT3(max.x,max.y,min.z); corners[6]=max; corners[7]=XMFLOAT3(max.x,min.y,max.z); } AABB AABB::get(const XMMATRIX& mat){ AABB ret; XMFLOAT3 min,max; for(int i=0;i<8;++i){ XMVECTOR point = XMVector3Transform( XMLoadFloat3(&corners[i]), mat ); XMStoreFloat3(&ret.corners[i],point); } min=ret.corners[0]; max=ret.corners[6]; for(int i=0;i<8;++i){ XMFLOAT3& p=ret.corners[i]; if(p.xmax.x) max.x=p.x; if(p.y>max.y) max.y=p.y; if(p.z>max.z) max.z=p.z; } ret.create(min,max); return ret; } AABB AABB::get(const XMFLOAT4X4& mat){ return get(XMLoadFloat4x4(&mat)); } XMFLOAT3 AABB::getMin()const {return corners[0];} XMFLOAT3 AABB::getMax() const{return corners[6];} XMFLOAT3 AABB::getCenter() const{ XMFLOAT3 min=getMin(),max=getMax(); return XMFLOAT3((min.x+max.x)*0.5f,(min.y+max.y)*0.5f,(min.z+max.z)*0.5f); } XMFLOAT3 AABB::getHalfWidth() const{ XMFLOAT3 max=getMax(),center=getCenter(); return XMFLOAT3(abs(max.x-center.x),abs(max.y-center.y),abs(max.z-center.z)); } float AABB::getArea() const{ XMFLOAT3 _min = getMin(); XMFLOAT3 _max = getMax(); return (_max.x-_min.x)*(_max.y-_min.y)*(_max.z-_min.z); } float AABB::getRadius() const{ XMFLOAT3& abc=getHalfWidth(); return max(max(abc.x,abc.y),abc.z); } AABB::INTERSECTION_TYPE AABB::intersects(const AABB& b) const{ XMFLOAT3 aMin = getMin(), aMax=getMax(); XMFLOAT3 bMin = b.getMin(), bMax=b.getMax(); if( bMin.x >= aMin.x && bMax.x <= aMax.x && bMin.y >= aMin.y && bMax.y <= aMax.y && bMin.z >= aMin.z && bMax.z <= aMax.z ) { return INSIDE; } if( aMax.x < bMin.x || aMin.x > bMax.x ) return OUTSIDE; if( aMax.y < bMin.y || aMin.y > bMax.y ) return OUTSIDE; if( aMax.z < bMin.z || aMin.z > bMax.z ) return OUTSIDE; return INTERSECTS; } bool AABB::intersects(const XMFLOAT3& p) const{ XMFLOAT3 max=getMax(); XMFLOAT3 min=getMin(); if (p.x>max.x) return false; if (p.xmax.y) return false; if (p.ymax.z) return false; if (p.z= tmin; } AABB AABB::operator* (float a) { XMFLOAT3 min = getMin(); XMFLOAT3 max = getMax(); min.x*=a; min.y*=a; min.z*=a; max.x*=a; max.y*=a; max.z*=a; return AABB(min,max); } #pragma endregion #pragma region SPHERE bool SPHERE::intersects(const AABB& b){ XMFLOAT3 min = b.getMin(); XMFLOAT3 max = b.getMax(); XMFLOAT3 closestPointInAabb = wiMath::Min(wiMath::Max(center, min), max); double distanceSquared = wiMath::Distance(closestPointInAabb,center); return distanceSquared < radius; } bool SPHERE::intersects(const SPHERE& b){ return wiMath::Distance(center,b.center)<=radius+b.radius; } #pragma endregion #pragma region RAY bool RAY::intersects(const AABB& box) const{ return box.intersects(*this); } #pragma endregion #pragma region HITSPHERE BufferResource HitSphere::vertexBuffer=nullptr; void HitSphere::SetUpStatic() { const int numVert = (RESOLUTION+1)*2; vector verts(0); for(int i=0;i<=RESOLUTION;++i){ float alpha = (float)i/(float)RESOLUTION*2*3.14159265359f; verts.push_back(XMFLOAT3A(XMFLOAT3A(sin(alpha),cos(alpha),0))); verts.push_back(XMFLOAT3A(XMFLOAT3A(0,0,0))); } D3D11_BUFFER_DESC bd; ZeroMemory( &bd, sizeof(bd) ); bd.Usage = D3D11_USAGE_IMMUTABLE; bd.ByteWidth = sizeof( XMFLOAT3A )*verts.size(); bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; D3D11_SUBRESOURCE_DATA InitData; ZeroMemory( &InitData, sizeof(InitData) ); InitData.pSysMem = verts.data(); wiRenderer::graphicsDevice->CreateBuffer( &bd, &InitData, &vertexBuffer ); } void HitSphere::CleanUpStatic() { if(vertexBuffer){ vertexBuffer->Release(); vertexBuffer=NULL; } } void HitSphere::UpdateTransform() { Transform::UpdateTransform(); //getMatrix(); center = translation; radius = radius_saved*scale.x; } #pragma endregion #pragma region BONE XMMATRIX Bone::getMatrix(int getTranslation, int getRotation, int getScale) { return XMMatrixTranslation(0,0,length)*XMLoadFloat4x4(&world); } void Bone::UpdateTransform() { //Transform::UpdateTransform(); // Needs to be updated differently than regular Transforms for (Transform* child : children) { child->UpdateTransform(); } } #pragma endregion #pragma region ANIMATIONLAYER AnimationLayer::AnimationLayer() { name = ""; activeAction = prevAction = 0; ResetAction(); ResetActionPrev(); playing = true; blendCurrentFrame = 0.0f; blendFrames = 0.0f; blendFact = 0.0f; currentFramePrevAction = 0.0f; weight = 1.0f; type = ANIMLAYER_TYPE_ADDITIVE; looped = true; } void AnimationLayer::ChangeAction(int actionIndex, float blendFrames, float weight) { currentFramePrevAction = currentFrame; ResetAction(); prevAction = activeAction; activeAction = actionIndex; this->blendFrames = blendFrames; blendFact = 0.0f; blendCurrentFrame = 0.0f; this->weight = weight; } void AnimationLayer::ResetAction() { currentFrame = 1; } void AnimationLayer::ResetActionPrev() { currentFramePrevAction = 1; } void AnimationLayer::PauseAction() { playing = false; } void AnimationLayer::StopAction() { ResetAction(); PauseAction(); } void AnimationLayer::PlayAction() { playing = true; } #pragma endregion #pragma region ARMATURE Armature::~Armature() { actions.clear(); for (Bone* b : boneCollection) { SAFE_DELETE(b); } boneCollection.clear(); rootbones.clear(); for (auto& x : animationLayers) { SAFE_DELETE(x); } animationLayers.clear(); } void Armature::UpdateTransform() { Transform::UpdateTransform(); // calculate frame for (Bone* root : rootbones) { RecursiveBoneTransform(this, root, getMatrix()); } } void Armature::UpdateArmature() { for (auto& x : animationLayers) { AnimationLayer& anim = *x; // current action float cf = anim.currentFrame; int maxCf = 0; int activeAction = anim.activeAction; int prevAction = anim.prevAction; float frameInc = (anim.playing ? wiRenderer::GetGameSpeed() : 0.f); cf = anim.currentFrame += frameInc; maxCf = actions[activeAction].frameCount; if ((int)cf > maxCf) { if (anim.looped) { anim.ResetAction(); cf = anim.currentFrame; } else { anim.currentFrame = cf = (float)maxCf; } } // prev action float cfPrevAction = anim.currentFramePrevAction; int maxCfPrevAction = actions[prevAction].frameCount; cfPrevAction = anim.currentFramePrevAction += frameInc; if ((int)cfPrevAction > maxCfPrevAction) { if (anim.looped) { anim.ResetActionPrev(); cfPrevAction = anim.currentFramePrevAction; } else { anim.currentFramePrevAction = cfPrevAction = (float)maxCfPrevAction; } } // blending anim.blendCurrentFrame += frameInc; if (abs(anim.blendFrames) > 0) anim.blendFact = wiMath::Clamp(anim.blendCurrentFrame / anim.blendFrames, 0, 1); else anim.blendFact = 1; } } void Armature::RecursiveBoneTransform(Armature* armature, Bone* bone, const XMMATRIX& parentCombinedMat) { Bone* parent = (Bone*)bone->parent; // TRANSITION BLENDING + ADDITIVE BLENDING XMVECTOR& finalTrans = XMVectorSet(0, 0, 0, 0); XMVECTOR& finalRotat = XMQuaternionIdentity(); XMVECTOR& finalScala = XMVectorSet(1, 1, 1, 0); for (auto& x : armature->animationLayers) { AnimationLayer& anim = *x; float cf = anim.currentFrame, cfPrev = anim.currentFramePrevAction; int activeAction = anim.activeAction, prevAction = anim.prevAction; int maxCf = armature->actions[activeAction].frameCount, maxCfPrev = armature->actions[prevAction].frameCount; XMVECTOR& prevTrans = InterPolateKeyFrames(cfPrev, maxCfPrev, bone->actionFrames[prevAction].keyframesPos, POSITIONKEYFRAMETYPE); XMVECTOR& prevRotat = InterPolateKeyFrames(cfPrev, maxCfPrev, bone->actionFrames[prevAction].keyframesRot, ROTATIONKEYFRAMETYPE); XMVECTOR& prevScala = InterPolateKeyFrames(cfPrev, maxCfPrev, bone->actionFrames[prevAction].keyframesSca, SCALARKEYFRAMETYPE); XMVECTOR& currTrans = InterPolateKeyFrames(cf, maxCf, bone->actionFrames[activeAction].keyframesPos, POSITIONKEYFRAMETYPE); XMVECTOR& currRotat = InterPolateKeyFrames(cf, maxCf, bone->actionFrames[activeAction].keyframesRot, ROTATIONKEYFRAMETYPE); XMVECTOR& currScala = InterPolateKeyFrames(cf, maxCf, bone->actionFrames[activeAction].keyframesSca, SCALARKEYFRAMETYPE); float blendFact = anim.blendFact; switch (anim.type) { case AnimationLayer::ANIMLAYER_TYPE_PRIMARY: finalTrans = XMVectorLerp(prevTrans, currTrans, blendFact); finalRotat = XMQuaternionSlerp(prevRotat, currRotat, blendFact); finalScala = XMVectorLerp(prevScala, currScala, blendFact); break; case AnimationLayer::ANIMLAYER_TYPE_ADDITIVE: finalTrans = XMVectorLerp(finalTrans, XMVectorAdd(finalTrans, XMVectorLerp(prevTrans, currTrans, blendFact)), anim.weight); finalRotat = XMQuaternionSlerp(finalRotat, XMQuaternionMultiply(finalRotat, XMQuaternionSlerp(prevRotat, currRotat, blendFact)), anim.weight); // normalize? finalScala = XMVectorLerp(finalScala, XMVectorMultiply(finalScala, XMVectorLerp(prevScala, currScala, blendFact)), anim.weight); break; default: break; } } XMVectorSetW(finalTrans, 1); XMVectorSetW(finalScala, 1); bone->worldPrev = bone->world; bone->translationPrev = bone->translation; bone->rotationPrev = bone->rotation; XMStoreFloat3(&bone->translation, finalTrans); XMStoreFloat4(&bone->rotation, finalRotat); XMStoreFloat3(&bone->scale, finalScala); XMMATRIX& anim = XMMatrixScalingFromVector(finalScala) * XMMatrixRotationQuaternion(finalRotat) * XMMatrixTranslationFromVector(finalTrans); XMMATRIX& rest = XMLoadFloat4x4(&bone->world_rest); XMMATRIX& boneMat = anim * rest * parentCombinedMat ; XMMATRIX& finalMat = XMLoadFloat4x4(&bone->recursiveRestInv)* boneMat ; XMStoreFloat4x4(&bone->world, boneMat); bone->boneRelativityPrev = bone->boneRelativity; XMStoreFloat4x4(&bone->boneRelativity, finalMat); for (unsigned int i = 0; ichildrenI.size(); ++i) { RecursiveBoneTransform(armature, bone->childrenI[i], boneMat); } // Because bones are not updated in the regular Transform fashion, a separate update needs to be called bone->UpdateTransform(); } XMVECTOR Armature::InterPolateKeyFrames(float cf, const int maxCf, const vector& keyframeList, KeyFrameType type) { XMVECTOR result = XMVectorSet(0, 0, 0, 0); if (type == POSITIONKEYFRAMETYPE) result = XMVectorSet(0, 0, 0, 1); if (type == ROTATIONKEYFRAMETYPE) result = XMVectorSet(0, 0, 0, 1); if (type == SCALARKEYFRAMETYPE) result = XMVectorSet(1, 1, 1, 1); //SEARCH 2 INTERPOLATABLE FRAMES int nearest[2] = { 0,0 }; int first = 0, last = 0; if (keyframeList.size()>1) { first = keyframeList[0].frameI; last = keyframeList.back().frameI; if (cf <= first) { //BROKEN INTERVAL nearest[0] = 0; nearest[1] = 0; } else if (cf >= last) { nearest[0] = keyframeList.size() - 1; nearest[1] = keyframeList.size() - 1; } else { //IN BETWEEN TWO KEYFRAMES, DECIDE WHICH for (int k = keyframeList.size() - 1; k>0; k--) if (keyframeList[k].frameI <= cf) { nearest[0] = k; break; } for (unsigned int k = 0; k= cf) { nearest[1] = k; break; } } //INTERPOLATE BETWEEN THE TWO FRAMES int keyframes[2] = { keyframeList[nearest[0]].frameI, keyframeList[nearest[1]].frameI }; float interframe = 0; if (cf <= first || cf >= last) { //BROKEN INTERVAL float intervalBegin = (float)(maxCf - keyframes[0]); float intervalEnd = keyframes[1] + intervalBegin; float intervalLen = abs(intervalEnd - intervalBegin); float offsetCf = cf + intervalBegin; if (intervalLen) interframe = offsetCf / intervalLen; } else { float intervalBegin = (float)keyframes[0]; float intervalEnd = (float)keyframes[1]; float intervalLen = abs(intervalEnd - intervalBegin); float offsetCf = cf - intervalBegin; if (intervalLen) interframe = offsetCf / intervalLen; } if (type == ROTATIONKEYFRAMETYPE) { XMVECTOR quat[2] = { XMLoadFloat4(&keyframeList[nearest[0]].data), XMLoadFloat4(&keyframeList[nearest[1]].data) }; result = XMQuaternionNormalize(XMQuaternionSlerp(quat[0], quat[1], interframe)); } else { XMVECTOR tran[2] = { XMLoadFloat4(&keyframeList[nearest[0]].data), XMLoadFloat4(&keyframeList[nearest[1]].data) }; result = XMVectorLerp(tran[0], tran[1], interframe); } } else { if (!keyframeList.empty()) result = XMLoadFloat4(&keyframeList.back().data); } return result; } void Armature::ChangeAction(const string& actionName, float blendFrames, const string& animLayer, float weight) { AnimationLayer* anim = GetPrimaryAnimation(); if (animLayer.length() > 0) { anim = GetAnimLayer(animLayer); } if (actionName.length() > 0) { for (unsigned int i = 1; i < actions.size(); ++i) { if (!actions[i].name.compare(actionName)) { anim->ChangeAction(i, blendFrames, weight); return; } } } // Fall back to identity action anim->ChangeAction(0, blendFrames, weight); } AnimationLayer* Armature::GetAnimLayer(const string& name) { for (auto& x : animationLayers) { if (!x->name.compare(name)) { return x; } } animationLayers.push_back(new AnimationLayer); animationLayers.back()->name = name; return animationLayers.back(); } void Armature::AddAnimLayer(const string& name) { for (auto& x : animationLayers) { if (!x->name.compare(name)) { return; } } animationLayers.push_back(new AnimationLayer); animationLayers.back()->name = name; } void Armature::DeleteAnimLayer(const string& name) { auto i = animationLayers.begin(); while (i != animationLayers.end()) { if ((*i)->type != AnimationLayer::ANIMLAYER_TYPE_PRIMARY && !(*i)->name.compare(name)) { animationLayers.erase(i++); } else { ++i; } } } #pragma endregion #pragma region TRANSFORM Transform::~Transform() { detach(); detachChild(); } //void Transform::DeleteTree(Transform* transform) //{ // if (transform == nullptr) // { // return; // } // // for (auto* x : transform->children) // { // DeleteTree(x); // } // delete transform; //} XMMATRIX Transform::getMatrix(int getTranslation, int getRotation, int getScale){ return XMLoadFloat4x4(&world); //worldPrev=world; //translationPrev=translation; //scalePrev=scale; //rotationPrev=rotation; //XMVECTOR s = XMLoadFloat3(&scale_rest); //XMVECTOR r = XMLoadFloat4(&rotation_rest); //XMVECTOR t = XMLoadFloat3(&translation_rest); //XMMATRIX& w = // XMMatrixScalingFromVector(s)* // XMMatrixRotationQuaternion(r)* // XMMatrixTranslationFromVector(t) // ; //XMStoreFloat4x4( &world_rest,w ); //if(parent!=nullptr) //{ // w = w * XMLoadFloat4x4(&parent_inv_rest) * parent->getMatrix(); // XMVECTOR v[3]; // XMMatrixDecompose(&v[0],&v[1],&v[2],w); // XMStoreFloat3( &scale,v[0] ); // XMStoreFloat4( &rotation,v[1] ); // XMStoreFloat3( &translation,v[2] ); // XMStoreFloat4x4( &world, w ); //} //else //{ // world = world_rest; // translation=translation_rest; // rotation=rotation_rest; // scale=scale_rest; //} //return w; } //attach to parent void Transform::attachTo(Transform* newParent, int copyTranslation, int copyRotation, int copyScale){ if (newParent != nullptr) { if (parent != nullptr) { detach(); } parent = newParent; parentName = newParent->name; copyParentT = copyTranslation; copyParentR = copyRotation; copyParentS = copyScale; XMStoreFloat4x4(&parent_inv_rest, XMMatrixInverse(nullptr, parent->getMatrix(copyParentT, copyParentR, copyParentS))); parent->children.insert(this); } } Transform* Transform::find(const string& findname) { if (!name.compare(findname)) { return this; } for (Transform* x : children) { if (x != nullptr) { Transform* found = x->find(findname); if (found != nullptr) { return found; } } } return nullptr; } //detach child - detach all if no parameters void Transform::detachChild(Transform* child){ if(child==nullptr){ if (children.empty()) { return; } vector delChildren(children.begin(), children.end()); for(Transform* c : delChildren){ if(c!=nullptr){ c->detach(); } } children.clear(); } else{ if( children.find(child)!=children.end() ){ child->detach(); } } } //detach from parent void Transform::detach(){ if(parent!=nullptr){ if(parent->children.find(this)!=parent->children.end()){ parent->children.erase(this); } applyTransform(copyParentT,copyParentR,copyParentS); } parent=nullptr; } void Transform::applyTransform(int t, int r, int s){ if(t) translation_rest=translation; if(r) rotation_rest=rotation; if(s) scale_rest=scale; } void Transform::transform(const XMFLOAT3& t, const XMFLOAT4& r, const XMFLOAT3& s){ translation_rest.x+=t.x; translation_rest.y+=t.y; translation_rest.z+=t.z; XMStoreFloat4(&rotation_rest,XMQuaternionNormalize(XMQuaternionMultiply(XMLoadFloat4(&rotation_rest),XMLoadFloat4(&r)))); scale_rest.x*=s.x; scale_rest.y*=s.y; scale_rest.z*=s.z; UpdateTransform(); } void Transform::transform(const XMMATRIX& m){ XMVECTOR v[3]; if(XMMatrixDecompose(&v[0],&v[1],&v[2],m)){ XMFLOAT3 t,s; XMFLOAT4 r; XMStoreFloat3(&s,v[0]); XMStoreFloat4(&r,v[1]); XMStoreFloat3(&t,v[2]); transform(t,r,s); } } void Transform::UpdateTransform() { worldPrev = world; translationPrev = translation; scalePrev = scale; rotationPrev = rotation; XMVECTOR s = XMLoadFloat3(&scale_rest); XMVECTOR r = XMLoadFloat4(&rotation_rest); XMVECTOR t = XMLoadFloat3(&translation_rest); XMMATRIX& w = XMMatrixScalingFromVector(s)* XMMatrixRotationQuaternion(r)* XMMatrixTranslationFromVector(t) ; XMStoreFloat4x4(&world_rest, w); if (parent != nullptr) { w = w * XMLoadFloat4x4(&parent_inv_rest) * parent->getMatrix(); XMVECTOR v[3]; XMMatrixDecompose(&v[0], &v[1], &v[2], w); XMStoreFloat3(&scale, v[0]); XMStoreFloat4(&rotation, v[1]); XMStoreFloat3(&translation, v[2]); XMStoreFloat4x4(&world, w); } else { world = world_rest; translation = translation_rest; rotation = rotation_rest; scale = scale_rest; } for (Transform* child : children) { child->UpdateTransform(); } } void Transform::Translate(const XMFLOAT3& value) { transform(value); } void Transform::RotateRollPitchYaw(const XMFLOAT3& value) { // This needs to be handled a bit differently XMVECTOR quat = XMLoadFloat4(&rotation_rest); XMVECTOR x = XMQuaternionRotationRollPitchYaw(value.x, 0, 0); XMVECTOR y = XMQuaternionRotationRollPitchYaw(0, value.y, 0); XMVECTOR z = XMQuaternionRotationRollPitchYaw(0, 0, value.z); quat = XMQuaternionMultiply(x, quat); quat = XMQuaternionMultiply(quat, y); quat = XMQuaternionMultiply(z, quat); XMStoreFloat4(&rotation_rest, quat); UpdateTransform(); } void Transform::Rotate(const XMFLOAT4& quaternion) { transform(XMFLOAT3(0, 0, 0), quaternion); } void Transform::Scale(const XMFLOAT3& value) { transform(XMFLOAT3(0, 0, 0), XMFLOAT4(0, 0, 0, 1), value); } Transform* Transform::GetRoot() { if (parent != nullptr) { return parent->GetRoot(); } return this; } #pragma endregion #pragma region Decals Decal::Decal(const XMFLOAT3& tra, const XMFLOAT3& sca, const XMFLOAT4& rot, const string& tex, const string& nor):Cullable(),Transform(){ scale_rest=scale=sca; rotation_rest=rotation=rot; translation_rest=translation=tra; UpdateTransform(); texture=normal=nullptr; addTexture(tex); addNormal(nor); life = -2; //persistent fadeStart=0; } Decal::~Decal() { wiResourceManager::GetGlobal()->del(texName); wiResourceManager::GetGlobal()->del(norName); } void Decal::addTexture(const string& tex){ texName=tex; if(!tex.empty()){ texture = (TextureView)wiResourceManager::GetGlobal()->add(tex); } } void Decal::addNormal(const string& nor){ norName=nor; if(!nor.empty()){ normal = (TextureView)wiResourceManager::GetGlobal()->add(nor); } } void Decal::UpdateTransform() { Transform::UpdateTransform(); XMMATRIX rotMat = XMMatrixRotationQuaternion(XMLoadFloat4(&rotation)); XMVECTOR eye = XMLoadFloat3(&translation); XMVECTOR frontV = XMVector3Transform(XMVectorSet(0, 0, 1, 0), rotMat); XMStoreFloat3(&front, frontV); XMVECTOR at = XMVectorAdd(eye, frontV); XMVECTOR up = XMVector3Transform(XMVectorSet(0, 1, 0, 0), rotMat); XMStoreFloat4x4(&view, XMMatrixLookAtLH(eye, at, up)); XMStoreFloat4x4(&projection, XMMatrixOrthographicLH(scale.x, scale.y, -scale.z * 0.5f, scale.z * 0.5f)); XMStoreFloat4x4(&world_rest, XMMatrixScalingFromVector(XMLoadFloat3(&scale))*rotMat*XMMatrixTranslationFromVector(eye)); bounds.createFromHalfWidth(XMFLOAT3(0, 0, 0), XMFLOAT3(scale.x, scale.y, scale.z)); bounds = bounds.get(XMLoadFloat4x4(&world_rest)); } void Decal::UpdateDecal() { if (life>-2) { life -= wiRenderer::GetGameSpeed(); } } #pragma endregion #pragma region CAMERA void Camera::UpdateTransform() { Transform::UpdateTransform(); //getMatrix(); UpdateProps(); } #pragma endregion #pragma region OBJECT Object::~Object() { SAFE_RELEASE(trailBuff); } void Object::EmitTrail(const XMFLOAT3& col, float fadeSpeed) { if (mesh != nullptr) { int base = mesh->trailInfo.base; int tip = mesh->trailInfo.tip; int x = trail.size(); if (base >= 0 && tip >= 0) { XMFLOAT4 baseP, tipP; XMFLOAT4 newCol = XMFLOAT4(col.x, col.y, col.z, 1); baseP = wiRenderer::TransformVertex(mesh, base).pos; tipP = wiRenderer::TransformVertex(mesh, tip).pos; trail.push_back(RibbonVertex(XMFLOAT3(baseP.x, baseP.y, baseP.z), XMFLOAT2(0,0), XMFLOAT4(0, 0, 0, 1),fadeSpeed)); trail.push_back(RibbonVertex(XMFLOAT3(tipP.x, tipP.y, tipP.z), XMFLOAT2(0,0), newCol,fadeSpeed)); } } } void Object::FadeTrail() { for (unsigned int j = 0; j0) trail[j].col.x = trail[j].col.x - fade*(wiRenderer::GetGameSpeed() + wiRenderer::GetGameSpeed()*(1 - j % 2) * 2); else trail[j].col.x = 0; if (trail[j].col.y>0) trail[j].col.y = trail[j].col.y - fade*(wiRenderer::GetGameSpeed() + wiRenderer::GetGameSpeed()*(1 - j % 2) * 2); else trail[j].col.y = 0; if (trail[j].col.z>0) trail[j].col.z = trail[j].col.z - fade*(wiRenderer::GetGameSpeed() + wiRenderer::GetGameSpeed()*(1 - j % 2) * 2); else trail[j].col.z = 0; if (trail[j].col.w>0) trail[j].col.w -= fade*wiRenderer::GetGameSpeed(); else trail[j].col.w = 0; #if 0 // Collapse trail... perhaps will be needed if (j % 2 == 0) { trail[j].pos = wiMath::Lerp(trail[j].pos, trail[j + 1].pos, trail[j].fade * wiRenderer::GetGameSpeed()); trail[j + 1].pos = wiMath::Lerp(trail[j + 1].pos, trail[j].pos, trail[j + 1].fade * wiRenderer::GetGameSpeed()); } #endif } while (!trail.empty() && trail.front().col.w <= 0) { trail.pop_front(); } } void Object::UpdateTransform() { Transform::UpdateTransform(); } void Object::UpdateObject() { XMMATRIX world = getMatrix(); if (mesh->isBillboarded) { XMMATRIX bbMat = XMMatrixIdentity(); if (mesh->billboardAxis.x || mesh->billboardAxis.y || mesh->billboardAxis.z) { float angle = 0; angle = (float)atan2(translation.x - wiRenderer::getCamera()->translation.x, translation.z - wiRenderer::getCamera()->translation.z) * (180.0f / XM_PI); bbMat = XMMatrixRotationAxis(XMLoadFloat3(&mesh->billboardAxis), angle * 0.0174532925f); } else bbMat = XMMatrixInverse(0, XMMatrixLookAtLH(XMVectorSet(0, 0, 0, 0), XMVectorSubtract(XMLoadFloat3(&translation), wiRenderer::getCamera()->GetEye()), XMVectorSet(0, 1, 0, 0))); XMMATRIX w = XMMatrixScalingFromVector(XMLoadFloat3(&scale)) * bbMat * XMMatrixRotationQuaternion(XMLoadFloat4(&rotation)) * XMMatrixTranslationFromVector(XMLoadFloat3(&translation) ); XMStoreFloat4x4(&this->world, w); } if (mesh->softBody) bounds = mesh->aabb; else if (!mesh->isBillboarded && mesh->renderable) { bounds = mesh->aabb.get(world); } else if (mesh->renderable) bounds.createFromHalfWidth(translation, scale); if (!trail.empty()) { wiRenderer::objectsWithTrails.push_back(this); FadeTrail(); } for (wiEmittedParticle* x : eParticleSystems) { x->Update(wiRenderer::GetGameSpeed()); wiRenderer::emitterSystems.push_back(x); } } #pragma endregion #pragma region LIGHT vector Light::shadowMaps_pointLight; vector Light::shadowMaps_spotLight; Light::~Light() { shadowCam.clear(); //shadowMap.clear(); shadowMaps_dirLight.clear(); lensFlareRimTextures.clear(); for (string x : lensFlareNames) wiResourceManager::GetGlobal()->del(x); lensFlareNames.clear(); } void Light::SetUp() { if (!shadowCam.empty()) return; if (type == Light::DIRECTIONAL) { float lerp = 0.5f; float lerp1 = 0.12f; float lerp2 = 0.016f; XMVECTOR a0, a, b0, b; a0 = XMVector3Unproject(XMVectorSet(0, (float)wiRenderer::GetScreenHeight(), 0, 1), 0, 0, (float)wiRenderer::GetScreenWidth(), (float)wiRenderer::GetScreenHeight(), 0.1f, 1.0f, wiRenderer::getCamera()->GetProjection(), wiRenderer::getCamera()->GetView(), XMMatrixIdentity()); a = XMVector3Unproject(XMVectorSet(0, (float)wiRenderer::GetScreenHeight(), 1, 1), 0, 0, (float)wiRenderer::GetScreenWidth(), (float)wiRenderer::GetScreenHeight(), 0.1f, 1.0f, wiRenderer::getCamera()->GetProjection(), wiRenderer::getCamera()->GetView(), XMMatrixIdentity()); b0 = XMVector3Unproject(XMVectorSet((float)wiRenderer::GetScreenWidth(), (float)wiRenderer::GetScreenHeight(), 0, 1), 0, 0, (float)wiRenderer::GetScreenWidth(), (float)wiRenderer::GetScreenHeight(), 0.1f, 1.0f, wiRenderer::getCamera()->GetProjection(), wiRenderer::getCamera()->GetView(), XMMatrixIdentity()); b = XMVector3Unproject(XMVectorSet((float)wiRenderer::GetScreenWidth(), (float)wiRenderer::GetScreenHeight(), 1, 1), 0, 0, (float)wiRenderer::GetScreenWidth(), (float)wiRenderer::GetScreenHeight(), 0.1f, 1.0f, wiRenderer::getCamera()->GetProjection(), wiRenderer::getCamera()->GetView(), XMMatrixIdentity()); float size = XMVectorGetX(XMVector3Length(XMVectorSubtract(XMVectorLerp(b0, b, lerp), XMVectorLerp(a0, a, lerp)))); float size1 = XMVectorGetX(XMVector3Length(XMVectorSubtract(XMVectorLerp(b0, b, lerp1), XMVectorLerp(a0, a, lerp1)))); float size2 = XMVectorGetX(XMVector3Length(XMVectorSubtract(XMVectorLerp(b0, b, lerp2), XMVectorLerp(a0, a, lerp2)))); XMVECTOR rot = XMQuaternionIdentity(); shadowCam.push_back(SHCAM(size, rot, 0, wiRenderer::getCamera()->zFarP)); shadowCam.push_back(SHCAM(size1, rot, 0, wiRenderer::getCamera()->zFarP)); shadowCam.push_back(SHCAM(size2, rot, 0, wiRenderer::getCamera()->zFarP)); } else if (type == Light::SPOT && shadow) { shadowCam.push_back(SHCAM(XMFLOAT4(0, 0, 0, 1), wiRenderer::getCamera()->zNearP, enerDis.y, enerDis.z)); } else if (type == Light::POINT && shadow) { shadowCam.push_back(SHCAM(XMFLOAT4(0.5f, -0.5f, -0.5f, -0.5f), wiRenderer::getCamera()->zNearP, enerDis.y, XM_PI / 2.0f)); //+x shadowCam.push_back(SHCAM(XMFLOAT4(0.5f, 0.5f, 0.5f, -0.5f), wiRenderer::getCamera()->zNearP, enerDis.y, XM_PI / 2.0f)); //-x shadowCam.push_back(SHCAM(XMFLOAT4(1, 0, 0, -0), wiRenderer::getCamera()->zNearP, enerDis.y, XM_PI / 2.0f)); //+y shadowCam.push_back(SHCAM(XMFLOAT4(0, 0, 0, -1), wiRenderer::getCamera()->zNearP, enerDis.y, XM_PI / 2.0f)); //-y shadowCam.push_back(SHCAM(XMFLOAT4(0.707f, 0, 0, -0.707f), wiRenderer::getCamera()->zNearP, enerDis.y, XM_PI / 2.0f)); //+z shadowCam.push_back(SHCAM(XMFLOAT4(0, 0.707f, 0.707f, 0), wiRenderer::getCamera()->zNearP, enerDis.y, XM_PI / 2.0f)); //-z } } void Light::UpdateTransform() { Transform::UpdateTransform(); } void Light::UpdateLight() { //Shadows if (type == Light::DIRECTIONAL) { float lerp = 0.5f;//third slice distance from cam (percentage) float lerp1 = 0.12f;//second slice distance from cam (percentage) float lerp2 = 0.016f;//first slice distance from cam (percentage) XMVECTOR c, d, e, e1, e2; c = XMVector3Unproject(XMVectorSet((float)wiRenderer::GetScreenWidth() * 0.5f, (float)wiRenderer::GetScreenHeight() * 0.5f, 1, 1), 0, 0, (float)wiRenderer::GetScreenWidth(), (float)wiRenderer::GetScreenHeight(), 0.1f, 1.0f, wiRenderer::getCamera()->GetProjection(), wiRenderer::getCamera()->GetView(), XMMatrixIdentity()); d = XMVector3Unproject(XMVectorSet((float)wiRenderer::GetScreenWidth() * 0.5f, (float)wiRenderer::GetScreenHeight() * 0.5f, 0, 1), 0, 0, (float)wiRenderer::GetScreenWidth(), (float)wiRenderer::GetScreenHeight(), 0.1f, 1.0f, wiRenderer::getCamera()->GetProjection(), wiRenderer::getCamera()->GetView(), XMMatrixIdentity()); if (!shadowCam.empty()) { float f = shadowCam[0].size / (float)wiRenderer::SHADOWMAPRES; e = XMVectorFloor(XMVectorLerp(d, c, lerp) / f)*f; f = shadowCam[1].size / (float)wiRenderer::SHADOWMAPRES; e1 = XMVectorFloor(XMVectorLerp(d, c, lerp1) / f)*f; f = shadowCam[2].size / (float)wiRenderer::SHADOWMAPRES; e2 = XMVectorFloor(XMVectorLerp(d, c, lerp2) / f)*f; XMMATRIX rrr = XMMatrixRotationQuaternion(XMLoadFloat4(&rotation_rest)); shadowCam[0].Update(rrr*XMMatrixTranslationFromVector(e)); if (shadowCam.size()>1) { shadowCam[1].Update(rrr*XMMatrixTranslationFromVector(e1)); if (shadowCam.size()>2) shadowCam[2].Update(rrr*XMMatrixTranslationFromVector(e2)); } } bounds.createFromHalfWidth(wiRenderer::getCamera()->translation, XMFLOAT3(10000, 10000, 10000)); } else if (type == Light::SPOT) { if (!shadowCam.empty()) { shadowCam[0].Update(XMLoadFloat4x4(&world)); } bounds.createFromHalfWidth(translation, XMFLOAT3(enerDis.y, enerDis.y, enerDis.y)); } else if (type == Light::POINT) { for (unsigned int i = 0; i