Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Zervox

Pages: 1 [2] 3
26
battle stage editor sounds really cool, I also like Halfers idea(unless it is already in there somewhere?). :)

27
Just had to donate for this, really awesome work. : )

28
Just going to take a stab guess.
in other games, contact range would be controlling factor for effects or behaviors/eg a fleeing frog in FFIX would run based on rules inside contact range, or lets say object starts floating when in contact range, then 'talk range would be the controlling setting for activating it(capturing frog, activating floating object)

where they can be set depends on how the code was made I guess, init would usually be set after main(as a C/C++ example), this however when in regards to many script implementations seen in other games, init is the first called, then main is called as the primary setter.

regarding Cloud, is it possible that the order of calls to the script is
init - set some values
sets other default values(assuming contact range is set based on parameters, one which could be as you said, model size)
main - rest here to override defaults

I have no clue about any core stuff in Final Fantasy games in this degree, just thinking implementation wise seen in other games which has had source available.
and yes, this sounds like a horrible way to do things, but hey, lots of games has really weird code running around in them.

29
Scripting and Reverse Engineering / Re: [FF9]2016 release
« on: 2016-04-17 13:53:43 »
No one is reversing anything into Unity to my knowledge, FF9 for PC uses Unity,besides I believe Android version uses Unity anyways.

30
Scripting and Reverse Engineering / Re: [FF9]2016 release
« on: 2016-04-17 02:32:42 »
Had a chance to check WMWorld/WMBlock/WMCell/WMReadFile?
I also note that WMPsXCamera could be of use if one wants to figure perfect camera angle themselves ; )

31
Graphical / Re: FF8 3d model modding?
« on: 2015-12-30 11:55:12 »
From what I've seen from deling there really isn't much magic going on. :P
you got the static background image layers. then you got the 'animated' images which is just individual static images of an object that is getting looped over(unless it is deling which converts it to single images).
like the starting infirmary scene, you got the infirmary, then you got the moving curtains as a seperate image with the curtain and the rest of the scene cut by alpha ontop which is looped over.
doors are images which are opened when the character gets to place 'x' in the screen controlled against a bounding box/region(if player is inside of that area the images for the doors gets looped over to open or close respectively).
to recreate the scenes you can either do camera matching perspective to the image while modelling, or you could guestimate the measurement of the room and objects then match the camera afterwards.
NOTE: also to know, every 2d prop in a scene is the same size as the original image it seems so there is no special placement for images like you usually see in games nowadays, so if the scene image is 972x572 every tiny prop image is the same size even if it is just the size of 25x25 in the scene.

32
Releases / Re: [FF8 Patch] Unofficial bad UV texture patch
« on: 2015-08-27 20:30:14 »
Simply amazing. :)

33
I see the mention about its offset by a percentage, is this percentage fixed? eg the same for all of the same object, I am not aware if the shaders in FF8 is the same for all objects, and if its not, is every object textures off with a percentage? or is there only specific type of objects? like GF,Character mesh, world tiles?

I am thinking if the percentage is fixed, each coordinates is padded with additional offset like if you just get the coordinate at 1,1 its actually outside the texture at 0,0 and thus the final coordinate at 256,256 is 255,255 or the reverse occasion, 257 instead of 256.

Edit:
That or I could guess that the shaders might actually just use wrong samplers.
It seems the problem mention here is the same I've found in many cases when it comes to DirectX or GL and the link below actually shows similar/the same problem.
http://gamedev.stackexchange.com/questions/21910/how-to-fix-odd-artifacts-at-the-edges-of-textures-in-directx-11

34
Now I am not sure if this is correct though, but playstation one was integer points only right? could this be caused because PCs would normally use floats for texture coordinates instead of integers? I am thinking specifically about possible inaccuracy of integer to floating point conversion(as I am not read up on the data, but I am asuming they are using pretty much the same files for PC as they do for PSX), not sure how FF8 on PC deals with this conversion.

35
I was curious about a potential bug I found in extracting the faceIndices, is that alot of the faces would be reversed as to what they should be, you find this by using 3ds max render function, the fix I found was that in findFaceIndices, the first (eg offset+0) is actually the resulting z index and x being (+2)

