void EEPFILE::eeLoadModelName(uint8_t id,char*buf,uint8_t len) { if(id<MAX_MODELS) { //eeprom_read_block(buf,(void*)modelEeOfs(id),sizeof(g_model.name)); memset(buf,' ',len); *buf='0'+(id+1)/10; buf++; *buf='0'+(id+1)%10; buf++; *buf=':'; buf++;buf++; if(!eeModelExists(id)) // make sure we don't add junk { *buf=0; //terminate str return; } theFile->openRd(FILE_MODEL(id)); uint16_t res = theFile->readRlc((uint8_t*)buf,sizeof(ModelData().name)); if(res == sizeof(ModelData().name) ) { //buf+=len-5; for(int i=0; i<(len-4); i++) { if(*buf==0) *buf=' '; buf++; } *buf=0;buf--; uint16_t sz=theFile->size(FILE_MODEL(id)); while(sz){ --buf; *buf='0'+sz%10; sz/=10;} } } }
ModelData DiscreteObject::getModel(){ return ModelData(B, A, k, noiseRatio); }
World::World(WindowFramework* windowFrameworkPtr) : m_windowFrameworkPtr(windowFrameworkPtr) { // preconditions if(m_windowFrameworkPtr == NULL) { nout << "ERROR: parameter windowFrameworkPtr cannot be NULL." << endl; return; } // This code puts the standard title and instruction text on screen COnscreenText title("title", COnscreenText::TS_plain); title.set_text("Panda3D: Tutorial - Joint Manipulation"); title.set_fg(Colorf(1,1,1,1)); title.set_pos(LVecBase2f(0.7, -0.95)); title.set_scale(0.07); title.reparent_to(m_windowFrameworkPtr->get_aspect_2d()); m_titleNp = title.generate(); m_esckeyTextNp = gen_label_text("ESC: Quit" , 0); m_onekeyTextNp = gen_label_text("[1]: Teapot" , 1); m_twokeyTextNp = gen_label_text("[2]: Candy cane", 2); m_threekeyTextNp = gen_label_text("[3]: Banana" , 3); m_fourkeyTextNp = gen_label_text("[4]: Sword" , 4); // setup key input m_windowFrameworkPtr->enable_keyboard(); m_windowFrameworkPtr->get_panda_framework()->define_key("escape", "Exit" , sys_exit , NULL); m_windowFrameworkPtr->get_panda_framework()->define_key("1" , "Teapot" , call_set_object<M_teapot >, this); m_windowFrameworkPtr->get_panda_framework()->define_key("2" , "CandyCane", call_set_object<M_candy_cane>, this); m_windowFrameworkPtr->get_panda_framework()->define_key("3" , "Banana" , call_set_object<M_banana >, this); m_windowFrameworkPtr->get_panda_framework()->define_key("4" , "Sword" , call_set_object<M_sword >, this); // Disable mouse-based camera-control // Note: disable by default in C++ // Position the camera m_windowFrameworkPtr->get_camera_group().set_pos(0,-15, 2); // Load our animated character // Note: File eve_walk.egg is broken! // The name of the animation is case sensitive and at line 13 of file // eve_walk.egg you should read `Eve' instead of `eve'. You need to // correct this in order to bind the animation automatically using // auto_bind() or WindowFramework::loop_animations(). Or you can use // PartGroup::HMF_ok_wrong_root_name to ask auto_bind() to be more // forgiving. CActor::AnimMap eveAnims; eveAnims["../models/eve_walk"].push_back("walk"); m_eve.load_actor(m_windowFrameworkPtr, "../models/eve", &eveAnims, PartGroup::HMF_ok_wrong_root_name); // Put it in the scene NodePath renderNp = m_windowFrameworkPtr->get_render(); m_eve.reparent_to(renderNp); // Now we use control_joint to get a NodePath that's in control of her neck // This must be done before any animations are played m_eveNeckNp = m_eve.control_joint("Neck"); // We now play an animation. An animation must be played, or at least posed // for the nodepath we just got from control_joint to actually effect the model m_eve.find_anim("walk")->set_play_rate(2); m_eve.loop("walk", true); // Now we add a task that will take care of turning the head PT(GenericAsyncTask) turnHeadTask = new GenericAsyncTask("turnHead", call_turn_head, this); if(turnHeadTask != NULL) { AsyncTaskManager::get_global_ptr()->add(turnHeadTask); } // Now we will expose the joint the hand joint. ExposeJoint allows us to // get the position of a joint while it is animating. This is different than // control_joint which stops that joint from animating but lets us move it. // This is particularly useful for putting an object (like a weapon) in an // actor's hand m_eveRightHandNp = m_eve.expose_joint("RightHand"); // This is a table with models, positions, rotations, and scales of objects to // be attached to our exposed joint. These are stock models and so they needed // to be repositioned to look right. vector<ModelData> positions(M_models); positions[M_teapot ] = ModelData("../models/teapot" , LVecBase3f(0.00,-0.66,-0.95), LVecBase3f(90, 0,90), 0.40); positions[M_candy_cane] = ModelData("../models/candycane", LVecBase3f(0.15,-0.99,-0.22), LVecBase3f(90, 0,90), 1.00); positions[M_banana ] = ModelData("../models/banana" , LVecBase3f(0.08,-0.10, 0.09), LVecBase3f( 0,-90, 0), 1.75); positions[M_sword ] = ModelData("../models/sword" , LVecBase3f(0.11, 0.19, 0.06), LVecBase3f( 0, 0,90), 1.00); // A list that will store our models objects m_modelsNp.reserve(M_models); NodePath modelsNp = m_windowFrameworkPtr->get_panda_framework()->get_models(); for(vector<ModelData>::iterator i = positions.begin(); i < positions.end(); ++i) { // Load the model NodePath np = m_windowFrameworkPtr->load_model(modelsNp, i->m_filename); // Position it np.set_pos(i->m_pos); // Rotate it np.set_hpr(i->m_hpr); // Scale it np.set_scale(i->m_scale); // Reparent the model to the exposed joint. That way when the joint moves, // the model we just loaded will move with it. np.reparent_to(m_eveRightHandNp); // Add it to our models list m_modelsNp.push_back(np); } // Make object 0 the first shown set_object(M_teapot); // Put in some default lighting setup_lights(); }
ModelData ModelLoader::Load(const std::vector<std::uint8_t>& fileData, const char* type) { Assimp::Importer importer; const aiScene* scene = importer.ReadFileFromMemory( fileData.data(), fileData.size(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals | aiProcess_CalcTangentSpace | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices | aiProcess_ImproveCacheLocality, type); if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) return ModelData(); // Used for creating the boundingBox glm::vec3 minPoint, maxPoint; auto processMesh = [&minPoint, &maxPoint](aiMesh* mesh, const aiScene* scene) -> MeshData { (void) scene; MeshData mData; for (std::uint32_t i = 0; i < mesh->mNumVertices; ++i) { VertexData vertexData; // Vertices const aiVector3D& vert = mesh->mVertices[i]; vertexData.vx = vert.x; vertexData.vy = vert.y; vertexData.vz = vert.z; // Normals const aiVector3D& norm = mesh->mNormals[i]; vertexData.nx = norm.x; vertexData.ny = norm.y; vertexData.nz = norm.z; if(mesh->HasTangentsAndBitangents()) { // Tangents const aiVector3D& tan = mesh->mTangents[i]; vertexData.tnx = tan.x; vertexData.tny = tan.y; vertexData.tnz = tan.z; } // TODO: think if we need the 'else' part //else {} // Texture coordinates if (mesh->mTextureCoords[0]) { const aiVector3D& texCoord = mesh->mTextureCoords[0][i]; vertexData.tx = texCoord.x; vertexData.ty = texCoord.y; } else { vertexData.tx = 0; vertexData.ty = 0; } // AABB minPoint if (vert.x < minPoint.x) minPoint.x = vert.x; if (vert.y < minPoint.y) minPoint.y = vert.y; if (vert.z < minPoint.z) minPoint.z = vert.z; // AABB maxPoint if (vert.x > maxPoint.x) maxPoint.x = vert.x; if (vert.y > maxPoint.y) maxPoint.y = vert.y; if (vert.z > maxPoint.z) maxPoint.z = vert.z; // Material index mData.meshIndex = mesh->mMaterialIndex; mData.data.push_back(vertexData); } // Indices for (std::uint32_t i = 0; i < mesh->mNumFaces; ++i) { aiFace face = mesh->mFaces[i]; for (std::uint32_t j = 0; j < face.mNumIndices; ++j) mData.indices.push_back(face.mIndices[j]); } // Material if (scene->HasMaterials()) { aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; if (material) { auto texTypes = {aiTextureType_DIFFUSE, aiTextureType_SPECULAR, aiTextureType_NORMALS, aiTextureType_NONE}; for (auto type : texTypes) { std::uint32_t texCount = material->GetTextureCount(type); for (std::uint32_t i = 0; i < texCount; ++i) { aiString str; material->GetTexture(type, i, &str); // TODO } } } } return mData; }; std::function<ModelData(aiNode*, const aiScene*)> processNode = [&processMesh, &processNode](aiNode* node, const aiScene* scene) -> ModelData { ModelData model; // Process all the node's meshes for (std::uint32_t i = 0; i < node->mNumMeshes; ++i) { aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; model.meshes.push_back(processMesh(mesh, scene)); } // Same for its children for (std::uint32_t i = 0; i < node->mNumChildren; ++i) { ModelData childModel = processNode(node->mChildren[i], scene); for (auto& mesh : childModel.meshes) model.meshes.push_back(std::move(mesh)); } return model; }; ModelData model = processNode(scene->mRootNode, scene); model.boundingBox = AABB(minPoint, maxPoint); return model; }
ModelData ModelIdentification::identify(double w, double u, double y){ // stałe pierwszego zbiornika: double A1 = 0.7329; double H1 = 4.6526; double kv1 = 0.2113; // stałe drugiego zbiornika: double tgalfa2 = 4.2687; double kv2 = 0.4336; // punkt pracy: // pierwszego zbiornika: // 1. punktu pracy pierwszego zbiornika nie można dokłądnie określić. // poprawne wyznaczenie punktu pracy jest szczegulnie ważne w chwili przelania. // orientacyjnie przyjmujemy punkt pracy do którego dążymy. //double h1 = pow(2, w/kv1); // 2. drobna symulacja ktora jest niżej // można sobie na nią pozwolić ponieważ w stanie ustalonym wszystkie błędy i tak znikną double h1 = temp; // 3. próba średniej ważonej obu pomysłów: //double w1 = 100; //double w2 = sampleTime; // waga zależna od czasu próbkowania: //double h1 = (temp * w1 + pow(2, w/kv1) * w2) / (w1 + w2); // drugiego zbiornika: // punkt pracy drugiego zbiornika to dokładnie jego wypływ. double q20 = y; //parametry pierwszego zbiornika: double b10; double a11; double op1; // obliczenie wypływu z pierwszego zbiornika na podstawie punktu pracy: double q10 = sqrt(h1) * kv1; // sprawdzenie czy zbiornika jest pełny: bool fullTank = ( h1 >= H1 ); if (!fullTank) { // dla niepelnego zbiornika: // transmitancja ciagla pierwszego zbiornika: // K(s) = k / (1 + sT) double T1 = A1 * 2 * q10 / (kv1 * kv1); double k1 = 1; // transmitancja dyskretna pierwszego zbiornika: // H(z^-1) = b0 / (1 + a1*(z^-1) a11 = - pow(M_E, - (sampleTime / T1)); b10 = k1 * (1 + a11); op1 = 1; } else { // dla pelnego zbiornika: // transmitancja ciagla pierwszego zbiornika: // K(s) = k / (1 + sT) // k1 = 1; // T1 = 0; // K(s) = 1; // transmitancja dyskretna pierwszego zbiornika: // H(z^-1) = b0 / (1 + a1*(z^-1)) a11 = 0; b10 = 1; op1 = 0; // H(z^-1) = 1; } // aktualizacja punktu pracy: h1 = h1 + (u - q10)/A1 * sampleTime; // sprawdzenie przepełnienia i pustego: h1 = h1 < 0 ? 0 : (h1 > H1 ? H1 : h1); // aktualizacja zmiennej prywatnej: temp = h1; // transmitancja ciagla drugiego zbiornika w punkcie pracy: // K(s) = k / (1 + sT) double T2 = ( 2 * M_PI * pow(q20,5) ) / ( tgalfa2 * tgalfa2 * pow(kv2,6) ); double k2 = 1; // transmitancja dyskretna drugiego zbiornika w punkcie pracy: // H(z^-1) = b0 / (1 + a1*(z^-1)) double a21 = - pow(M_E, - (sampleTime / T2)); double b20 = k2 * (1 + a21); double op2 = 1; // transmitancja końcowa: double b0 = b10 * b20; double a0 = 1; double a1 = a11 + a21; double a2 = a11 * a21; double op = op1 + op2; std::vector<double> B; std::vector<double> A; B.push_back(b0); A.push_back(a0); A.push_back(a1); A.push_back(a2); //std::cout << ModelData(B, A, op) << "\n"; return ModelData(B, A, op); // mamy model drugiego rzędu z opóźnieniem równym 2 // lub model pierwszego rzędu z opóźnieniem równym 1 // więc w sumie to jest to niestacjonarność... }
void CBloodFlower::TurnEffectsOff(u32 effect, CStateManager& mgr) { ModelData()->AnimationData()->SetParticleEffectState(sFireEffects[effect], false, mgr); }