Beispiel #1
0
ObjVertGroup EERIE_OBJECT_GetGroup(const EERIE_3DOBJ * obj, const std::string & groupname) {
	
	if(!obj)
		return ObjVertGroup();
	
	for(size_t i = 0; i < obj->grouplist.size(); i++) {
		if(obj->grouplist[i].name == groupname) {
			return ObjVertGroup(i);
		}
	}
	
	return ObjVertGroup();
}
Beispiel #2
0
void Entity::destroy() {
	
	LogDebug("destroying entity " << idString());
	
	if(instance() > 0 && !(ioflags & IO_NOSAVE)) {
		if(scriptload) {
			// In case we previously saved this entity...
			currentSavedGameRemoveEntity(idString());
		} else {
			currentSavedGameStoreEntityDeletion(idString());
		}
	}
	
	if(obj) {
		while(!obj->linked.empty()) {
			if(obj->linked[0].lgroup != ObjVertGroup() && obj->linked[0].obj) {
				Entity * linked = obj->linked[0].io;
				if(linked && ValidIOAddress(linked)) {
					EERIE_LINKEDOBJ_UnLinkObjectFromObject(obj, linked->obj);
					linked->destroy();
				}
			}
		}
	}
	
	delete this;
	
}
Beispiel #3
0
void EERIE_Object_Precompute_Fast_Access(EERIE_3DOBJ * eerie) {
	
	if(!eerie)
		return;

	// GetActionPointIdx(eerie, "v_right");
	// GetActionPointIdx(eerie, "u_right");
	// GetActionPointIdx(eerie, "carry_attach");
	// EERIE_OBJECT_GetGroup(eerie, "jaw");
	// EERIE_OBJECT_GetGroup(eerie, "mouth all");
	
	eerie->fastaccess.view_attach       = GetActionPointIdx(eerie, "view_attach");
	eerie->fastaccess.primary_attach    = GetActionPointIdx(eerie, "primary_attach");
	eerie->fastaccess.left_attach       = GetActionPointIdx(eerie, "left_attach");
	eerie->fastaccess.weapon_attach     = GetActionPointIdx(eerie, "weapon_attach");
	eerie->fastaccess.secondary_attach  = GetActionPointIdx(eerie, "secondary_attach");
	eerie->fastaccess.fire              = GetActionPointIdx(eerie, "fire");
	
	eerie->fastaccess.head_group = EERIE_OBJECT_GetGroup(eerie, "head");

	if(eerie->fastaccess.head_group == ObjVertGroup())
		eerie->fastaccess.head_group_origin = -1;
	else
	{
		long lHeadOrigin  = eerie->grouplist[eerie->fastaccess.head_group.handleData()].origin;
		eerie->fastaccess.head_group_origin = checked_range_cast<short>(lHeadOrigin);
	}
	
	eerie->fastaccess.sel_head     = EERIE_OBJECT_GetSelection(eerie, "head");
	eerie->fastaccess.sel_chest    = EERIE_OBJECT_GetSelection(eerie, "chest");
	eerie->fastaccess.sel_leggings = EERIE_OBJECT_GetSelection(eerie, "leggings");
}
Beispiel #4
0
ObjVertGroup GetActionPointGroup(const EERIE_3DOBJ * eobj, ActionPoint idx) {
	
	if(!eobj)
		return ObjVertGroup();
	
	for(long i = eobj->grouplist.size() - 1; i >= 0; i--) {
		const std::vector<size_t> & indices = eobj->grouplist[i].indexes;
		for(size_t j = 0; j < indices.size(); j++){
			if(long(indices[j]) == idx.handleData()) {
				return ObjVertGroup(i);
			}
		}
	}
	
	return ObjVertGroup();
}
Beispiel #5
0
/*!
 * \brief Apply animation and draw object
 */