36
I am guessing that there is no lookup data for each block to know beforehand how much data has been encoded because of
Code: [Select]
this.faceIndexOffset = faceIndexOffset;inside block?
which is used later in Controller
Code: [Select]
int vertexIndexOffset = 0;
        int textureIndexOffset = 6;
        for(Iterator iterator = segments.iterator(); iterator.hasNext();)
        {
            Segment segment = (Segment)iterator.next();
            segment.generateBlocks(data, vertexIndexOffset, textureIndexOffset);
            vertexIndexOffset = segment.getFaceIndexOffset();
        }

37
That's totally okay, after all I did say that I will publish the source if anyone wants it. Didn't just do it because I thought I would pull out next version out pretty quickly :P. It's in github though so I can just link it if needed https://github.com/Halferi/wmx2obj  Well there you have it :D, that's the same version as the compiled one though.

Well you can say that from the whole code. I never intended it to be final yet because I knew that I still have to change things for optimization. That also includes the rearranging of functions to easier upgrades in future once the program is "ready". But don't get me wrong, I do really appreciate that you do these optimization checks, also saves time from me :P.

I don't think that there is any limitation to it technically. Problems that may occur though is the performance, but testing that comes later. Each section can hold technically 0x9000 bytes which is 36864 bytes in decimals. The world map currently hardly utilizes this space fully at all, in fact I don't seem to remember any section to take over half of the maximum size.
I also haven't seen any section near that number.
I am a bit curious to the 36864 limit, I am not familiar with any data type which is capped to that range, is this due to a custom size check hardcoded into the segment read code?

38
Yeah.. like many others here do what they do for the same reason.. because they are too lazy to ask Square for source code  :-D :-D :-D

Hah! Made me chuckle.  ;D

39
From what I saw in Blocks generate faces
Code: [Select]
void findTexturePage(byte data[], int offset, int faceIndexOffset, int textureIndexOffset)is only called once
and all the if checks in findTexturePage are checked at once, meaning if one succeds the others won't get added so it is technically only one texture page in Face class active as texturepages always returns 1 in size to me.
Also due to
Code: [Select]
public String getPage()
    {
        return (String)texturepages.get(texturepages.size() - 1);
    }
it still just sends the last created one, which means all other data stored in faces are of no use. or is this just for debugging code and that code will be changed?

at write out I just did in C++ that all the Texture indices that are equal got written out together once per block, this reduced the total size of the file from 80MB to 38.6MB which is quite some savings, it did however add a bit of processing time.

also a change I'd like to suggest is moving findTextureIndices to Block.
considering TextureCoords is only x and y , this way you can get away with Dbl x and Dbl y on textures. although it would write out 3xtextures per fetch, it is however alot easier for writing a code sort for texture coordinates. eg

in Texture
Code: [Select]
public class Texture
{

    public Texture(int id,double X,double Y)
    {
        this.id = id;
        this.X=X;
        this.Y=Y;
    }

    public int getId()
    {
        return id;
    }

    public double getX()
    {
        return X;
    }
   public double getY()
    {
        return Y;
    }

    public int getPage()
    {
        return ((Integer)texturepages.get(texturepages.size() - 1)).intValue();
    }

    public void print()
    {
        System.out.print(texturepages);
    }

    public static final int COORDINATE_BYTES = 1;
    public static final int p = 0;
    private final int id;
    private double X;
    private double Y;
    private final ArrayList texturepages = new ArrayList();
}
in Block
Code: [Select]
public void findTextureIndices(byte data[], int offset)
    {
        textures.add(new Texture(textures.size(),(data[offset + 6] & 0xff) + 0.5D) / 256D,(data[offset + 7] & 0xff) + 0.5D) / 256D)
        textures.add(new Texture(textures.size(),(data[offset + 8] & 0xff) + 0.5D) / 256D,(data[offset + 9] & 0xff) + 0.5D) / 256D)
        textures.add(new Texture(textures.size(),(data[offset + 10] & 0xff) + 0.5D) / 256D,(data[offset + 11] & 0xff) + 0.5D) / 256D)
    }
 public void generateTextures(byte data[], int faceIndexOffset, int textureIndexOffset)
    {
        for(int texture = 0; texture < faceCount; texture++) findTextureIndices(data, offset + texture * 16))
    }


