예제 #1
0
파일: skeleton.cpp 프로젝트: rainChu/openmw
void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent)
{
    Ogre::Bone *bone;
    if(!skel->hasBone(node->name))
        bone = skel->createBone(node->name);
    else
        bone = skel->createBone();
    if(parent) parent->addChild(bone);
    mNifToOgreHandleMap[node->recIndex] = bone->getHandle();

    bone->setOrientation(node->trafo.rotation);
    bone->setPosition(node->trafo.pos);
    bone->setScale(Ogre::Vector3(node->trafo.scale));
    bone->setBindingPose();

    if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */
         node->recType == Nif::RC_RootCollisionNode || /* handled in nifbullet (hopefully) */
         node->recType == Nif::RC_NiTriShape || /* Handled in the mesh loader */
         node->recType == Nif::RC_NiBSAnimationNode || /* Handled in the object loader */
         node->recType == Nif::RC_NiBillboardNode || /* Handled in the object loader */
         node->recType == Nif::RC_NiBSParticleNode ||
         node->recType == Nif::RC_NiCamera ||
         node->recType == Nif::RC_NiAutoNormalParticles ||
         node->recType == Nif::RC_NiRotatingParticles
         ))
        warn("Unhandled "+node->recName+" "+node->name+" in "+skel->getName());

    Nif::ControllerPtr ctrl = node->controller;
    while(!ctrl.empty())
    {
        if(!(ctrl->recType == Nif::RC_NiParticleSystemController ||
             ctrl->recType == Nif::RC_NiVisController ||
             ctrl->recType == Nif::RC_NiUVController ||
             ctrl->recType == Nif::RC_NiKeyframeController ||
             ctrl->recType == Nif::RC_NiGeomMorpherController
             ))
            warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName());
        ctrl = ctrl->next;
    }

    const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
    if(ninode)
    {
        const Nif::NodeList &children = ninode->children;
        for(size_t i = 0;i < children.length();i++)
        {
            if(!children[i].empty())
                buildBones(skel, children[i].getPtr(), bone);
        }
    }
}
예제 #2
0
void CAnimatedEntity::moveBone(const std::string &bone, float pitch) {
    Ogre::Bone * entityBone = _entity->getSkeleton()->getBone(bone);
    entityBone->reset();

    Ogre::Skeleton * skel = _entity->getSkeleton();

    //entityBone->setManuallyControlled(true);

    unsigned short boneHandle = entityBone->getHandle();
    Ogre::AnimationStateIterator animStateIt = _entity->getAllAnimationStates()->getAnimationStateIterator();

    while( animStateIt.hasMoreElements() )
    {
        Ogre::AnimationState *pAnimState = animStateIt.getNext();
        // ignore disabled animations
        skel->getAnimation(pAnimState->getAnimationName())->destroyNodeTrack(boneHandle);
    }

    entityBone->pitch(Ogre::Radian(pitch));
}
예제 #3
0
void EMDOgre::createOgreMesh(EMDSubmesh *submesh, string mesh_name) {
	string ogre_mesh_name = mesh_name + "_" + submesh->getMaterialName();
	Ogre::MeshPtr ogre_mesh = Ogre::MeshManager::getSingleton().createManual(ogre_mesh_name, XENOVIEWER_RESOURCE_GROUP);

	LibXenoverse::AABB mesh_aabb;
	mesh_aabb.reset();

	if (skeleton) {
		ogre_mesh->setSkeletonName(skeleton->getName());
	}

	// Create Vertex Pool
	vector<EMDVertex> submesh_vertices = submesh->getVertices();
	const size_t nVertices = submesh_vertices.size();
	const size_t nVertCount = 8;
	const size_t vbufCount = nVertCount*nVertices;
	float *vertices = (float *)malloc(sizeof(float)*vbufCount);
	for (size_t i = 0; i < nVertices; i++) {
		vertices[i*nVertCount] = submesh_vertices[i].x;
		vertices[i*nVertCount + 1] = submesh_vertices[i].y;
		vertices[i*nVertCount + 2] = submesh_vertices[i].z;
		vertices[i*nVertCount + 3] = submesh_vertices[i].nx;
		vertices[i*nVertCount + 4] = submesh_vertices[i].ny;
		vertices[i*nVertCount + 5] = submesh_vertices[i].nz;
		vertices[i*nVertCount + 6] = submesh_vertices[i].u;
		vertices[i*nVertCount + 7] = submesh_vertices[i].v;
		mesh_aabb.addPoint(submesh_vertices[i].x, submesh_vertices[i].y, submesh_vertices[i].z);
	}

	// Create Submeshes for each Triangle List
	vector<EMDTriangles> submesh_triangles = submesh->getTriangles();
	for (size_t i = 0; i < submesh_triangles.size(); i++) {
		Ogre::SubMesh *sub = createOgreSubmesh(&submesh_triangles[i], ogre_mesh);
	}

	// Create Shared Vertex Data for all submeshes
	Ogre::VertexData *vertex_data = new Ogre::VertexData();
	ogre_mesh->sharedVertexData = vertex_data;
	vertex_data->vertexCount = nVertices;

	Ogre::VertexDeclaration* decl = vertex_data->vertexDeclaration;
	size_t offset = 0;

	decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

	decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);

	decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
	offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);

	Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(offset, nVertices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
	vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
	Ogre::VertexBufferBinding* bind = vertex_data->vertexBufferBinding;
	bind->setBinding(0, vbuf);


	// Create Bone Assignments if Skeleton name exists
	if (skeleton) {
		Ogre::Skeleton *ogre_skeleton = skeleton->getOgreSkeleton();
		if (ogre_skeleton) {
			for (size_t i = 0; i < submesh_triangles.size(); i++) {
				EMDTriangles *triangles = &submesh_triangles[i];
				vector<unsigned int> vertex_indices;
				size_t face_count = triangles->faces.size();

				// Make a list of all vertex indices being used in the submesh
				vertex_indices.reserve(face_count);
				for (size_t j = 0; j < face_count; j++) {
					bool found = false;

					for (size_t k = 0; k < vertex_indices.size(); k++) {
						if (vertex_indices[k] == triangles->faces[j]) {
							found = true;
							break;
						}
					}

					if (!found) vertex_indices.push_back(triangles->faces[j]);
				}

				// Build Bone Mapping Table
				vector<unsigned short> bone_table;
				bone_table.resize(triangles->bone_names.size());

				for (size_t j = 0; j < bone_table.size(); j++) {
					string bone_name = triangles->bone_names[j];

					LOG_DEBUG("Bone Skin Table %d: %s\n", j, bone_name.c_str());
					if (ogre_skeleton->hasBone(bone_name)) {
						Ogre::Bone *mBone = ogre_skeleton->getBone(bone_name);
						bone_table[j] = mBone->getHandle();
					}
					else {
						LOG_DEBUG("Couldn't find %s in ogre skeleton!\n", bone_name.c_str());
					}
				}

				// Add bone assignments to all the vertices that were found
				for (size_t j = 0; j < vertex_indices.size(); j++) {
					Ogre::VertexBoneAssignment vba;
					vba.vertexIndex = vertex_indices[j];
					EMDVertex *vertex = &submesh_vertices[vba.vertexIndex];

					for (size_t k = 0; k < 4; k++) {
						unsigned char bone_index = vertex->bone[3 - k];
						float bone_weight = vertex->bone_weight[k];

						if (bone_weight > 0.0f) {
							vba.boneIndex = bone_table[bone_index];
							vba.weight = bone_weight;
							ogre_mesh->addBoneAssignment(vba);
						}
					}
				}
			}

			// Apply changes, build the buffer
			ogre_mesh->_compileBoneAssignments();
			ogre_mesh->sharedVertexData->reorganiseBuffers(decl->getAutoOrganisedDeclaration(true, false, false));
		}
	}

	//ogre_mesh->_setBounds(Ogre::AxisAlignedBox(mesh_aabb.start_x, mesh_aabb.start_y, mesh_aabb.start_z, mesh_aabb.end_x, mesh_aabb.end_y, mesh_aabb.end_z));
	ogre_mesh->_setBounds(Ogre::AxisAlignedBox(-1000, -1000, -1000, 1000, 1000, 1000));
	ogre_mesh->_setBoundingSphereRadius(mesh_aabb.sizeMax());
	ogre_mesh->load();

	free(vertices);

	created_meshes.push_back(ogre_mesh_name);
}
예제 #4
0
void NPCCharacter::_actionLook(const Ogre::Vector3& target)
{
	Ogre::Bone* headBone;
	std::string n = _node->getName();
	Ogre::Skeleton* skel = static_cast<Ogre::Entity*>(_movableObject)->getSkeleton();
	headBone = skel->getBone("Bip01_Head");

	headBone->setManuallyControlled(true);
	headBone->setInheritOrientation(true);
	int nAnim = skel->getNumAnimations();

	//have to do this to allow the head to turn properly.
	for(int i = 0; i < nAnim; ++i)
	{
		skel->getAnimation(i)->destroyNodeTrack(headBone->getHandle());
	}

	Ogre::Vector3 test = headBone->_getDerivedPosition() * CHARACTER_SCALE_FACTOR + _node->getPosition();
	Ogre::Vector3 dir = target - test;
	Ogre::Quaternion nodeRot,boneRot;
	Ogre::Euler boneEuler; boneEuler.setDirection(dir,true,false);
	/*boneRot = _node->convertLocalToWorldOrientation(_node->getOrientation()) * headBone->_getDerivedOrientation();
	Ogre::Vector3 boneTest = boneRot * Ogre::Vector3::UNIT_Z;*/
	//Ogre::Vector3 boneTest = headBone->getOrientation() * Ogre::Vector3::UNIT_Z;

	//turns the direction vector into a 2D normalized vector on the X/Z axis.
	dir.y = 0;
	dir.normalise();

	//All of this ray query stuff is to make sure that the AI can "see" the target before attempting to look at it.
	Ogre::SceneManager* scene = _node->getCreator();
	Ogre::Ray ray(headBone->_getDerivedPosition() * CHARACTER_SCALE_FACTOR + _node->getPosition(),dir);

	Ogre::RaySceneQuery* query = scene->createRayQuery(ray);
	query->setSortByDistance(true);
	query->setQueryMask(CHARACTER_MASK | SCENERY_MASK);

	Ogre::RaySceneQueryResult results = query->execute();

	bool withinView = false;
	if(results.size() == 0)
	{
		withinView = true;
	}
	else
	{
		if(results.begin()->movable->getParentNode()->getName() == getName())
		{
			if(results.size() == 1)
			{
				withinView = true;
			}
		}
		
		if(!withinView && results.size() > 1 && std::next(results.begin())->distance > test.distance(target))
		{
			withinView = true;
		}
	}

	scene->destroyQuery(query);

	if(withinView)
	{
		Ogre::Euler node;
		Ogre::Euler t = headOrientation.getRotationTo(dir);
		t.limitYaw(Ogre::Radian(3.0));
		t.limitPitch(Ogre::Radian(0.0));

		headOrientation = headOrientation + t;
		headOrientation.limitYaw(Ogre::Degree(100));
		headOrientation.limitPitch(Ogre::Degree(60));

		headBone->setOrientation(headOrientation);

		/*headBone->rotate(boneTest.getRotationTo(dir),Ogre::Node::TS_WORLD);

		Ogre::Quaternion boneRotation = _node->convertLocalToWorldOrientation(_node->getOrientation()) * headBone->_getDerivedOrientation() * (Ogre::Quaternion(Ogre::Degree(180),Ogre::Vector3::UNIT_Y));
		Ogre::Quaternion nodeRotation = _node->_getDerivedOrientation();
		Ogre::Quaternion diff = nodeRotation.Inverse() * boneRotation;*/
	}

	_isActFinished = true;
}