[[Category RSC]] Work in progress. This page refers to .ob3, a custom format for 3D models created by Jagex. It is used by the RuneScape Classic engine since client version #74. For the earlier version of the format see [[OB2|OB2]].
package jagex.client;

import jagex.Data;

public class OB3Model {

	private static final int num_seq = 0xbc614e;
	public int gouraud_shade[];
	public int vert_count;
	public int vert_x[];
	public int vert_y[];
	public int vert_z[];
	public int face_count;
	public int face_v_count[];
	public int face[][];
	public int face_back[];
	public int face_front[];

	public OB3Model(byte data[], int offset) {
		int vert_count = Data.getUnsignedShort(data, offset);
		offset += 2;
		int face_count = Data.getUnsignedShort(data, offset);
		offset += 2;

		vert_x = new int[vert_count];
		vert_y = new int[vert_count];
		vert_z = new int[vert_count];
		face_v_count = new int[face_count];
		faces = new int[face_count][];
		face_back = new int[face_count];
		face_front = new int[face_count];
		gouraud_shade = new int[face_count];

		for (int v = 0; v < vert_count; v++) {
			vert_x[v] = Data.getSignedShort(data, offset);
			offset += 2;
		}

		for (int v = 0; v < vert_count; v++) {
			vert_y[v] = Data.getSignedShort(data, offset);
			offset += 2;
		}

		for (int v = 0; v < vert_count; v++) {
			vert_z[v] = Data.getSignedShort(data, offset);
			offset += 2;
		}

		this.vert_count = vert_count;
		for (int f = 0; f < face_count; f++)
			face_v_count[f] = (data[offset++] & 0xff);

		for (int f = 0; f < face_count; f++) {
			face_back[f] = Data.getSignedShort(data, offset);
			offset += 2;
			if (face_back[f] == 32767)
				face_back[f] = num_seq;
		}

		for (int f = 0; f < face_count; f++) {
			face_front[f] = Data.getSignedShort(data, offset);
			offset += 2;
			if (face_front[f] == 32767)
				face_front[f] = num_seq;
		}

		for (int f = 0; f < face_count; f++) {
			int i = data[offset++] & 0xff;
			if (i == 0)
				gouraud_shade[f] = 0;
			else
				gouraud_shade[f] = num_seq;
		}

		for (int f = 0; f < face_count; f++) {
			face[f] = new int[face_v_count[f]];
			for (int fv = 0; fv < face_v_count[f]; fv++) {
				if (vert_count < 256) {
					face[f][fv] = data[offset++] & 0xff;
				} else {
					face[f][fv] = Data.getUnsignedShort(data, offset);
					offset += 2;
				}
			}
		}

		this.face_count = face_count;
	}
}
== '''Faces''' == A '''negative''' face_back or face_front value indicates a '''solid colour''', whereas a '''positive''' value indicates a '''texture'''. The texture is defined by its offset in the client's texture array. When converting to/from [http://en.wikipedia.org/wiki/Wavefront_.obj_file Wavefront OBJ] format, remember that the OB3 face values are one less than the OBJ face values.