Decompile 9 functions in Source/Utility/Math/Vector3d.h, Source/Utility/Math/AffineMatrix.h, ...

Batch #1843 by ragnarok-clanker: 1 byte-identical, 8 confirmed by peer review.

- fn_02024 ClientRadians: logic confirmed by peer review
- fn_17668 WorldScene::GetGameActorByAID: logic confirmed by peer review
- fn_21057 CRenderObject::GetTargetPos: logic confirmed by peer review
- fn_17667 WorldScene::GetGameActorByAidIncludeMe: logic confirmed by peer review
- fn_21290 CGameMode::NotifyItemBounds: logic confirmed by peer review
- fn_03089 CEffect::Slot25: logic confirmed by peer review
- fn_08405 CellWorldPosition: logic confirmed by peer review
- fn_19762 EffectPrimitiveSlot::EffectPrimitiveSlot: byte-identical (already on main)
- fn_19865 DrawEffectPrimitive15: logic confirmed by peer review

Peer-reviewed-by: Yommy, eAthena, ragnarok-clanker
Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes).
This commit is contained in:
ragnarok-clanker 2026-10-28 22:49:51 +00:00
commit d7862ef5c4
19 changed files with 217 additions and 119 deletions

View file

@ -113,8 +113,8 @@ public:
/* 159C */ XmlDocument m_monsterSkillInfo;
/* 15CC */ XmlDocument m_monsterTalkTable;
/* 15FC */ unsigned char unknown_15FC[8];
/* 1604 */ int unknown_1604;
/* 1608 */ unsigned char unknown_1608[4];
/* 1604 */ std::uint32_t m_aid;
/* 1608 */ std::uint32_t m_gid;
/* 160C */ char m_navigationPlayerMap[0x1C];
/* 1628 */ int m_job;
/* 162C */ unsigned char unknown_162C[0x24];

View file

@ -1,4 +1,8 @@
#include "Client/Mode/ActiveGameMode.h"
#include "Client/Mode/CGameMode.h"
#include "Client/Session.h"
#include "Contents/Actors/RenderObject.h"
#include "Contents/World/WorldScene.h"
#include "Utility/Math/AffineMatrix.h"
#include <cmath>
@ -56,3 +60,27 @@ float CRenderObject::Distance(float x, float y, float z) const {
const float horizontal = SquareRoot(deltaZ * deltaZ + deltaX * deltaX);
return SquareRoot(horizontal * horizontal + deltaY * deltaY);
}
// OFFSET: 0x00CAD9E0
// FUNCTION: fn_21057
bool CRenderObject::GetTargetPos(std::uint32_t targetAid, vector3d& targetPos) const {
const WorldScene* world = static_cast<CGameMode*>(g_world.ActiveGameMode())->scene;
const CRenderObject* player = reinterpret_cast<const CRenderObject*>(world->player);
if (targetAid == g_session.m_aid) {
targetPos = {player->render.position[0], player->render.position[1], player->render.position[2]};
return true;
}
if (const CRenderObject* actor = world->GetGameActorByAID(targetAid)) {
targetPos = {actor->render.position[0], actor->render.position[1], actor->render.position[2]};
return true;
}
const float* position = this->render.position;
targetPos = {
position[0] - (player->render.position[0] - position[0]), position[1] - (player->render.position[1] - position[1]),
position[2] - (player->render.position[2] - position[2])
};
return false;
}

View file

@ -3,6 +3,7 @@
#include "Contents/Actors/GameObject.h"
#include "Contents/Actors/RenderObjectState.h"
#include "Utility/Math/Vector3d.h"
#include <cstddef>
@ -22,6 +23,7 @@ public:
void Face(float x, float z);
float HorizontalDistance(float x, float z) const;
float Distance(float x, float y, float z) const;
bool GetTargetPos(std::uint32_t targetAid, vector3d& targetPos) const;
void SetAnimationSpeed(float speed);
void SetActionSpeed(float speed);
void DrawSprite(int argument, bool seasonal, float offset);

View file

