Kuribo64
Views: 19,850,133 Home | Forums | Uploader | Wiki | Object databases | IRC
Rules/FAQ | Memberlist | Calendar | Stats | Online users | Last posts | Search
03-28-24 08:21 AM
Guest:

0 users reading Looking into SM64DS fixing collision | 1 bot

Main - General SM64DS hacking - Looking into SM64DS fixing collision Hide post layouts | Thread closed

Pages: 1 2 3 4 5
Skelux
Posted on 11-27-12 04:56 AM Link | #1249
I've been wanting to port Super Mario Star Road to DS and the only thing holding me back from doing so Is the problem with KLC conversion. Mega-mario, I was hoping you may be able to give me an idea of what's causing the faulty collision so I could code it properly. Could it be a problem with grid block size?

I asked on youtube also, but I notice you are not very active.

Arisotura
Posted on 11-27-12 10:21 AM (rev. 2 of 11-27-12 09:34 PM) Link | #1251
I'm a bit busier than usual irl currently, that's probably why.

The problem mostly happens when there are too many collision planes in the same spot. I think there are also precision issues because blargh fixed point arithmetic.

Perhaps converting the model's coordinates to match the KCL precision would help. IDK though.

The best thing to do would be getting a KCL viewer working and examining Nintendo's KCLs closely, to see how they made them.


If someone can help fix those annoying issues, I could reopen SM64DS hacking. That being said, if there's enough interest for it.

____________________
NSMBHD - Kafuka - Jul
melonDS the most fruity DS emulator there is

zafkflzdasd

ray
Posted on 11-28-12 05:45 PM Link | #1268
There are many people interested into SM64DS Hacking. But everyone has the same problem as me: Crappy collision. If the collision generator would be good, so that there aren't anymore random holes, and if you would be able to choose what terrain it is (water/sand/stone/...), I would make soo much levels. Probably a full hack.

There are some things which should also be improved, like textures. If you import them, they become darker, as they have been before. And the Level editor misses some features, like copy-pasting objects, or deleting them with the delete key.

____________________
Check out my Patreon Page if you want to support me :)



Arisotura
Posted on 11-28-12 08:03 PM Link | #1269
Well yeah. I know the editor lacks several features, but my main goal was getting collision right. I knew that even if I added more features, people would keep mentioning the collision issues.

If someone, be it Skelux or anyone else, manages to fix that, more SM64DS hacking activity will happen.

____________________
NSMBHD - Kafuka - Jul
melonDS the most fruity DS emulator there is

zafkflzdasd

blank
Posted on 11-28-12 09:27 PM Link | #1270
Gericom were able to use a modified version of my KCL creation code for MKDS, the same could probably be done for SM54DS. With a minor modification to my collision exporter I was able to export the collision for Tick Tock Clock:


[image]

Arisotura
Posted on 11-28-12 09:31 PM Link | #1271
Nice. Now what we'd need to know is how well it works with SM64DS custom levels. So far it seems to be working rather well with MKDS custom tracks...

Anyway I'm interested into your code. If it's C#, I may give it a try in SM64DSe. And if it works, it'll be awesome for the few people interested in SM64DS hacking.

____________________
NSMBHD - Kafuka - Jul
melonDS the most fruity DS emulator there is

zafkflzdasd

blank
Posted on 11-28-12 10:23 PM Link | #1272
You can find the tools with source here, but the source is python. Also, the way the octree is written probably wont work with SM64DS, at least it didn't with MKDS.

Arisotura
Posted on 11-28-12 10:32 PM (rev. 2 of 11-28-12 10:33 PM) Link | #1273
Interesting. I'll try that out, if I can port it to valid C#.

____________________
NSMBHD - Kafuka - Jul
melonDS the most fruity DS emulator there is

zafkflzdasd

Skelux
Posted on 11-29-12 08:09 AM Link | #1274
I think the darkness might be because normals are not imported. Although the DS doesn't handle them like the N64, I do notice that some faces have darker shading such as the small slopes on the tiles inside the castle.

