Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work on math inlines, match a few Char TUs #285

Merged
merged 21 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/SZBE69_B8/objects.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@
"system/char/CharTransDraw.cpp": "Matching",
"system/char/CharUpperTwist.cpp": "NonMatching",
"system/char/CharWeightable.cpp": "Matching",
"system/char/CharWeightSetter.cpp": "NonMatching",
"system/char/CharWeightSetter.cpp": "Matching",
"system/char/CharacterTest.cpp": "NonMatching",
"system/char/ClipCollide.cpp": "NonMatching",
"system/char/ClipCompressor.cpp": "Matching",
Expand Down
4 changes: 2 additions & 2 deletions src/system/beatmatch/JoypadMidiController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ int JoypadMidiController::OnMsg(const KeyboardModMsg& msg){
}

JoypadButton JoypadMidiController::MidiNoteToButton(int note) const {
static DataNode* keyboard_wide_frets = DataVariable("keyboard_wide_frets");
if(keyboard_wide_frets->Int(0)){
static DataNode& keyboard_wide_frets = DataVariable("keyboard_wide_frets");
if(keyboard_wide_frets.Int(0)){
int octave = note / 12;
int pad = mLocalUser->GetPadNum();
if (pad <= 1u && (octave % 2) != pad) {
Expand Down
2 changes: 2 additions & 0 deletions src/system/char/CharBoneTwist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ CharBoneTwist::CharBoneTwist() : mBone(this, 0), mTargets(this, kObjListNoNull)

}

// fn_804B42D0 - poll

void CharBoneTwist::PollDeps(std::list<Hmx::Object*>& changedBy, std::list<Hmx::Object*>& change){
change.push_back(mBone);
for(ObjPtrList<RndTransformable, class ObjectDir>::iterator it = mTargets.begin(); it != mTargets.end(); ++it){
Expand Down
9 changes: 7 additions & 2 deletions src/system/char/CharCollide.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ class CharCollide : public RndTransformable {
virtual ~CharCollide();
virtual void Highlight();

Shape mShape;
int mFlags;
float GetRadius(const Vector3&, Vector3&) const;
float Radius() const;
Shape GetShape() const { return mShape; }
const Vector3& Axis() const;

Shape mShape; // 0x90
int mFlags; // 0x94
ObjPtr<RndMesh, ObjectDir> mMesh; // 0x98
// float mRadius;
// float mMaxLength;
Expand Down
2 changes: 2 additions & 0 deletions src/system/char/CharDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class CharDriver : public RndHighlightable, public CharWeightable, public CharPo
virtual void Exit();
virtual void Replace(Hmx::Object*, Hmx::Object*);

float EvaluateFlags(int);

ObjPtr<CharBonesObject, ObjectDir> mBones;
ObjPtr<ObjectDir, ObjectDir> mClips;
CharClipDriver* mFirst;
Expand Down
256 changes: 252 additions & 4 deletions src/system/char/CharHair.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,62 @@
#include "rndobj/Trans.h"
#include "rndobj/Wind.h"
#include "char/Character.h"
#include "math/MathFuncs.h"
#include "math/Rot.h"
#include <cmath>

INIT_REVS(CharHair)

#pragma push
#pragma dont_inline on
// fn_804D49F8
void CharHair::Strand::SetRoot(RndTransformable* trans){
mRoot = trans;
if(!mRoot) mPoints.resize(0);
else {
float len = mPoints.size() != 0 ? mPoints.back().length : 0;
mBaseMat = mRoot->LocalXfm().m;
SetAngle(mAngle);

// i hate the way these are structured, i'd rather just make for loops but nooo
int depth = 0;
RndTransformable* it = mRoot;
while(true){
depth++;
if(it->TransChildren().empty()) break;
it = it->TransChildren().front();
}
mPoints.resize(depth);

depth = 0;
it = mRoot;
while(true){
mPoints[depth].bone = it;
if(it->TransChildren().empty()) break;
it = it->TransChildren().front();
depth++;
}

Point* pt = 0;
for(int i = 1; i < mPoints.size(); i++){
pt = &mPoints[i - 1];
RndTransformable* bone = mPoints[i].bone;
pt->length = bone->LocalXfm().v.y;
pt->pos = bone->WorldXfm().v;
}

Point* backpt = &mPoints.back();
if(!len){
if(pt) len = pt->length;
else len = 5.0f;
}
backpt->length = len;

ScaleAdd(backpt->bone->WorldXfm().v, backpt->bone->WorldXfm().m.y, backpt->length, backpt->pos);
}
}
#pragma pop

CharHair::CharHair() : mStiffness(0.04f), mTorsion(0.1f), mInertia(0.7f), mGravity(1.0f), mWeight(0.5f), mFriction(0.3f), mMinSlack(0.0f), mMaxSlack(0.0f),
mStrands(this), mReset(1), mSimulate(1), mUsePostProc(1), mMe(this, 0), mWind(this, 0), mCollide(this, kObjListNoNull), unk6c(0) {

Expand All @@ -19,15 +72,153 @@ CharHair::~CharHair(){

}

void CharHair::Enter(){
mReset = 1;
RndPollable::Enter();
Hookup();
}

#pragma push
#pragma dont_inline on
// fn_804D6590
void CharHair::SimulateInternal(float f){
for(ObjPtrList<CharCollide, ObjectDir>::iterator it = mCollide.begin(); it != mCollide.end(); ++it){
(*it);
float sixtyover = 60.0f / f;
float f19 = (1.0f / f) * sixtyover;
float powed = std::pow(1.0f - mStiffness, sixtyover * sixtyover);
Vector3 vec134(0,0,0);
if(mWind){
if(mStrands[0].Root()){
float secs = TheTaskMgr.Seconds(TaskMgr::b);
mWind->GetWind(mStrands[0].Root()->WorldXfm().v, secs, vec134);
vec134 *= f19 * 0.5f;
}
}
vec134.z = vec134.z + mGravity * f19 * -3.858268f;

for(int i = 0; i < mStrands.size(); i++){
Strand& modStrand = mStrands[Mod(i + 1, mStrands.size())];
Strand& thisStrand = mStrands[i];
if(thisStrand.Root() && thisStrand.Root()->TransParent()){
Transform t100;
t100.v = thisStrand.Root()->WorldXfm().v;
Multiply(thisStrand.RootMat(), thisStrand.Root()->TransParent()->WorldXfm().m, t100.m);
ObjVector<Point>& points = thisStrand.Points();
for(int j = 0; j < points.size(); j++){
Point& thisPoint = points[j];
Vector3 v140(thisPoint.pos);
thisPoint.pos += thisPoint.force;
thisPoint.pos.x += vec134.x;
thisPoint.pos.y += vec134.y;
thisPoint.pos.z += vec134.z;
if(thisPoint.sideLength >= 0.0f){
Vector3 vRes;
Point& modPoint = modStrand.Points()[j];
Subtract(thisPoint.pos, modPoint.pos, vRes);
float lensq = LengthSquared(vRes);
float sidelen = thisPoint.sideLength - mMinSlack;
float sidelensq = sidelen * sidelen;
if(lensq < sidelensq){
vRes *= (sidelensq / (sidelensq + lensq) - 0.5f);
thisPoint.pos += vRes;
modPoint.pos -= vRes;
}
else {
float maxslacklen = thisPoint.sideLength + mMaxSlack;
float maxslacklensq = maxslacklen * maxslacklen;
if(maxslacklen > maxslacklensq){
vRes *= (maxslacklensq / (maxslacklensq + lensq) - 0.5f);
thisPoint.pos += vRes;
modPoint.pos -= vRes;
}
}
}
Hmx::Matrix3 m128;
Subtract(thisPoint.pos, t100.v, m128.y);
float rsa = RecipSqrtAccurate(LengthSquared(m128.y));
float rsalen = thisPoint.length * rsa - 1.0f;
if(j > 0){
ScaleAddEq(points[j - 1].force, m128.y, -sixtyover * 0.5f * rsalen);
}
ScaleAddEq(thisPoint.pos, m128.y, rsalen);
Vector3 v158;
ScaleAdd(t100.v, t100.m.y, thisPoint.length, v158);
Interp(thisPoint.lastZ, t100.m.z, mTorsion, m128.z);
if(thisPoint.collides.size() != 0){
float diffRad = thisPoint.outerRadius - thisPoint.radius;
float maxRad = Max(thisPoint.radius, thisPoint.outerRadius);
for(ObjPtrList<CharCollide, ObjectDir>::iterator it = thisPoint.collides.begin(); it != thisPoint.collides.end(); ++it){
CharCollide* thisCollide = *it;
Vector3 v164;
float collideRad = thisCollide->GetRadius(thisPoint.pos, v164);
switch(thisCollide->GetShape()){
case CharCollide::kPlane: // 0
if(maxRad > collideRad){
ScaleAddEq(thisPoint.pos, thisCollide->Axis(), maxRad - collideRad);
}
break;
case CharCollide::kCigar: // 3
case CharCollide::kSphere: // 1
float v164sq = LengthSquared(v164);
float sumRad = collideRad + maxRad;
if(v164sq < sumRad * sumRad){
if(diffRad > 0.0f){
float v164sqrecip = RecipSqrtAccurate(v164sq);
float cluster = v164sq * v164sqrecip;
float othersumRad = collideRad + thisPoint.radius;
v164 *= -v164sqrecip;
if(cluster < othersumRad){
m128.z = v164;
ScaleAddEq(thisPoint.pos, v164, cluster - othersumRad);
}
else Interp(m128.z, v164, (sumRad - cluster) / diffRad, m128.z);
}
else ScaleAddEq(thisPoint.pos, v164, sumRad * RecipSqrtAccurate(v164sq) - 1.0f);
}
break;
case CharCollide::kInsideCigar: // 4
case CharCollide::kInsideSphere: // 2
float v164sq42 = LengthSquared(v164);
float minusRad = collideRad - maxRad;
if(v164sq42 > minusRad * minusRad){
if(diffRad > 0.0f){
float v164sqrecip = RecipSqrtAccurate(v164sq42);
float cluster = v164sq42 * v164sqrecip;
float othersumRad = collideRad - thisPoint.radius;
v164 *= -v164sqrecip;
if(cluster > othersumRad){
m128.z = v164;
ScaleAddEq(thisPoint.pos, v164, cluster - othersumRad);
}
else Interp(m128.z, v164, (cluster - minusRad) / diffRad, m128.z);
}
else ScaleAddEq(thisPoint.pos, v164, minusRad * RecipSqrtAccurate(v164sq42) - 1.0f);
}
break;
default: break;
}
}

Vector3 v1, v2, v3;
Interp(v1, v2, 0.0f, v3);
Scale(m128.y, rsa, t100.m.y);
Cross(t100.m.y, m128.z, t100.m.x);
t100.m.x *= RecipSqrtAccurate(LengthSquared(t100.m.x));
Normalize(t100.m.x, t100.m.x);
Cross(t100.m.x, t100.m.y, t100.m.z);
thisPoint.lastZ = t100.m.z;
if(thisPoint.bone) thisPoint.bone->SetWorldXfm(t100);
Subtract(v158, thisPoint.pos, thisPoint.force);
Vector3 v170;
Subtract(thisPoint.lastFriction, thisPoint.force, v170);
thisPoint.lastFriction = thisPoint.force;
thisPoint.force *= 1.0f - powed;
ScaleAddEq(thisPoint.force, v170, -mFriction);
Vector3 v17c;
Subtract(thisPoint.pos, v140, v17c);
ScaleAddEq(thisPoint.force, v17c, mInertia);
t100.v = thisPoint.pos;
}
}
}
}
}
#pragma pop

Expand All @@ -36,6 +227,59 @@ CharHair::Strand::Strand(Hmx::Object* o) : mShowSpheres(0), mShowCollide(0), mSh
mRootMat.Identity();
}

BinStream& operator>>(BinStream& bs, CharHair::Point& pt){
bs >> pt.pos;
bs >> pt.bone;
bs >> pt.length;
if(CharHair::gRev < 3){
int i;
char buf[0x100];
bs >> i;
bs.ReadString(buf, 0xff);
}
else if(CharHair::gRev == 3){
int i;
bs >> i;
}
bs >> pt.radius;
if(CharHair::gRev > 1) bs >> pt.outerRadius;
else pt.outerRadius = 0;
if(CharHair::gRev == 6 || CharHair::gRev == 7 || CharHair::gRev == 8){
float f;
bs >> f;
pt.radius += f;
pt.outerRadius += f;
}
if(CharHair::gRev == 6){
char buf[0x100];
bs.ReadString(buf, 0xff);
}
if(CharHair::gRev < 8){
pt.sideLength = -1.0f;
if(CharHair::gRev > 5){
int i;
bs >> i >> i;
}
}
else {
bool b = false;
if(CharHair::gRev < 9) bs >> b;
bs >> pt.sideLength;
if(CharHair::gRev < 9 && !b){
pt.sideLength = -1.0f;
}
}
if(CharHair::gRev > 9){
bs >> pt.collide;
bs >> pt.unk60;
bs >> pt.unk64;
}
pt.collides.clear();
pt.force.Zero();
pt.lastFriction.Zero();
pt.lastZ.Zero();
}

void CharHair::Strand::Load(BinStream& bs){
bs >> mRoot;
bs >> mAngle;
Expand All @@ -47,6 +291,10 @@ void CharHair::Strand::Load(BinStream& bs){
else mHookupFlags = 0;
}

BinStream& operator>>(BinStream& bs, CharHair::Strand& strand){
strand.Load(bs);
}

SAVE_OBJ(CharHair, 0x41B)

void CharHair::Load(BinStream& bs){
Expand Down
Loading
Loading