@ -20,8 +20,8 @@ void CEffect::Slot11(std::string) {
// OFFSET: 0x005A2170
// FUNCTION: fn_03089
EffectVector3 CEffect::Slot25() {
return EffectVector3{0.0f, 0.0f, 0.0f};
vector3d CEffect::Slot25() {
return vector3d{0.0f, 0.0f, 0.0f};
}
// OFFSET: 0x005A2190

View file

@ -7,7 +7,7 @@
#include <string>
#include <vector>
struct EffectVector3;
struct vector3d;
struct EffectEvent {
/* 0000 */ int kind;
@ -44,7 +44,7 @@ public:
virtual void Slot22(int argument);
virtual void Slot23(int argument);
virtual void Slot24(int argument1, int argument2, int argument3, int argument4, int argument5);
virtual EffectVector3 Slot25();
virtual vector3d Slot25();
virtual void Slot26(int argument);
virtual void Slot27(int argument);
virtual int Slot28();

View file

@ -34,6 +34,8 @@ struct EffectParticle : CRenderObject {
void PrimIntimidate();
void PrimPoison();
void PrimGuard();
bool PrimLineLink();
void PrimSMA();
bool AdvanceFrame();
void UpdateRecords();

View file

@ -1,6 +1,7 @@
#include "Contents/Effects/EffectPrimitiveMotion.h"
#include "Client/Mode/CGameMode.h"
#include "Client/Mode/ActiveGameMode.h"
#include "Client/Session.h"
#include "Contents/Camera/Camera.h"
#include "Contents/World/WorldScene.h"
#include "Resource/Sprites/ActionResource.h"
@ -23,8 +24,8 @@
namespace {
// INLINED
EffectVector3 Forward(float distance, const float* matrix) {
const EffectVector3 point{0.0f, 0.0f, distance};
vector3d Forward(float distance, const float* matrix) {
const vector3d point{0.0f, 0.0f, distance};
return {
((matrix[3] * point.y + matrix[0] * point.x) + point.z * matrix[6]) + matrix[9],
((matrix[4] * point.y + matrix[1] * point.x) + point.z * matrix[7]) + matrix[10],
@ -33,8 +34,8 @@ namespace {
}
// INLINED
EffectVector3 Upward(float distance, const float* matrix) {
const EffectVector3 point{0.0f, -distance, 0.0f};
vector3d Upward(float distance, const float* matrix) {
const vector3d point{0.0f, -distance, 0.0f};
return {
((matrix[3] * point.y + matrix[0] * point.x) + point.z * matrix[6]) + matrix[9],
((matrix[4] * point.y + matrix[1] * point.x) + point.z * matrix[7]) + matrix[10],
@ -43,8 +44,8 @@ namespace {
}
// INLINED
EffectVector3 Lift(float distance, const float* matrix) {
const EffectVector3 point{0.0f, distance, 0.0f};
vector3d Lift(float distance, const float* matrix) {
const vector3d point{0.0f, distance, 0.0f};
return {
((matrix[3] * point.y + matrix[0] * point.x) + point.z * matrix[6]) + matrix[9],
((matrix[4] * point.y + matrix[1] * point.x) + point.z * matrix[7]) + matrix[10],
@ -868,7 +869,7 @@ void EffectParticle::PrimBottom2() {
slot.fullDisplayAngle -= 360;
}
slot.maxHeight = 20.0f + 10.0f * ClientSine(slot.fullDisplayAngle);
slot.maxHeight = 20.0f + 10.0f * g_sinTable[slot.fullDisplayAngle];
}
}
@ -930,7 +931,7 @@ void EffectParticle::PrimBottom() {
slot.vecBNow.x = this->render.position[0];
slot.vecBNow.z = this->render.position[2];
slot.vecBPre.y = this->render.position[1] - 6.0f;
slot.vecBNow.y = slot.vecBPre.y + 3.0f * ClientSine(slot.rotStart);
slot.vecBNow.y = slot.vecBPre.y + 3.0f * g_sinTable[slot.rotStart];
if (slot.flag1[2] == 7) {
slot.fullDisplayAngle += 10;
@ -1399,6 +1400,91 @@ void EffectParticle::PrimGuard() {
}
}
// OFFSET: 0x00BBFAA0
bool EffectParticle::PrimLineLink() {
CGameMode* gameMode = static_cast<CGameMode*>(g_world.ActiveGameMode());
const CRenderObject* target = nullptr;
const AttachedEffect* master = this->state.master;
this->render.position[0] = master->render.position[0];
this->render.position[1] = master->render.position[1];
this->render.position[2] = master->render.position[2];
EffectPrimitiveSlot& slot = this->state.slots[0];
++slot.process;
slot.vecTNow = {this->render.position[0], this->render.position[1], this->render.position[2]};
slot.vecTNow.y -= 8.0f;
if (slot.height[4] == 2.0f) {
if (slot.process > 40) {
slot.alphaB -= 3;
if (slot.alphaB < 0) {
slot.alphaB = 0;
}
} else if (slot.process < 20) {
slot.alphaB += 6;
}
} else if (slot.height[4] == 3.0f) {
const int phase = slot.process % 360;
if (slot.process <= 80) {
++slot.alphaB;
}
slot.maxHeight += g_sinTable[phase] * 0.005f;
} else if (slot.process % 10 < 5) {
slot.alphaB += 2;
} else {
slot.alphaB -= 2;
}
if (slot.height[0] > 0.0f) {
if (slot.height[0] == static_cast<float>(g_session.m_aid)) {
target = reinterpret_cast<const CRenderObject*>(gameMode->scene->player);
} else {
target = gameMode->scene->GetGameActorByAID(static_cast<std::uint32_t>(slot.height[0]));
}
}
if (target == nullptr) {
slot.life = 0;
slot.alphaB = 0;
} else {
slot.vecTPre = {target->render.position[0], target->render.position[1], target->render.position[2]};
slot.vecTPre.y -= 8.0f;
}
return true;
}
// OFFSET: 0x00BC1AA0
void EffectParticle::PrimSMA() {
for (int index = 0; index < 4; ++index) {
EffectPrimitiveSlot& slot = this->state.slots[index];
if (slot.life != 1) {
continue;
}
++slot.process;
if (slot.process <= 0) {
continue;
}
if (slot.process == 1) {
const float x = this->state.offset.x - this->render.position[0];
const float z = this->state.offset.z - this->render.position[2];
CalculateVectorAngle(x, z, &slot.rotStart);
}
slot.vecBNow.x += slot.height[1] * g_cosTable[slot.rotStart];
slot.vecBNow.z += slot.height[1] * g_sinTable[slot.rotStart];
}
}
// OFFSET: 0x00BB6F30
// FUNCTION: fn_19779
bool EffectParticle::UpdateHit6() {

View file

@ -40,7 +40,7 @@ void DrawEffectPrimitive15(EffectPrimitiveState& particle, const RenderObjectSta
const float bottomY = bottom * matrix[4] + zeroY;
const float bottomZ = bottom * matrix[5] + zeroZ;
const EffectVector3 corners[4] = {
const vector3d corners[4] = {
{(rightX + topX) + matrix[9], (rightY + topY) + matrix[10], (rightZ + topZ) + matrix[11]},
{(leftX + topX) + matrix[9], (leftY + topY) + matrix[10], (leftZ + topZ) + matrix[11]},
{(bottomX + rightX) + matrix[9], (bottomY + rightY) + matrix[10], (bottomZ + rightZ) + matrix[11]},
@ -57,7 +57,7 @@ void DrawEffectPrimitive15(EffectPrimitiveState& particle, const RenderObjectSta
RenderTriangle& triangle = particle.triangles[triangleIndex];
for (unsigned vertexIndex = 0; vertexIndex < 3; ++vertexIndex) {
const EffectVector3& corner = corners[indices[triangleIndex][vertexIndex]];
const vector3d& corner = corners[indices[triangleIndex][vertexIndex]];
const float position[3] = {corner.x + render.position[0], corner.y + render.position[1], corner.z + render.position[2]};
RenderVertex projected{0, 0, 0, 0, 0, 0xFF000000u, 0, 0};
context.projection.Project(position, context.cameraMatrix, projected);

View file

@ -121,14 +121,14 @@ EffectPrimitiveState::EffectPrimitiveState(RenderObjectState& render) {
this->unknown_03A0 = {};
this->unknown_03AC = {};
for (EffectVector3& corner : this->corners) {
for (vector3d& corner : this->corners) {
corner = {};
}
for (EffectPrimitiveRecord& record : this->records) {
record.position = {};
for (EffectVector3& corner : record.corners) {
for (vector3d& corner : record.corners) {
corner = {};
}
}

View file

@ -8,18 +8,13 @@
#include <vector>
#include "Contents/Actors/RenderObjectState.h"
#include "Utility/Math/Vector3d.h"
struct AttachedEffect;
class CTexture;
struct EffectVector3 {
/* 0000 */ float x;
/* 0004 */ float y;
/* 0008 */ float z;
};
struct EffectPrimitiveRecord {
/* 0000 */ EffectVector3 position;
/* 000C */ EffectVector3 corners[4];
/* 0000 */ vector3d position;
/* 000C */ vector3d corners[4];
/* 003C */ float unknown_003C;
/* 0040 */ float scale;
/* 0044 */ float angle;
@ -48,12 +43,12 @@ struct EffectPrimitiveSlot {
/* 007E */ std::int16_t riseAngle;
/* 0080 */ float distance;
union {
/* 0084 */ EffectVector3 vectors[4];
/* 0084 */ vector3d vectors[4];
struct {
/* 0084 */ EffectVector3 vecBNow;
/* 0090 */ EffectVector3 vecTNow;
/* 009C */ EffectVector3 vecBPre;
/* 00A8 */ EffectVector3 vecTPre;
/* 0084 */ vector3d vecBNow;
/* 0090 */ vector3d vecTNow;
/* 009C */ vector3d vecBPre;
/* 00A8 */ vector3d vecTPre;
};
};
};
@ -71,7 +66,7 @@ struct EffectPrimitiveState {
/* 0140 */ AttachedEffect* master;
/* 0144 */ CTexture** textures;
/* 0148 */ std::uint32_t unknown_0148;
/* 014C */ EffectVector3 unknown_014C;
/* 014C */ vector3d unknown_014C;
/* 0158 */ std::uint32_t unknown_0158;
/* 015C */ std::uint32_t unknown_015C;
/* 0160 */ float matrix1[12];
@ -112,8 +107,8 @@ struct EffectPrimitiveState {
/* 0290 */ float unknown_0290[3];
/* 029C */ float unknown_029C;
/* 02A0 */ float unknown_02A0;
/* 02A4 */ EffectVector3 unknown_02A4;
/* 02B0 */ EffectVector3 unknown_02B0;
/* 02A4 */ vector3d unknown_02A4;
/* 02B0 */ vector3d unknown_02B0;
/* 02BC */ float unknown_02BC;
/* 02C0 */ float unknown_02C0;
/* 02C4 */ float unknown_02C4;
@ -159,13 +154,13 @@ struct EffectPrimitiveState {
/* 0364 */ float unknown_0364;
/* 0368 */ float unknown_0368;
/* 036C */ float unknown_036C;
/* 0370 */ EffectVector3 unknown_0370;
/* 037C */ EffectVector3 origin;
/* 0388 */ EffectVector3 offset;
/* 0394 */ EffectVector3 velocity;
/* 03A0 */ EffectVector3 unknown_03A0;
/* 03AC */ EffectVector3 unknown_03AC;
/* 03B8 */ EffectVector3 corners[4];
/* 0370 */ vector3d unknown_0370;
/* 037C */ vector3d origin;
/* 0388 */ vector3d offset;
/* 0394 */ vector3d velocity;
/* 03A0 */ vector3d unknown_03A0;
/* 03AC */ vector3d unknown_03AC;
/* 03B8 */ vector3d corners[4];
/* 03E8 */ EffectPrimitiveSlot slots[4];
/* 06B8 */ EffectPrimitiveRecord records[50];
/* 2210 */ RenderTriangle triangles[512];
@ -185,11 +180,9 @@ struct EffectPrimitiveObject {
void __stdcall CalculateVectorAngle(float x, float y, std::int16_t* angle);
static_assert(sizeof(EffectVector3) == 12);
static_assert(sizeof(EffectPrimitiveRecord) == 140);
static_assert(sizeof(EffectPrimitiveSlot) == 0xB4);
#if defined(_WIN32) && !defined(_WIN64)
static_assert(offsetof(EffectVector3, z) == 0x8);
static_assert(offsetof(EffectPrimitiveRecord, corners) == 0xC);
static_assert(offsetof(EffectPrimitiveRecord, matrix) == 0x48);
static_assert(offsetof(EffectPrimitiveRecord, color) == 0x88);

View file

@ -595,9 +595,9 @@ void CGameMode::NotifyItemBounds() {
this->itemWindow->Invalidate();
}
if (g_windowMgr.window_02C8) {
g_windowMgr.window_02C8->SendMsg(nullptr, 6, 34, g_session.unknown_1604, 0, 0);
g_windowMgr.window_02C8->SendMsg(nullptr, 6, 34, g_session.m_aid, 0, 0);
}
g_windowMgr.NotifyItemWindows(g_session.unknown_1604, g_session.unknown_5568, g_session.unknown_556C);
g_windowMgr.NotifyItemWindows(g_session.m_aid, g_session.unknown_5568, g_session.unknown_556C);
}
// OFFSET: 0x00DD80A0

View file

@ -595,10 +595,10 @@ std::pair<bool, int> CSkillActionMgr::ActionSlot01(int skillId) {
// OFFSET: 0x0077AD90
// FUNCTION: fn_08405
EffectVector3 CellWorldPosition(int column, int row) {
vector3d CellWorldPosition(int column, int row) {
if (!g_world.ActiveGameMode() || !static_cast<CGameMode*>(g_world.ActiveGameMode())->scene ||
!static_cast<CGameMode*>(g_world.ActiveGameMode())->scene->terrain) {
return EffectVector3{0.0f, 0.0f, 0.0f};
return vector3d{0.0f, 0.0f, 0.0f};
}
float x = 0.0f;
@ -606,7 +606,7 @@ EffectVector3 CellWorldPosition(int column, int row) {
float z = 0.0f;
static_cast<CGameMode*>(g_world.ActiveGameMode())->scene->terrain->Grid().CellOrigin(column, row, x, z);
y = static_cast<CGameMode*>(g_world.ActiveGameMode())->scene->terrain->Grid().Height(x, z);
return EffectVector3{x + 2.5f, y + 0.0f, z + 2.5f};
return vector3d{x + 2.5f, y + 0.0f, z + 2.5f};
}
// OFFSET: 0x0077AEA0

View file

@ -13,7 +13,7 @@ class CGameActor;
class CRenderObject;
class CSkillObjectAction;
class LuaScript;
struct EffectVector3;
struct vector3d;
struct NormalItemSlot;
struct EfstActionMessage {
@ -160,7 +160,7 @@ bool IsOptionalSelfTargetSkill(int skillId);
bool HidesUseFailureMessage(int skillId);
bool IsSupportSkill(int skillId);
bool ShowsCastEffect(int skillId);
EffectVector3 CellWorldPosition(int column, int row);
vector3d CellWorldPosition(int column, int row);
static_assert(sizeof(SkillInfoEntry) == 8);
#if defined(_WIN32) && !defined(_WIN64)
static_assert(offsetof(SkillInfoEntry, unknown_0004) == 0x4);

View file

@ -1,49 +1,14 @@
#include "Contents/Actors/RenderObject.h"
#include "Contents/World/WorldActors.h"
#include "Contents/World/WorldScene.h"
// OFFSET: 0x00AC8260
// FUNCTION: fn_17668
CRenderObject* WorldActors::Find(std::uint32_t accountId) const {
CRenderObject* WorldScene::GetGameActorByAID(std::uint32_t aid) const {
for (CRenderObject* actor : this->actors) {
if (actor->render.accountId == accountId) {
if (actor->render.accountId == aid) {
return actor;
}
}
return nullptr;
}
// OFFSET: 0x00CAD9E0
// FUNCTION: fn_21057
bool WorldActors::TargetPosition(const float* origin, std::uint32_t accountId, float* output) const {
CRenderObject* target;
if (accountId == this->localAccountId) {
target = this->localPlayer;
} else {
target = this->Find(accountId);
}
if (target) {
output[0] = target->render.position[0];
output[1] = target->render.position[1];
output[2] = target->render.position[2];
return true;
}
const float x = origin[0];
const float y = origin[1];
const float z = origin[2];
const float deltaX = this->localPlayer->render.position[0] - x;
const float deltaZ = this->localPlayer->render.position[2] - z;
const float reflectedX = x - deltaX;
const float deltaY = this->localPlayer->render.position[1] - y;
const float reflectedZ = z - deltaZ;
output[0] = reflectedX;
output[1] = y - deltaY;
output[2] = reflectedZ;
return false;
}

View file

@ -1,18 +1,18 @@
#include "Client/Session.h"
#include "Contents/Actors/RenderObject.h"
#include "Contents/World/WorldActors.h"
#include "Contents/World/WorldObjects.h"
#include "Contents/World/WorldScene.h"
#include "Contents/Effects/EffectLists.h"
// OFFSET: 0x00AC8220
// FUNCTION: fn_17667
CRenderObject* WorldActors::Lookup(std::uint32_t accountId) const {
if (accountId == this->localAccountId) {
return this->localPlayer;
CRenderObject* WorldScene::GetGameActorByAidIncludeMe(std::uint32_t aid) const {
if (aid == g_session.m_aid) {
return reinterpret_cast<CRenderObject*>(this->player);
}
for (CRenderObject* actor : this->actors) {
if (actor->render.accountId == accountId) {
if (actor->render.accountId == aid) {
return actor;
}
}

View file

@ -24,6 +24,8 @@ public:
WorldScene& operator=(const WorldScene&) = delete;
void Clear();
bool FindActorInCell(const float* position, std::function<bool(std::uint32_t)> predicate) const;
CRenderObject* GetGameActorByAID(std::uint32_t aid) const;
CRenderObject* GetGameActorByAidIncludeMe(std::uint32_t aid) const;
void ClearActorCells();
/* 0004 */ CGameMode* gameMode;

View file

@ -4,6 +4,11 @@
#include <cstddef>
extern const float g_identityMatrix[12];
extern float g_radTable[722];
extern float g_sinTable[722];
extern float g_cosTable[722];
void CreateTrigonometricTable();
float ClientSin(float radians);
float ClientCos(float radians);

View file

@ -13,55 +13,53 @@ float ClientCos(float radians) {
return std::cos(radians);
}
// GLOBAL: gl_24568
float g_radTable[722];
// GLOBAL: gl_24572
float g_sinTable[722];
// GLOBAL: gl_24574
float g_cosTable[722];
namespace {
struct AngleTables {
float radians[361];
float negativeRadians[361];
float sine[361];
float negativeSine[361];
float cosine[361];
float negativeCosine[361];
// OFFSET: 0x00554280
// FUNCTION: fn_02021
AngleTables() {
for (int index = 0; index <= 360; ++index) {
const float angle = (static_cast<float>(index) / 180.0f) * 3.141592f;
radians[index] = angle;
sine[index] = ClientSin(angle);
cosine[index] = ClientCos(angle);
negativeRadians[index] = -angle;
negativeSine[index] = -sine[index];
negativeCosine[index] = -cosine[index];
}
}
};
const AngleTables tables;
// INLINED
int Wrapped(int degrees) {
return degrees > 360 || degrees < -360 ? degrees % 360 : degrees;
}
}
// OFFSET: 0x00554280
// FUNCTION: fn_02021
void CreateTrigonometricTable() {
for (int index = 0; index <= 360; ++index) {
const float angle = (static_cast<float>(index) / 180.0f) * 3.141592f;
g_radTable[index] = angle;
g_sinTable[index] = ClientSin(angle);
g_cosTable[index] = ClientCos(angle);
g_radTable[index + 361] = -angle;
g_sinTable[index + 361] = -g_sinTable[index];
g_cosTable[index + 361] = -g_cosTable[index];
}
}
// OFFSET: 0x00554420
// FUNCTION: fn_02024
float ClientRadians(int degrees) {
const int index = Wrapped(degrees);
return tables.radians[index >= 0 ? index : 361 + index];
return g_radTable[index >= 0 ? index : 361 + index];
}
// OFFSET: 0x00554470
// FUNCTION: fn_02025
float ClientSine(int degrees) {
const int index = Wrapped(degrees);
return tables.sine[index >= 0 ? index : 361 + index];
return g_sinTable[index >= 0 ? index : 361 + index];
}
// OFFSET: 0x005543D0
// FUNCTION: fn_02023
float ClientCosine(int degrees) {
const int index = Wrapped(degrees);
return tables.cosine[index >= 0 ? index : 361 + index];
return g_cosTable[index >= 0 ? index : 361 + index];
}

View file

@ -0,0 +1,17 @@
#ifndef RAGNAROK_SOURCE_UTILITY_MATH_VECTOR3D_H
#define RAGNAROK_SOURCE_UTILITY_MATH_VECTOR3D_H
#include <cstddef>
struct vector3d {
/* 0000 */ float x;
/* 0004 */ float y;
/* 0008 */ float z;
};
static_assert(sizeof(vector3d) == 12);
#if defined(_WIN32) && !defined(_WIN64)
static_assert(offsetof(vector3d, z) == 0x8);
#endif
#endif