Arisotura
Posted on 11-29-12 12:43 PM Link | #1275
Textures becoming darker might be due to the compression. Normals aren't in cause though as they're unneeded, Nintendo's models have premade shading with vertex colors, and shading on custom models should be done the same way.

____________________
NSMBHD - Kafuka - Jul
melonDS the most fruity DS emulator there is

zafkflzdasd

Gericom
Posted on 11-29-12 05:02 PM (rev. 2 of 11-29-12 05:02 PM) Link | #1276
I can give you c# code:

[source=c#]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
using System.IO;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Drawing;

namespace MKDS_Course_Modifier.Converters.Obj2Kcl
{
class Obj2Kcl
{
public static void ConvertToKcl(string infile, string outfile)
{
object[] o = read_obj(infile);
write_kcl(outfile, o[0] as List, (Vector3)o[1], (Vector3)o[2],23, 1, o[3] as string[], o[4] as int[]);
}
private static object[] read_obj(string filename)
{
Vector3 bb_min = new Vector3();
Vector3 bb_max = new Vector3();
List vertices = new List();
List triangles = new List();
List Normals = new List();
List Materialu = new List();
List names = new List();
Stream fs = File.OpenRead(filename);
StreamReader sr = new StreamReader(fs);

string curmaterial = "";
CultureInfo usahax = new CultureInfo("en-US");

string curline;
while ((curline = sr.ReadLine()) != null)
{
curline = curline.Trim();

// skip empty lines and comments
if (curline.Length < 1) continue;
if (curline[0] == '#') continue;

string[] parts = curline.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 1) continue;
int face = 0;
switch (parts[0])
{
case "mtllib": // material lib file
{

}
break;

case "usemtl": // material name
if (parts.Length < 2) continue;
curmaterial = parts[1];
if (!names.Contains(curmaterial))
{
names.Add(curmaterial);
}
break;

case "v": // vertex
{
if (parts.Length < 4) continue;
float x = float.Parse(parts[1], usahax);
float y = float.Parse(parts[2], usahax);
float z = float.Parse(parts[3], usahax);

if (x < bb_min.X || bb_min.X == 0) { bb_min.X = x; }
if (y < bb_min.Y || bb_min.Y == 0) { bb_min.Y = y; }
if (z < bb_min.Z || bb_min.Z == 0) { bb_min.Z = z; }
if (x > bb_max.X || bb_max.X == 0) { bb_max.X = x; }
if (y > bb_max.Y || bb_max.Y == 0) { bb_max.Y = y; }
if (z > bb_max.Z || bb_max.Z == 0) { bb_max.Z = z; }
vertices.Add(new Vector3(x, y, z));
}
break;

case "vt": // texcoord
{

}
break;

case "vn": // normal
{
if (parts.Length < 4) continue;
float x = float.Parse(parts[1], usahax);
float y = float.Parse(parts[2], usahax);
float z = float.Parse(parts[3], usahax);

Normals.Add(new Vector3(x, y, z));

//Vector3 vec = new Vector3(x, y, z);
//vec.Normalize();
//m_Normals.Add(vec);
}
break;

case "f": // face
{
if (parts.Length < 4) continue;
Vector3 u = vertices[int.Parse(parts[1].Split('/')[0]) - 1];
Vector3 v = vertices[int.Parse(parts[2].Split('/')[0]) - 1];
Vector3 w = vertices[int.Parse(parts[3].Split('/')[0]) - 1];

if (parts[1].Split('/').Length == 2)
{
Vector3 n = Normals[int.Parse(parts[1].Split('/')[2]) - 1];
if (norm_sq(Vector3.Cross(v - u, w - u)) < 0.001) { continue; } //#TODO: find a better solution
triangles.Add(new Triangle(u, v, w, n));
Materialu.Add(names.IndexOf(curmaterial));
}
else
{
if (norm_sq(Vector3.Cross(v - u, w - u)) < 0.001) { continue; } //#TODO: find a better solution
triangles.Add(new Triangle(u, v, w));
Materialu.Add(names.IndexOf(curmaterial));
}
}
break;
}
}

sr.Close();
return new object[] { triangles, bb_min, bb_max, names.ToArray(), Materialu.ToArray() };
}
private static float maxcubesize = -1;
private static void write_kcl(string filename, List triangles, Vector3 bb_min, Vector3 bb_max, int max_triangles, int min_width, string[] names, int[] materialu)
{
bb_min -= new Vector3(25f, 25f, 25f);
bb_max += new Vector3(25f, 25f, 25f);
kclType ty = new kclType(names);
ty.DialogResult = System.Windows.Forms.DialogResult.None;
ty.ShowDialog();
while (ty.DialogResult != System.Windows.Forms.DialogResult.OK) ;
Dictionary Mapping;
Dictionary Colli;
Mapping = ty.Mapping;
Colli = ty.Colli;

int n_min = next_exponent(min_width, 2);
int n_x = Math.Max(next_exponent(bb_max.X - bb_min.X, 2), n_min);
int n_y = Math.Max(next_exponent(bb_max.Y - bb_min.Y, 2), n_min);
int n_z = Math.Max(next_exponent(bb_max.Z - bb_min.Z, 2), n_min);
n_x = (int)max(n_x, n_z);
n_z = n_x;
int n = Math.Max((int)min(n_x, n_y, n_z), n_min);

float divs_x = (float)Math.Pow(2, (n_x - n));
float divs_y = (float)Math.Pow(2, (n_y - n));
float divs_z = (float)Math.Pow(2, (n_z - n));
float width = (float)Math.Pow(2, n);
maxcubesize = width;

List octree = new List();
List indices = new List();
int l = 0;
foreach (Triangle t in triangles)
{
if (Colli[names[materialu[l]]])
{
indices.Add(l);
}
l++;
}
for (int k = 0; k < divs_z; k++)
{
for (int j = 0; j < divs_y; j++)
{
for (int i = 0; i < divs_x; i++)
{
bool st;
octree.Add(new OctreeNode(bb_min + width * new Vector3(i, j, k), width, triangles, indices, max_triangles, min_width, out st));
}
}
}

//OctreeNode octree = [OctreeNode(bb_min + width*Vector(i,j,k),width,triangles,xrange(len(triangles)),max_triangles,min_width)
// for k in xrange(divs_z) for j in xrange(divs_y) for i in xrange(divs_x)]

EndianBinaryWriter f = new EndianBinaryWriter(File.Create(filename), Endianness.LittleEndian);

//# header
f.Write((UInt32)0); //# vertex offset placeholder
f.Write((UInt32)0); //# vector offset placeholder
f.Write((UInt32)0); //# triangle offset placeholder
f.Write((UInt32)0); //# octree offset placeholder
f.Write((UInt32)122880); //# unknown
f.Write((Int32)(bb_min.X * 4096)); //# x min
f.Write((Int32)(bb_min.Y * 4096)); //# y min
f.Write((Int32)(bb_min.Z * 4096)); //# z min
f.Write((UInt32)((0xFFFFFFFF << n_x) & 0xFFFFFFFF)); //# x mask
f.Write((UInt32)((0xFFFFFFFF << n_y) & 0xFFFFFFFF)); //# y mask
f.Write((UInt32)((0xFFFFFFFF << n_z) & 0xFFFFFFFF)); //# z mask
f.Write((UInt32)n); //# coordinate shift
f.Write((UInt32)(n_x - n)); //# y shift
f.Write((UInt32)(n_x - n + n_y - n)); //# z shift
f.Write((UInt32)102400); //# unknown

//# vertex section
int pos = (int)f.BaseStream.Position;
f.BaseStream.Position = 0;
f.Write((Int32)pos); //# vertex offset
f.BaseStream.Position = pos;
List Vt = new List();
List Videx = new List();
int ii = 0;
foreach (Triangle t in triangles)
{
if (Colli[names[materialu[ii]]])
{
int d = containsVector3(t.u, Vt);
if (d == -1)
{
Vt.Add(t.u);
Videx.Add(Vt.Count - 1);
}
else
{
Videx.Add(d);
}
}
ii++;
}
foreach (Vector3 c in Vt)
{
f.Write((Int32)(c.X * 4096));
f.Write((Int32)(c.Y * 4096));
f.Write((Int32)(c.Z * 4096));
}

//# vector section
pos = (int)f.BaseStream.Position;
f.BaseStream.Position = 4;
f.Write((Int32)pos); //# vector offset
f.BaseStream.Position = pos;

List Norm = new List();
List Nidex = new List();
ii = 0;
foreach (Triangle t in triangles)
{
if (Colli[names[materialu[ii]]])
{
Vector3 a = -unit(Vector3.Cross(t.w - t.u, t.n));
Vector3 b = unit(Vector3.Cross(t.v - t.u, t.n));
Vector3 c = unit(Vector3.Cross(t.w - t.v, t.n));
int d = containsVector3(t.n, Norm);
if (d == -1)
{
Norm.Add(t.n);
Nidex.Add(Norm.Count - 1);
}
else
{
Nidex.Add(d);
}
d = containsVector3(a, Norm);
if (d == -1)
{
Norm.Add(a);
Nidex.Add(Norm.Count - 1);
}
else
{
Nidex.Add(d);
}
d = containsVector3(b, Norm);
if (d == -1)
{
Norm.Add(b);
Nidex.Add(Norm.Count - 1);
}
else
{
Nidex.Add(d);
}
d = containsVector3(c, Norm);
if (d == -1)
{
Norm.Add(c);
Nidex.Add(Norm.Count - 1);
}
else
{
Nidex.Add(d);
}
}
ii++;
}

foreach (Vector3 c in Norm)
{
f.Write((Int16)(c.X * 4096));
f.Write((Int16)(c.Y * 4096));
f.Write((Int16)(c.Z * 4096));
}

while (f.BaseStream.Position % 4 != 0) { f.Write((Byte)0); }

//# triangle section
pos = (int)f.BaseStream.Position;
f.BaseStream.Position = 8;
f.Write((Int32)(pos - 16)); //# triangle offset
f.BaseStream.Position = pos;
int m = 0;
ii = 0;
foreach (Triangle t in triangles)
{
if (Colli[names[materialu[ii]]])
{
Vector3 c = unit(Vector3.Cross(t.w - t.v, t.n));
f.Write((Int32)(Vector3.Dot(t.w - t.u, c) * 4096)); //# length
f.Write((UInt16)(Videx[m])); //# vertex index
f.Write((UInt16)(Nidex[4 * m])); //# normal index
f.Write((UInt16)(Nidex[4 * m + 1])); //# a index
f.Write((UInt16)(Nidex[4 * m + 2])); //# b index
f.Write((UInt16)(Nidex[4 * m + 3])); //# c index
f.Write(Bytes.StringToByte(string.Format("{0:X4}", Mapping[names[materialu[ii]]])), 0, 2); //# surface type
m++;
}
ii++;
}

//# octree section
pos = (int)f.BaseStream.Position;
f.BaseStream.Position = 12;
f.Write((Int32)pos); //# octree offset
f.BaseStream.Position = pos;
long bas = f.BaseStream.Position;
Queue nodes;
Queue nodeStarts;
OctreeNode current;
Collection dataSection;
int progress, totalNodes;
long freeAddress, startAddress, dataStart;

startAddress = freeAddress = f.BaseStream.Position;
nodes = new Queue();
dataSection = new Collection();
nodeStarts = new Queue();

for (int i = 0; i < octree.Count; i++)
{
nodeStarts.Enqueue(freeAddress);
nodes.Enqueue(octree);
}
freeAddress += octree.Count * 4;
progress = 0;
totalNodes = octree.Count;
while (nodes.Count > 0)
{
current = nodes.Dequeue();

if (current.is_leaf)
{
f.Write(0);
nodeStarts.Dequeue();
}
else
{
f.Write((int)(freeAddress - nodeStarts.Dequeue()));
for (int i = 0; i < current.branches.Count; i++)
{
nodes.Enqueue(current.branches);
nodeStarts.Enqueue(freeAddress);
totalNodes++;
}
freeAddress += 0x20;
}

progress++;
//progressHandler.Invoke(10 + ((45 * progress) / totalNodes), Program.GetString("ProgressWritingOctree"));
}

dataStart = f.BaseStream.Position;
freeAddress = startAddress;
f.BaseStream.Seek(startAddress, SeekOrigin.Begin);
for (int i = 0; i < octree.Count; i++)
{
nodeStarts.Enqueue(freeAddress);
nodes.Enqueue(octree);
}
freeAddress += octree.Count * 4;
progress = 0;

while (nodes.Count > 0)
{
startAddress = f.BaseStream.Position;
current = nodes.Dequeue();

if (current.is_leaf)
{
f.Write((int)(int.MinValue | (f.BaseStream.Length - nodeStarts.Dequeue() - 2)));
f.BaseStream.Seek(0, SeekOrigin.End);
for (int i = 0; i < current.indices.Count; i++)
f.Write((ushort)(current.indices + 1));
f.Write((ushort)0);

for (int i = 0; i < current.indices.Count; i++)
dataSection.Add((ushort)(current.indices + 1));
dataSection.Add(0);

f.BaseStream.Seek(startAddress + 4, SeekOrigin.Begin);
}
else
{
nodeStarts.Dequeue();
f.BaseStream.Seek(4, SeekOrigin.Current);
for (int i = 0; i < current.branches.Count; i++)
{
nodes.Enqueue(current.branches);
nodeStarts.Enqueue(freeAddress);
}
freeAddress += 0x20;
}

progress++;
//progressHandler.Invoke(55 + ((45 * progress) / totalNodes), Program.GetString("ProgressWritingOctree"));
}
f.Close();
}
private static int containsVector3(Vector3 a, List b)
{
for (int i = 0; i < b.Count; i++)
{
if (b.X == a.X && b.Y == a.Y && b.Z == a.Z)
{
return i;
}
}
return -1;
}
private static int next_exponent(float value, int bas)
{
if (value <= 1) { return 0; }
return (int)(Math.Ceiling(Math.Log(value, bas)));
}
public static float norm_sq(Vector3 a)
{
return a.X * a.X + a.Y * a.Y + a.Z * a.Z;
}
public static float norm(Vector3 a)
{
return (float)Math.Sqrt(norm_sq(a));
}
public static Vector3 unit(Vector3 a)
{
Vector3 r = a;
r = Vector3.Divide(r, norm(r));
return r;
}
private class Triangle
{
public Vector3 u;
public Vector3 v;
public Vector3 w;
public Vector3 n;
public Triangle(Vector3 u, Vector3 v, Vector3 w)
{
this.u = u;
this.v = v;
this.w = w;
this.n = unit(Vector3.Cross(v - u, w - u));
}
public Triangle(Vector3 u, Vector3 v, Vector3 w, Vector3 n)
{
this.u = u;
this.v = v;
this.w = w;
this.n = n;
}
}
private class OctreeNode : Cube
{
public bool is_leaf;
public List indices = new List();
public List branches = new List();
public OctreeNode(Vector3 bas, float width, List triangles, List indices, int max_triangles, int min_width, out bool stayd)
{
stayd = false;
//Cube.__init__(self,base,width)
this.hw = width / 2.0f;
this.c = bas + new Vector3(this.hw, this.hw, this.hw);
this.is_leaf = true;
bool stay = false;
bool go = false;
foreach (int i in indices)
{
bool stay2;
bool go2;
if (tricube_overlap(triangles, this, out stay2, out go2)) { this.indices.Add(i); }
if (stay == false && stay2)
{
stay = stay2;
}
if (go == false && go2)
{
go = go2;
}
}
if (stay && this.indices.Count < 64)
{
stayd = true;
return;
}
else if (this.indices.Count >= 64)
{
go = true;
}
if (this.indices.Count > max_triangles && this.hw > min_width/* || this.hw > 32 && this.indices.Count > 0*/ || go && this.hw > min_width)
{
this.is_leaf = false;
for (int k = 0; k < 2; k++)
{
for (int j = 0; j < 2; j++)
{
for (int i = 0; i < 2; i++)
{
bool st;
this.branches.Add(new OctreeNode(bas + this.hw * new Vector3(i, j, k), this.hw, triangles, this.indices, max_triangles, min_width, out st));
if (st)
{
this.is_leaf = true;
foreach (int l in indices)
{
bool stay2;
bool go2;
if (tricube_overlap(triangles, this, out stay2, out go2)) { this.indices.Add(l); }
}
this.branches.Clear();
return;
}
}
}
}
this.indices.Clear();
}
}
}
private class Cube
{
public float hw;
public Vector3 c;
//def __init__(self,base,width):
// self.hw = width/2.0
// self.c = base + Vector(self.hw,self.hw,self.hw)

public bool axis_test(float a1, float a2, float b1, float b2, float c1, float c2, Cube c)
{
float p = a1 * b1 + a2 * b2;
float q = a1 * c1 + a2 * c2;
float r = /*(c.hw + c.hw / 4f)*/c.hw * (Math.Abs(a1) + Math.Abs(a2));
return Math.Min(p, q) > r || Math.Max(p, q) < -r;
}

public bool tricube_overlap(Triangle t, Cube c, out bool stay, out bool go)
{
/*float oldhw = c.hw;
//c.hw += 1;
//c.hw += 10;
stay = false;
go = false;

Vector3 v0 = t.u - c.c;
Vector3 v1 = t.v - c.c;
Vector3 v2 = t.w - c.c;

float hw = c.hw;
c.hw += hw/4f;

if (min(v0.X, v1.X, v2.X) > c.hw || max(v0.X, v1.X, v2.X) < -/*(c.hw + c.hw / 4f)/c.hw) { goto endfalse; }
if (min(v0.Y, v1.Y, v2.Y) > c.hw || max(v0.Y, v1.Y, v2.Y) < -/*(c.hw + c.hw / 4f)/c.hw) { goto endfalse; }
if (min(v0.Z, v1.Z, v2.Z) > c.hw || max(v0.Z, v1.Z, v2.Z) < -/*(c.hw + c.hw / 4f)/c.hw) { goto endfalse; }

/*float d = Vector3.Dot(t.n, v0);
float r = /*(c.hw + c.hw / 4f)/c.hw * (Math.Abs(t.n.X) + Math.Abs(t.n.Y) + Math.Abs(t.n.Z));
if (d > r || d < -r) { goto endfalse; }

Vector3 e = v1 - v0;
if (axis_test(e.Z, -e.Y, v0.Y, v0.Z, v2.Y, v2.Z, c)) { goto endfalse; }
if (axis_test(-e.Z, e.X, v0.X, v0.Z, v2.X, v2.Z, c)) { goto endfalse; }
if (axis_test(e.Y, -e.X, v1.X, v1.Y, v2.X, v2.Y, c)) { goto endfalse; }

e = v2 - v1;
if (axis_test(e.Z, -e.Y, v0.Y, v0.Z, v2.Y, v2.Z, c)) { goto endfalse; }
if (axis_test(-e.Z, e.X, v0.X, v0.Z, v2.X, v2.Z, c)) { goto endfalse; }
if (axis_test(e.Y, -e.X, v0.X, v0.Y, v1.X, v1.Y, c)) { goto endfalse; }

e = v0 - v2;
if (axis_test(e.Z, -e.Y, v0.Y, v0.Z, v1.Y, v1.Z, c)) { goto endfalse; }
if (axis_test(-e.Z, e.X, v0.X, v0.Z, v1.X, v1.Z, c)) { goto endfalse; }
if (axis_test(e.Y, -e.X, v1.X, v1.Y, v2.X, v2.Y, c)) { goto endfalse; }/
c.hw = hw;
if (c.hw < 64)
{
if (v0.Y > (c.hw / 2f) + (c.hw / 4f) || v1.Y > (c.hw / 2f) + (c.hw / 4f) || v2.Y > (c.hw / 2f) + (c.hw / 4f))// || v0.Y < -(c.hw / 2.0f) - (c.hw / 4f) || v1.Y < -(c.hw / 2.0f) - (c.hw / 4f) || v2.Y < -(c.hw / 2.0f) - (c.hw / 4f))
{
stay = true;
//go = true;
}
}
return true;
endfalse:
c.hw = hw;
return false;
}*/
/*stay = false;
System.Windows.Media.Media3D.Rect3D r = new System.Windows.Media.Media3D.Rect3D(c.c.X - c.hw, c.c.Y - c.hw, c.c.Z - c.hw, c.hw, c.hw, c.hw);
if (r.Contains(new System.Windows.Media.Media3D.Point3D(t.u.X, t.u.Y, t.u.Z)) || r.Contains(new System.Windows.Media.Media3D.Point3D(t.v.X, t.v.Y, t.v.Z)) || r.Contains(new System.Windows.Media.Media3D.Point3D(t.w.X, t.w.Y, t.w.Z)))
{
return true;
}
return false;*/
//c.hw += 1;
//c.hw += 10;
stay = false;
go = false;

Vector3 v0 = t.u - c.c;
Vector3 v1 = t.v - c.c;
Vector3 v2 = t.w - c.c;

if (min(v0.X, v1.X, v2.X) > c.hw || max(v0.X, v1.X, v2.X) < -(c.hw + c.hw / 4f)) { return false; }
if (min(v0.Y, v1.Y, v2.Y) > c.hw || max(v0.Y, v1.Y, v2.Y) < -(c.hw + c.hw / 4f)) { return false; }
if (min(v0.Z, v1.Z, v2.Z) > c.hw || max(v0.Z, v1.Z, v2.Z) < -(c.hw + c.hw / 4f)) { return false; }

float d = Vector3.Dot(t.n, v0);
float r = (c.hw + c.hw / 4f) * (Math.Abs(t.n.X) + Math.Abs(t.n.Y) + Math.Abs(t.n.Z));
if (d > r || d < -r) { return false; }

Vector3 e = v1 - v0;
if (axis_test(e.Z, -e.Y, v0.Y, v0.Z, v2.Y, v2.Z, c)) { return false; }
if (axis_test(-e.Z, e.X, v0.X, v0.Z, v2.X, v2.Z, c)) { return false; }
if (axis_test(e.Y, -e.X, v1.X, v1.Y, v2.X, v2.Y, c)) { return false; }

e = v2 - v1;
if (axis_test(e.Z, -e.Y, v0.Y, v0.Z, v2.Y, v2.Z, c)) { return false; }
if (axis_test(-e.Z, e.X, v0.X, v0.Z, v2.X, v2.Z, c)) { return false; }
if (axis_test(e.Y, -e.X, v0.X, v0.Y, v1.X, v1.Y, c)) { return false; }

e = v0 - v2;
if (axis_test(e.Z, -e.Y, v0.Y, v0.Z, v1.Y, v1.Z, c)) { return false; }
if (axis_test(-e.Z, e.X, v0.X, v0.Z, v1.X, v1.Z, c)) { return false; }
if (axis_test(e.Y, -e.X, v1.X, v1.Y, v2.X, v2.Y, c)) { return false; }
if (c.hw < 64)
{
stay = true;
//if (v0.Y > (c.hw / 2f) + (c.hw / 4f) || v1.Y > (c.hw / 2f) + (c.hw / 4f) || v2.Y > (c.hw / 2f) + (c.hw / 4f))// || v0.Y < -(c.hw / 2.0f) - (c.hw / 4f) || v1.Y < -(c.hw / 2.0f) - (c.hw / 4f) || v2.Y < -(c.hw / 2.0f) - (c.hw / 4f))
//{
// stay = true;
// //go = true;
//}
}
return true;
}
}
private static float min(params float[] v)
{
float min = float.MaxValue;
foreach (float f in v)
{
if (f < min)
{
min = f;
}
}
return min;
}
private static float max(params float[] v)
{
float max = float.MinValue;
foreach (float f in v)
{
if (f > max)
{
max = f;
}
}
return max;
}
private static Vector3 MinMax(Vector3 min, Vector3 max, Vector3 input)
{
Vector3 a = input;
if (min.X > a.X)
min.X = a.X;
if (min.Y > a.Y)
min.Y = a.Y;
if (min.Z > a.Z)
min.Z = a.Z;
if (max.X < a.X)
max.X = a.X;
if (max.Y < a.Y)
max.Y = a.Y;
if (max.Z < a.Z)
max.Z = a.Z;
return a;
}
}
}
[/source]

