Blender: Translate UV-Map on [0,1]²

Ramkhamhaeng

Warlord
Joined
Feb 24, 2014
Messages
209
Hello guys,

I did not use the Blender version 2.49b, but a newer one. So I can not import Nifs directly in blender and I'm using the import/export-options from Nifskope to edit a mesh in Blender and bring it back to Nifskope later.
The tool chain looks like:
Nifskope -> Export as *.obj-file -> Blender -> Export as *3ds-file -> Nifskope

Unfortunately at some stage the UV-Map of my mesh will be changed from [0,1]²-values on [0,1]x[-1,0]. In most cases the change is not visible for the user, but if you apply e.g. a texture-rotation around the its center it made a big difference!

Does anybody know how I could shift the v-coordinate back onto the [0,1]-range? (Editing by hand in Nifskope is no option ;))

Regards
 
Does anybody know how I could shift the v-coordinate back onto the [0,1]-range? (Editing by hand in Nifskope is no option ;))

Regards

You're going through enormous trouble to avoid 2.49b. You could still use newer versions of blender, and only use 2.49b to import/export nifs.

Anyway, I tried your nif/obj/3ds method and got the reversed UV coordinates as well. No clue why that happens, or how it works at all. I didn't know UV coordinates could be "off the grid" so to speak.

The coordinates are normal when I exported as "obj" instead of 3ds. So, you could try that. In both cases it was buggy trying to swap the object into a nif. Said the two versions were incompatible.
 
Thank for your analysis and confirmation.
If I made more stuff I probably will install the old blender version.

For this issue I now wrote a tiny script to change the map in the nif file. For my little feature, it will be good enough.
I add it here just for reference.
Spoiler :

Use the 'file-offset' menu point in Nifskope to get find out the correct offset for your UVMaps.
Code:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Helper script to reset coordinates in UVMap.
# Position of UVMap is hardcoded in this script, but not evaluated!
#
# Dependencies: pip3 install bitstring

import sys
import math
import re

import bitstring as bs

keywords = [b'MyMesh1']  # NiTriStrips node name
NiTriShapeData_NumVertices = NiTriStrips_pos + (19341 - 18535) * 8
NiTriShapeData_UVMap_pos = NiTriStrips_pos + (21310 - 18535) * 8

class WriteDummy:
    # Used if no output file is given.
    def write(self, b):
        pass

    def close(self):
        pass


def update(filename, filename_out=""):
    s = bs.BitStream(filename=filename)

    if len(filename_out) > 0:
        fout = open(filename_out, "wb")
    else:
        fout = WriteDummy()

    n_hits = 0
    for keyword in keywords:
        start = 0
        s.pos = 0
        hit = s.find(keyword, start=start)
        while hit:
            n_hits += 1

            # Read NiTriStrips name
            NiTriStrips_pos = hit[0]

            # 1. Len of UVMap
            # Number of vertices stored in chiled NiTriShapeData.
            # Note that offset of this child node differs. Hard coded offset
            # for my nif-Model
           
            s.pos = NiTriShapeData_NumVertices
            UVMap_len = s.readlist('intle:32')[0]

            # Manual definition
            # UVMap_len = int((21958-21310) / ( 2 * 4 )) # (OffsetNextNode - OffsetUVMap) / 2 * len(float)
            print("Len of UVMap: {}".format(UVMap_len))


            # 2. UVMap
            # Position of first u value of UVMap. (Also hard coded...)
            s.pos = NiTriShapeData_UVMap_pos
            print("Byte-Position of UVMap: {}".format(s.pos/8)) # Ok

            if True:
                # Check position
                uvmap = s.readlist('{}*floatle:32'.format(UVMap_len * 2))
                print("Old values: ")
                print("{}\n{}\n[…]\n{}\n{}".format(uvmap[0:2], uvmap[2:4], uvmap[-4:-2], uvmap[-2:]))

                # Increment v value, if negative
                vmap = uvmap[1::2]
                vmap_inc = [ v if v >= 0.0 else v + 1.0 for v in vmap]
                uvmap[1::2] = vmap_inc

                print("New values:")
                print("{}\n{}\n[…]\n{}\n{}".format(uvmap[0:2], uvmap[2:4], uvmap[-4:-2], uvmap[-2:]))

                # Reset position for write
                s.pos -= 32 * UVMap_len * 2
                print("Pos? {}".format(s.pos/8))  # Ok

                write_keys(s, uvmap, 32)


            # Prepare next loop
            start = s.pos
            hit = s.find(keyword, start=start)


    print("Number of changed uvmaps: {}".format(n_hits))

    # Save result
    try:
        s.tofile(fout)
    finally:
        fout.close()


def write_keys(stream_out, new_values, dist=8*4):
    start_pos = stream_out.pos

    for val in new_values[:1]:
        # print("Write {}".format(val))
        replace_float(stream_out.pos, stream_out, val, True)

    for val in new_values[1:]:
        # print("Write {}".format(val))
        stream_out.pos += dist  # Move to next key position
        replace_float(stream_out.pos, stream_out, val, True)

    stream_out.pos = start_pos


def replace_float(pos_out, stream_out, float_in, reset_pos=False):
    x = bs.Bits(length=32, floatle=float_in)
    replace(pos_out, stream_out, x, reset_pos)


def replace(pos_out, stream_out, bits_in, reset_pos=False):
    if reset_pos:
        backup_pos = stream_out.pos

    stream_out.overwrite(bits_in, pos=pos_out)
    if reset_pos:
        stream_out.pos = backup_pos


if __name__ == "__main__":
    args = dict(zip(range(len(sys.argv)), sys.argv))
    update(args.get(1, ""), args.get(2, ""))
 
The coordinates are normal when I exported as "obj" instead of 3ds. So, you could try that. In both cases it was buggy trying to swap the object into a nif. Said the two versions were incompatible.

I avoid this problem by copy the NiTriShapeData-Node from the blender import into an existing NiTriStripe-Node with proper texturing, etc.
 
You wrote a script to change all the UV coordinates? Damn dude. You know, if you redirected this determination you could do some cool stuff. Like finding a way to automatically set the starting position and rotation of bones in the .kf files.
 
Top Bottom