Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

307 lines (246 sloc) 9.557 kB
/*
* Copyright 2011-2012 Arx Libertatis Team (see the AUTHORS file)
*
* This file is part of Arx Libertatis.
*
* Arx Libertatis is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Arx Libertatis is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Arx Libertatis. If not, see <http://www.gnu.org/licenses/>.
*/
/* Based on:
===========================================================================
ARX FATALIS GPL Source Code
Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
<http://www.gnu.org/licenses/>.
In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
// Code: Cyril Meynier
//
// Copyright (c) 1999 ARKANE Studios SA. All rights reserved
#include "physics/Clothes.h"
#include <cstring>
#include "graphics/data/MeshManipulation.h"
#include "graphics/Math.h"
using std::vector;
#define MOLLESS_USEGRAVITY 1
#define MOLLESS_USEDAMPING 1
#define MOLLESS_DEFAULT_DAMPING 0.1f
#define SPHEREMUL 48.f;
#define MOLLESS_COLLISION_NONE 0
#define MOLLESS_COLLISION_PENETRATING 1
#define MOLLESS_COLLISION_COLLIDING 2
void MOLLESS_Clear(EERIE_3DOBJ * obj, long flag) {
if ((obj) && (obj->cdata)) {
for (long i = 0; i < obj->cdata->nb_cvert; i++) {
CLOTHESVERTEX * cv = &obj->cdata->cvert[i];
cv->velocity.x = 0.f;
cv->velocity.y = 0.f;
cv->velocity.z = 0.f;
cv->force.x = 0.f;
cv->force.y = 0.f;
cv->force.z = 0.f;
if(!(flag & 1)) {
cv->coll = -1;
cv->t_pos = cv->pos = obj->vertexlist[cv->idx].v;
} else {
cv->t_pos = cv->pos;
}
}
}
}
void AddSpring(EERIE_3DOBJ * obj, short vert1, short vert2, float constant, float damping, long type) {
if (vert1 == -1 || vert2 == -1 || vert1 == vert2) {
return;
}
for(vector<EERIE_SPRINGS>::const_iterator i = obj->cdata->springs.begin(); i < obj->cdata->springs.end(); ++i) {
if((i->startidx == vert1 && i->endidx == vert2) || (i->startidx == vert2 && i->endidx == vert1)) {
return;
}
}
EERIE_SPRINGS newSpring;
newSpring.startidx = vert1;
newSpring.endidx = vert2;
newSpring.restlength = dist(obj->cdata->cvert[vert1].pos, obj->cdata->cvert[vert2].pos);
newSpring.constant = constant;
newSpring.damping = damping;
newSpring.type = type;
obj->cdata->springs.push_back(newSpring);
}
short GetIDXVert(EERIE_3DOBJ * obj, short num)
{
for (short i = 0; i < obj->cdata->nb_cvert; i++)
{
if (obj->cdata->cvert[i].idx == num) return i;
}
return -1;
}
//*************************************************************************************
// Creates Clothes Data Structure for an object.
//*************************************************************************************
void EERIEOBJECT_AddClothesData(EERIE_3DOBJ * obj)
{
long sel = -1;
long selmounocol = -1;
for(size_t i = 0; i < obj->selections.size(); i++) { // TODO iterator
if(obj->selections[i].name == "mou") {
sel = i;
break;
}
}
for(size_t i = 0; i < obj->selections.size(); i++) { // TODO iterator
if(obj->selections[i].name == "mounocol") {
selmounocol = i;
break;
}
}
if (sel == -1) return;
if (obj->selections[sel].selected.size() > 0)
{
obj->cdata = new CLOTHES_DATA();
obj->cdata->nb_cvert = (short)obj->selections[sel].selected.size();
obj->cdata->cvert = new CLOTHESVERTEX[obj->cdata->nb_cvert];
memset(obj->cdata->cvert, 0, sizeof(CLOTHESVERTEX)*obj->cdata->nb_cvert);
obj->cdata->backup = new CLOTHESVERTEX[obj->cdata->nb_cvert];
memset(obj->cdata->backup, 0, sizeof(CLOTHESVERTEX)*obj->cdata->nb_cvert);
}
// There is a Mollesse (TM) (C) Selection
if (obj->selections[sel].selected.size() > 0)
{
for (int i = 0; i < obj->cdata->nb_cvert; i++)
{
obj->cdata->cvert[i].idx = (short)obj->selections[sel].selected[i];
obj->cdata->cvert[i].pos.x = obj->cdata->cvert[i].t_pos.x = obj->vertexlist[obj->cdata->cvert[i].idx].v.x;
obj->cdata->cvert[i].pos.y = obj->cdata->cvert[i].t_pos.y = obj->vertexlist[obj->cdata->cvert[i].idx].v.y;
obj->cdata->cvert[i].pos.z = obj->cdata->cvert[i].t_pos.z = obj->vertexlist[obj->cdata->cvert[i].idx].v.z;
obj->cdata->cvert[i].mass = 0.5f;
if ((selmounocol != -1) && (IsInSelection(obj, obj->selections[sel].selected[i], selmounocol) >= 0))
{
obj->cdata->cvert[i].flags = CLOTHES_FLAG_NORMAL | CLOTHES_FLAG_NOCOL;
}
else
obj->cdata->cvert[i].flags = CLOTHES_FLAG_NORMAL;
obj->cdata->cvert[i].coll = -1;
}
for (int i = 0; i < obj->cdata->nb_cvert; i++)
{
for (long j = 0; j < obj->ndata[obj->cdata->cvert[i].idx].nb_Nvertex; j++)
{
short vert = obj->ndata[obj->cdata->cvert[i].idx].Nvertex[j];
if (IsInSelection(obj, vert, sel) >= 0)
{
AddSpring(obj, (short)i, (short)GetIDXVert(obj, vert), 11.f, 0.3f, 0);
}
else
{
obj->cdata->cvert[i].flags |= CLOTHES_FLAG_FIX;
obj->cdata->cvert[i].coll = -2;
obj->cdata->cvert[i].mass = 0.f;
}
}
}
// Adds more springs (shear)
for (int i = 0; i < obj->cdata->nb_cvert; i++)
{
for (long j = 0; j < obj->ndata[obj->cdata->cvert[i].idx].nb_Nvertex; j++)
{
short vert = obj->ndata[obj->cdata->cvert[i].idx].Nvertex[j];
if (vert == obj->cdata->cvert[i].idx) continue; // Cannot add a spring between 1 node :p
if (IsInSelection(obj, vert, sel) >= 0)
{
float distance = distSqr(obj->vertexlist[obj->cdata->cvert[i].idx].v,
obj->vertexlist[vert].v) * square(1.2f);
// We springed it in the previous part of code
for (long k = 0; k < obj->ndata[vert].nb_Nvertex; k++)
{
short ver = obj->ndata[vert].Nvertex[k];
if (IsInSelection(obj, ver, sel) >= 0) // This time we have one !
{
if (ver == obj->cdata->cvert[i].idx) continue;
float distance2 = distSqr(obj->vertexlist[obj->cdata->cvert[i].idx].v,
obj->vertexlist[ver].v);
if (distance2 < distance)
{
AddSpring(obj, (short)i, (short)GetIDXVert(obj, ver), 4.2f, 0.7f, 1);
}
}
}
}
}
}
// Adds more springs (bend)
for (int i = 0; i < obj->cdata->nb_cvert; i++)
{
for (long j = 0; j < obj->ndata[obj->cdata->cvert[i].idx].nb_Nvertex; j++)
{
short vert = obj->ndata[obj->cdata->cvert[i].idx].Nvertex[j];
if (vert == obj->cdata->cvert[i].idx) continue; // Cannot add a spring between 1 node :p
if (IsInSelection(obj, vert, sel) >= 0)
{
// We springed it in the previous part of code
for (long k = 0; k < obj->ndata[vert].nb_Nvertex; k++)
{
short ver = obj->ndata[vert].Nvertex[k];
if (IsInSelection(obj, ver, sel) >= 0) // This time we have one !
{
float distance = distSqr(obj->vertexlist[obj->cdata->cvert[i].idx].v,
obj->vertexlist[ver].v) * square(1.2f);
for (long k2 = 0; k2 < obj->ndata[ver].nb_Nvertex; k2++)
{
short ve = obj->ndata[ver].Nvertex[k];
if (ve == vert) continue;
if (IsInSelection(obj, ve, sel) >= 0) // This time we have one !
{
if (obj->cdata->cvert[(short)GetIDXVert(obj, ve)].flags & CLOTHES_FLAG_FIX) continue;
float distance2 = distSqr(obj->vertexlist[obj->cdata->cvert[i].idx].v,
obj->vertexlist[ve].v);
if ((distance2 > distance) && (distance2 < distance * square(2.f)))
{
AddSpring(obj, (short)i, (short)GetIDXVert(obj, ve), 2.2f, 0.9f, 2);
}
}
}
}
}
}
}
}
}
}
void KillClothesData(EERIE_3DOBJ * obj) {
if(obj == NULL) {
return;
}
if(obj->cdata == NULL) {
return;
}
if(obj->cdata->cvert) {
delete[] obj->cdata->cvert;
obj->cdata->cvert = NULL;
}
if(obj->cdata->backup) {
delete[] obj->cdata->backup;
obj->cdata->backup = NULL;
}
delete obj->cdata;
obj->cdata = NULL;
}
Jump to Line
Something went wrong with that request. Please try again.