Arisotura
Posted on 11-29-12 06:29 PM Link | #1277
Thanks, that might be useful. Haven't read it in detail though, mostly because reading code inside a 560px wide box when you have a 1920px wide monitor isn't exactly comfortable.

____________________
NSMBHD - Kafuka - Jul
melonDS the most fruity DS emulator there is

zafkflzdasd

Skelux
Posted on 12-03-12 03:09 AM Link | #1321
I think you're right about it being a precision problem. I notice that the lower you round the coordinates, the more of the faulty collision planes will start working.
Helper.RoundVector(ref v, 31f); for example

Arisotura
Posted on 12-03-12 08:28 AM Link | #1329
Good to know. I had made this to round vectors before transforming them to fixed-point so that they'd fit better, but if you say it works better with less rounding, I'll try out. Heck, perhaps we can even completely take rounding out.

____________________
NSMBHD - Kafuka - Jul
melonDS the most fruity DS emulator there is

zafkflzdasd

Gericom
Posted on 12-04-12 12:14 PM (rev. 2 of 12-04-12 12:15 PM) Link | #1402
Why do you round things? Writing fixed point numbers is easy. You can do it like this:
[source=c#]
float number = 1234.5678f;
uint write = (uint)(number * 4096f);
[/source]
I don't know why a 1 bit sign + 19 bit integer + 12 bit fractional part should be a problem...
(I use it very often and I never have problems)

Arisotura
Posted on 12-11-12 11:52 PM Link | #1714
IIRC, the actual problem isn't the coordinates themselves, but rather, the KCL normals that make up the planes.

Normals have even more limited precision than coordinates, because unless I got something wrong, normals aren't 1bit sign + 15bit fractional, which would have been the best format.

Doing the math for finding the normals, and then converting them to fixed point, all while retaining good enough precision, isn't easy. The rounding was an attempt at improving things, which was suggested by Dirbaio.

____________________
NSMBHD - Kafuka - Jul
melonDS the most fruity DS emulator there is

zafkflzdasd

Skelux
Posted on 12-13-12 08:52 AM Link | #1730
What's the main difference between MKDS kcl and SM64 imported kcl? I tried creating a kcl file using MKDS editor and replaced the one which SM64DSE imported, but Mario just fell strait through.

Arisotura
Posted on 12-13-12 04:00 PM Link | #1732
Easy.

Import the same model into SM64DS and MKDS. Export both collision maps. Compare them with a hex editor.

I'd do it but I have other things to do.

____________________
NSMBHD - Kafuka - Jul
melonDS the most fruity DS emulator there is

zafkflzdasd

blank
Posted on 12-13-12 05:57 PM Link | #1737
The main difference is that SM64DS kcl files are LZ77 compressed while MKDS kcl files aren't compressed.

Arisotura
Posted on 12-13-12 06:02 PM Link | #1738
That's true for the original files. Compression isn't required.

____________________
NSMBHD - Kafuka - Jul
melonDS the most fruity DS emulator there is

zafkflzdasd
Pages: 1 2 3 4 5

Main - General SM64DS hacking - Looking into SM64DS fixing collision Hide post layouts | Thread closed

Page rendered in 0.132 seconds. (2048KB of memory used)
MySQL - queries: 27, rows: 237/237, time: 0.018 seconds.
[powered by Acmlm] Acmlmboard 2.064 (2018-07-20)
© 2005-2008 Acmlm, Xkeeper, blackhole89 et al.