by the way if you are wondering how I got your code changes is because I was too lazy to ask for source and decompiled your code, sorry about that. ;)


also, don't know where I read it, but someone somewhere said there was a limitation to how many faces or vertices can be on each terrain chunk, which I can't really see, a pure water tile uses 512 faces, 400 vertices, but the chunk with balamb town for example uses 790 vertices and 1156 faces, which suggests to me that it should be possible to put more detail onto the FF8 world.

40
For Faces I noticed it really only ever uses one texturePage in the current code(if this is correct)
we should make
Code: [Select]
ArrayList<String> texturepages;
Code: [Select]
String texturepage;and do
Code: [Select]
String getPage(){return texturepage;}replace all
Code: [Select]
texturepages.add("***");with
Code: [Select]
texturepage="***";
Then do a custom compare( I don't know java enough for this)
Code: [Select]
CustomComparator {
    public boolean compare(Face a, Face b) {
        return a.texturepage.before(b.texturepage);
    }
}
Then we can after the loop in GenerateFaces do
Code: [Select]
faces.sort(CustomComparator);

41
Had some fun exporting the mesh from 3ds max to a heightmap ;D


42
Also found in the block structure
Code: [Select]
public void generateFaces(byte[] data, int vertexIndexOffset) {
        // initialize face instances
        for (int face = 0; face < faceCount; face++) {
            addFace(new Face(face));
        }
       
        // find vertex indices of the face instances
        for (Face face : faces) {
            face.findVertexIndices(
                    data,
                    offset + face.getId() * FACE_BYTES,
                    vertexIndexOffset
            );
        }
    }
   
    public void generateVertices(byte[] data, int segmentX, int segmentZ) {
        // initialize vertex instances
        for (int vertex = 0; vertex < vertexCount; vertex++) {
            addVertex(new Vertex(vertex));
        }
       
        // find vertex coordinates of the vertex instances
        for (Vertex vertex : vertices) {
            vertex.findCoordinates(
                    data,
                    offset + faceCount * FACE_BYTES
                            + vertex.getId() * VERTEX_BYTES,
                    offsetX,
                    offsetZ,
                    segmentX,
                    segmentZ
            );
        }
    }
in C++ containers similar to ArrayList in java allows
Code: [Select]
public void generateFaces(byte[] data, int vertexIndexOffset) {
        // find vertex indices of the face instances
        for (int face = 0; face < faceCount; face++) {
            Face ref=faces.add(new Face(face));
            ref.findVertexIndices(
                    data,
                    offset + ref.getId() * FACE_BYTES,
                    vertexIndexOffset
            );
        }
    }
   
    public void generateVertices(byte[] data, int segmentX, int segmentZ) {
        // initialize vertex instances
        // find vertex coordinates of the vertex instances
        for (Vertex vertex : vertices) {
             Vertex ref=vertices.add(new Vertex(vertex));
            ref.findCoordinates(
                    data,
                    offset + faceCount * FACE_BYTES
                            + ref.getId() * VERTEX_BYTES,
                    offsetX,
                    offsetZ,
                    segmentX,
                    segmentZ
            );
        }
    }

Is something like this not possible in Java?
if it is, it would save alot of additional loop complexity.
it would still be possible to just access it straight after inserting it(as add(object) is put into the end) by doing
Code: [Select]
Face ref=faces.get(face);I'd still say the addVertex and addFace amongst other functions
does not need their
Code: [Select]
public void addFace(Face face) {
        if (faces.size() < faceCount) {
            faces.add(face);
        }
    }
   
    public void addVertex(Vertex vertex) {
        if (vertices.size() < vertexCount) {
            vertices.add(vertex);
        }
    }
ArrayList size checks, as the faceCount and vertexCount loop is always the same, meaning these branching if statements are just wasting CPU cycles.

43
Ah, yeah, I expected it would probably be hard to follow due to crappy writing on my part.
Rewrite:

I first suggested doing
Code: [Select]
for loop (segments){
    WriteVertices(segments[i],PrintWriter);
    WriteTextures(segments[i],PrintWriter);
    WriteFaces(segments[i],PrintWriter);
}
doing a loop over segments only once is 835 iterations max, as the range of world chunks is a total of 835 due to the interchangable parts.
the  way it done now is
Code: [Select]
WriteVertices(PrintWriter);
WriteTextures(PrintWriter);
WriteFaces(PrintWriter);
Which loops segments 3 times over(one for each function call), so a total of 2505 loops, since these are seperate, each loop inside a loop adds complexity,
so being able to reduce amount of loops from 3 to 1 on first stage would reduce conversion rate noticably due to code complexity reduction(compiler wise).

I later suggested doing
Code: [Select]
for loop (segments){
   for loop(blocks)
    WriteVertices(blocks[j],PrintWriter);
    WriteTextures(blocks[j],PrintWriter);
    WriteFaces(blocks[j],PrintWriter);
}
Which didn't work as I wanted it to as it would make 3ds max tear the model to pieces(mangled mesh) on import, because the indices etc didn't match the segment.

44
Ok so, tested doing blocks outside then it occured to me the way it is built that obviously you can't preloop blocks because a segment has multiple blocks which needs to be written in correct order else the retriangulate of 3ds max will destroy 90% of the vertices. but doing the segment then passing the looped segment into the write functions still works which would cut down the loops from 2 505 to 835 for the outer segment loop alone also it would reduce the complexity of the code allowing compiled code to execute better.

the texture indices would also help alot in this regard, another thing I found atleast when did the wavefront in C++ as the java version used to much time for impatient me to see, is that materials are written multiple times even within the same segment, so some sort of lookup regarding material type to make each block sort printed faces by material so that instead of

Code: [Select]
usemtl 9
f 390519//1550113 390518//1550114 390524//1550115
usemtl 1
f 390517//1550116 390530//1550117 390499//1550118
f 390491//1550119 390517//1550120 390492//1550121
usemtl 9
f 390523//1550122 390512//1550123 390519//1550124
usemtl 8
f 390516//1550125 390512//1550126 390523//1550127
usemtl 9
f 390521//1550128 390522//1550129 390517//1550130
f 390520//1550131 390521//1550132 390491//1550133
f 390497//1550134 390495//1550135 390521//1550136
f 390506//1550137 390497//1550138 390520//1550139
f 390518//1550140 390520//1550141 390490//1550142
f 390512//1550143 390506//1550144 390518//1550145
usemtl 0
f 390517//1550146 390529//1550147 390532//1550148
usemtl 8
f 390515//1550149 390511//1550150 390516//1550151
f 390514//1550152 390510//1550153 390515//1550154
f 390514//1550155 390508//1550156 390509//1550157
f 390505//1550158 390511//1550159 390510//1550160
f 390503//1550161 390510//1550162 390509//1550163
f 390508//1550164 390503//1550165 390509//1550166
f 390496//1550167 390505//1550168 390503//1550169
usemtl water
f 390502//1550170 390498//1550171 390501//1550172
usemtl 9
f 390490//1550173 390491//1550174 390493//1550175

it would be

Code: [Select]
usemtl 0
f 390517//1550146 390529//1550147 390532//1550148
usemtl 1
f 390517//1550116 390530//1550117 390499//1550118
f 390491//1550119 390517//1550120 390492//1550121
usemtl 8
f 390516//1550125 390512//1550126 390523//1550127
f 390515//1550149 390511//1550150 390516//1550151
f 390514//1550152 390510//1550153 390515//1550154
f 390514//1550155 390508//1550156 390509//1550157
f 390505//1550158 390511//1550159 390510//1550160
f 390503//1550161 390510//1550162 390509//1550163
f 390508//1550164 390503//1550165 390509//1550166
f 390496//1550167 390505//1550168 390503//1550169
usemtl 9
f 390519//1550113 390518//1550114 390524//1550115
f 390523//1550122 390512//1550123 390519//1550124
f 390521//1550128 390522//1550129 390517//1550130
f 390520//1550131 390521//1550132 390491//1550133
f 390497//1550134 390495//1550135 390521//1550136
f 390506//1550137 390497//1550138 390520//1550139
f 390518//1550140 390520//1550141 390490//1550142
f 390512//1550143 390506//1550144 390518//1550145
f 390490//1550173 390491//1550174 390493//1550175
usemtl water
f 390502//1550170 390498//1550171 390501//1550172

Hope I am not butting in on too much for you Halfer. ;)