static void Cedric_AnimateDrawEntity(Skeleton & skeleton, AnimLayer * animlayer,
                                     EERIE_EXTRA_ROTATE * extraRotation,
                                     AnimationBlendStatus * animBlend,
                                     EERIE_EXTRA_SCALE & extraScale) {
	
	// Initialize the rig
	for(size_t i = 0; i != skeleton.bones.size(); i++) {
		Bone & bone = skeleton.bones[i];

		bone.init.quat = glm::quat();
		bone.init.trans = bone.transinit_global;
	}

	// Apply Extra Rotations in Local Space
	if(extraRotation) {
		for(size_t k = 0; k < MAX_EXTRA_ROTATE; k++) {
			ObjVertGroup i = extraRotation->group_number[k];

			if(i != ObjVertGroup()) {
				size_t boneIndex = size_t(i.handleData());
				skeleton.bones[boneIndex].init.quat = angleToQuatForExtraRotation(extraRotation->group_rotate[k]);
			}
		}
	}

	// Perform animation in Local space
	Cedric_AnimateObject(&skeleton, animlayer);

	if(extraScale.groupIndex != ObjVertGroup()) {
		size_t boneIndex = size_t(extraScale.groupIndex.handleData());
		Bone & bone = skeleton.bones[boneIndex];

		bone.init.scale += extraScale.scale;
	}

	// Check for Animation Blending in Local space
	if(animBlend) {
		// Is There any Between-Animations Interpolation to make ?
		Cedric_BlendAnimation(skeleton, animBlend);

		for(size_t i = 0; i < skeleton.bones.size(); i++) {
			skeleton.bones[i].last = skeleton.bones[i].init;
		}
	}
}
Beispiel #6
0
static void Cedric_AnimateDrawEntityRender(EERIE_3DOBJ * eobj, const Vec3f & pos,
                                           Entity * io, float invisibility) {
	
	Skeleton *obj = eobj->m_skeleton;
	
	if(!obj)
		return;
	
	ColorMod colorMod;
	colorMod.updateFromEntity(io);
	
	/* Get nearest lights */
	Vec3f tv = pos;
	
	if(io && io->obj->fastaccess.head_group_origin != ObjVertHandle()) {
		tv.y = io->obj->vertexlist3[io->obj->fastaccess.head_group_origin.handleData()].v.y + 10;
	} else {
		tv.y -= 90.f;
	}
	
	ShaderLight lights[llightsSize];
	int lightsCount;
	UpdateLlights(lights, lightsCount, tv, false);
	
	Cedric_ApplyLighting(lights, lightsCount, eobj, obj, colorMod);
	
	Cedric_RenderObject(eobj, obj, io, pos, invisibility);
	
	// Now we can render Linked Objects
	for(size_t k = 0; k < eobj->linked.size(); k++) {
		const EERIE_LINKED & link = eobj->linked[k];
		
		if(link.lgroup == ObjVertGroup() || !link.obj)
			continue;
		
		// specific check to avoid drawing player weapon on its back when in subjective view
		if(io == entities.player() &&
			link.lidx == entities.player()->obj->fastaccess.weapon_attach &&
			!EXTERNALVIEW
		) {
			continue;
		}
		
		TransformInfo t(
			actionPointPosition(eobj, link.lidx),
			eobj->m_skeleton->bones[link.lgroup.handleData()].anim.quat,
			link.io ? link.io->scale : 1.f,
			link.obj->vertexlist[link.lidx2.handleData()].v - link.obj->vertexlist[link.obj->origin].v);
		
		DrawEERIEInter(link.obj, t, link.io, true, invisibility);
	}
}
void EERIEDrawAnimQuatUpdate(EERIE_3DOBJ * eobj,
                             AnimLayer * animlayer,
                             const Anglef & angle,
                             const Vec3f & pos,
                             AnimationDuration time,
                             Entity * io,
                             bool update_movement
) {

	ARX_PROFILE_FUNC();
	
	if(io) {
		float speedfactor = io->basespeed + io->speed_modif;

		if(speedfactor < 0)
			speedfactor = 0;

		AnimationDuration tim = time * speedfactor;

		if(tim <= AnimationDuration_ZERO)
			time = AnimationDuration_ZERO;
		else
			time = tim;
	}

	if(time > AnimationDuration_ZERO) {
		for(size_t count = 0; count < MAX_ANIM_LAYERS; count++) {
			AnimLayer & layer = animlayer[count];
			if(layer.cur_anim)
				PrepareAnim(layer, time, io);
		}
	}

	// Set scale and invisibility factors
	// Scaling Value for this object (Movements will also be scaled)
	float scale = (io) ? io->scale : 1.f;

	// Only layer 0 controls movement
	Vec3f ftr = CalcTranslation(animlayer[0]);


	if(update_movement)
		StoreEntityMovement(io, ftr, scale);

	if(io && io != entities.player() && !Cedric_IO_Visible(io->pos))
		return;

	glm::quat rotation;

	bool isNpc = io && (io->ioflags & IO_NPC);
	if(!isNpc) {
		// To correct invalid angle in Animated FIX/ITEMS
		rotation = glm::toQuat(toRotationMatrix(angle));
	} else {
		rotation = QuatFromAngles(angle);
	}

	EERIE_EXTRA_ROTATE * extraRotation = NULL;
	AnimationBlendStatus * animBlend = NULL;

	if(io && (io->ioflags & IO_NPC) && io->_npcdata->ex_rotate) {
		extraRotation = io->_npcdata->ex_rotate;
	}

	if(io) {
		animBlend = &io->animBlend;
	}

	EERIE_EXTRA_SCALE extraScale;

	if(BH_MODE && eobj->fastaccess.head_group != ObjVertGroup()) {
		extraScale.groupIndex = eobj->fastaccess.head_group;
		extraScale.scale = Vec3f_ONE;
	}

	arx_assert(eobj->m_skeleton);
	Skeleton & skeleton = *eobj->m_skeleton;

	Cedric_AnimateDrawEntity(skeleton, animlayer, extraRotation, animBlend, extraScale);

	// Build skeleton in Object Space
	TransformInfo t(pos, rotation, scale, ftr);
	Cedric_ConcatenateTM(skeleton, t);

	Cedric_TransformVerts(eobj, pos);
	if(io) {
		io->bbox3D = UpdateBbox3d(eobj);
	}

	Cedric_ViewProjectTransform(eobj);
	if(io) {
		io->bbox2D = Cedric_UpdateBbox2d(*eobj);
	}
}
Beispiel #8
0
// Converts a Theo Object to an EERIE object
static EERIE_3DOBJ * TheoToEerie(const char * adr, long size, const res::path & texpath, const res::path & fic) {
	
	LogWarning << "TheoToEerie " << fic;
	
	if(!adr)
		return NULL;
	
	res::path txpath = texpath.empty() ? "graph/obj3d/textures" : texpath;
	
	if(size < 10) {
		return NULL;
	}
	
	size_t pos = 0;
	
	const THEO_HEADER * pth = reinterpret_cast<const THEO_HEADER *>(adr + pos);
	pos += sizeof(THEO_HEADER);
	
	if(pth->version < 3003 || pth->version > 3011) {
		LogError << "TheoToEerie: invalid version in " << fic << ": found " << pth->version
		         << " expected 3004 to 3011";
		return NULL;
	}
	
	EERIE_3DOBJ * eerie = new EERIE_3DOBJ;
	eerie->clear();
	
	eerie->file = fic;
	
	if(pth->type_write == 0) {
		// read the texture
		
		LogError <<  "WARNING object " << fic << " SAVE MAP IN OBJECT = INVALID... Using Dummy Textures...";
		
		eerie->texturecontainer.resize(pth->nb_maps);
		for(long i = 0; i < pth->nb_maps; i++) {
			pos += sizeof(THEO_TEXTURE);
			eerie->texturecontainer[i] = GetAnyTexture();
		}
		
	} else {
		
		if((pth->type_write & SAVE_MAP_BMP) || (pth->type_write & SAVE_MAP_TGA)) {
			
			eerie->texturecontainer.resize(pth->nb_maps);
			for(long i = 0; i < pth->nb_maps; i++) {
				
				res::path name;
				if(pth->version >= 3008) {
					const THEO_SAVE_MAPS_IN_3019 * tsmi3019 = reinterpret_cast<const THEO_SAVE_MAPS_IN_3019 *>(adr + pos);
					pos += sizeof(THEO_SAVE_MAPS_IN_3019);
					name = res::path::load(util::loadString(tsmi3019->texture_name)).remove_ext();
				} else {
					const THEO_SAVE_MAPS_IN * tsmi = reinterpret_cast<const THEO_SAVE_MAPS_IN *>(adr + pos);
					pos += sizeof(THEO_SAVE_MAPS_IN);
					name = res::path::load(util::loadString(tsmi->texture_name)).remove_ext();
				}
				
				if(!name.empty()) {
					eerie->texturecontainer[i] = TextureContainer::Load(txpath / name, TextureContainer::Level);
				}
			}
		}
	}
	
	pos = pth->object_seek;
	loadObjectData(eerie, adr, &pos, pth->version);
	eerie->angle = Anglef::ZERO;
	eerie->pos = Vec3f_ZERO;

	// NORMALS CALCULATIONS

	//Compute Faces Areas
	for(size_t i = 0; i < eerie->facelist.size(); i++) {
		const Vec3f & p0 = eerie->vertexlist[eerie->facelist[i].vid[0]].v;
		const Vec3f & p1 = eerie->vertexlist[eerie->facelist[i].vid[1]].v;
		const Vec3f & p2 = eerie->vertexlist[eerie->facelist[i].vid[2]].v;
		eerie->facelist[i].temp = glm::distance((p0 + p1) * .5f, p2) * glm::distance(p0, p1) * .5f;
	}

	for(size_t i = 0; i < eerie->facelist.size(); i++) {
		eerie->facelist[i].norm = CalcObjFaceNormal(
		    eerie->vertexlist[eerie->facelist[i].vid[0]].v,
		    eerie->vertexlist[eerie->facelist[i].vid[1]].v,
		    eerie->vertexlist[eerie->facelist[i].vid[2]].v
		);
		float area = eerie->facelist[i].temp;

		for(long j = 0; j < 3; j++) {
			float mod = area * area;
			Vec3f nrml = eerie->facelist[i].norm * mod;
			float count = mod;

			for(size_t i2 = 0; i2 < eerie->facelist.size(); i2++) {
				if(i != i2) {
					float area2 = eerie->facelist[i].temp;

					for(long j2 = 0; j2 < 3; j2++) {
						if(closerThan(eerie->vertexlist[eerie->facelist[i2].vid[j2]].v, eerie->vertexlist[eerie->facelist[i].vid[j]].v, .1f)) {
							mod = (area2 * area2);
							nrml += eerie->facelist[i2].norm * mod;
							count += mod; 
						}
					}
				}
			}

			count = 1.f / count;
			eerie->vertexlist[eerie->facelist[i].vid[j]].vert.p = nrml * count;
		}
	}

	for(size_t i = 0; i < eerie->facelist.size(); i++) {
		for(long j = 0; j < 3; j++) {
			eerie->vertexlist[eerie->facelist[i].vid[j]].norm = eerie->vertexlist[eerie->facelist[i].vid[j]].vert.p;
		}
	}

	// Apply Normals Spherical correction for NPC head
	long neck_orgn = GetGroupOriginByName(eerie, "neck");
	ObjVertGroup head_idx = EERIE_OBJECT_GetGroup(eerie, "head");

	if(head_idx != ObjVertGroup() && neck_orgn >= 0) {
		VertexGroup & headGroup = eerie->grouplist[head_idx.handleData()];
		
		Vec3f center = Vec3f_ZERO;
		Vec3f origin = eerie->vertexlist[neck_orgn].v;
		float count = (float)headGroup.indexes.size();

		if(count > 0.f) {
			for(size_t idx = 0 ; idx < headGroup.indexes.size(); idx++) {
				center += eerie->vertexlist[ headGroup.indexes[idx] ].v;
			}
			
			center = (center * (1.f / count) + origin + origin) * (1.0f / 3);
			float max_threshold = glm::distance(origin, center);
			
			for(size_t i = 0; i < headGroup.indexes.size(); i++) {
				EERIE_VERTEX * ev = &eerie->vertexlist[headGroup.indexes[i]];
				float d = glm::distance(ev->v, origin);
				float factor = 1.f;

				if(d < max_threshold) {
					factor = d / max_threshold;
				}

				float ifactor = 1.f - factor;
				Vec3f fakenorm;
				fakenorm = ev->v - center;
				fakenorm = glm::normalize(fakenorm);
				ev->norm = ev->norm * ifactor + fakenorm * factor;
				ev->norm = glm::normalize(ev->norm);
			}
		}
	}

	// NORMALS CALCULATIONS END
	//***********************************************************
	
	eerie->m_skeleton = NULL;
	EERIE_CreateCedricData(eerie);
	return eerie;
}