45
My code already names the segments in the obj file with corresponding integer id,so that 3ds max will import them as seperate mesh parts.
regarding saving an area to separate .obj files, it probably isn't a good idea, already with segments alone they make about 1 part per area, meaning a total number of 835 .obj files.

Also I think we should do

Code: [Select]
iterate segments {
Segment seg = segmentiterator;
write("g "+seg.getID())
iterate  blocks(j, seg.getBlocks()) {
               Blocks b = blockiterator;
                writeVertices(b, printWriter);
                writeTextures(b, printWriter);
                writeFaces(b, printWriter);
to save some processing time removing uneeded for loops, I noticed atleast for me that the textured version takes FOREVER to finish, reducing the amount of loops would probably help alot.

46
Code: [Select]
public void exportFile(File file) throws IOException {
    PrintWriter printWriter = new PrintWriter(file);
    printWriter.println("# Converted to Wavefront .obj with wmx2obj");
    printWriter.println("# wmx2obj \u00A9 2015 Aleksanteri Hirvonen");
    printWriter.println();
for (Segment segment : segments) {
printWriter.println("g " + segment.getID());
writeVertices(segment,printWriter);
writeFaces(segment,printWriter);
}
    printWriter.close();
}

private void writeVertices(Segment segment,PrintWriter printWriter) {
    // take the coordinate values of each vertex instance
    // and write to file
    printWriter.println("# List of geometric vertices");
       
    for (Block block : segment.getBlocks()) {
        for (Vertex vertex : block.getVertices()) {
            printWriter.println(
                    "v "
                    + vertex.getCoordinate(Vertex.X) + " "
                    + -vertex.getCoordinate(Vertex.Y) + " "
                    + -vertex.getCoordinate(Vertex.Z)
            );
        }
    }
    printWriter.println();
}

private void writeFaces(Segment segment,PrintWriter printWriter) {
    // take the vertex index values of each face instance
    // and write to file
    printWriter.println("# Polygonal face elements");
    for (Block block : segment.getBlocks()) {
        for (Face face : block.getFaces()) {
            printWriter.print("f ");
            for (Integer vertexIndex : face.getVertexIndices()) {
                printWriter.print(vertexIndex + " ");
            }
            printWriter.println();
        }
    }
}

I added this code for exporting  each segment as a separate wavefront part hope it would please someone.
not sure about javascript and how I am passing the segments as I converted my code from C++

47

a0stg001.x  Whinhill Village? 


if I am not mistaken that is the bridge in dollet connecting to the communication mountain.

48
Graphical / Re: [WIP] Hojo Lifeform
« on: 2015-03-26 04:55:10 »
Like the model, Just thought I'd pop in a suggestion, the 10k poly limits is this due to using auto mesh pruners(decimators) or retopologizing manually? I found 3D Coat a supreme tool for manually retopologizing meshes(Actually not half bad going low poly to higher poly either just to get the base shape the same) allowing you to get really good detail and low poly at decent speed(the retopology tools are quick to learn and easy to use).

49
Glad it worked. It's nice when the problem is something really simple(unless one has spent alot of time debugging just to find it was way too simple).
That last screenshot made me dizzy for some reason, think its because of the shape, :)

50
0.3333f and 0.3f differs 0.3f=0.3000f
f = floating point eg a decimal variable.
0.3333 would be a double precision decimal variable.

Pages: 1 [2] 3